blob: 66cce468eacc9962a45ff5e59e67eeef9e08311c [file] [log] [blame]
package tests_test
import (
"context"
"io/ioutil"
"os"
"strings"
"testing"
"time"
"google3/third_party/golang/github_com/bramvdbogaerde/go_scp/v/v1/auth/auth"
"google3/third_party/golang/github_com/bramvdbogaerde/go_scp/v/v1/scp"
"google3/third_party/golang/go_crypto/ssh/ssh"
)
func establishConnection(t *testing.T) scp.Client {
// Use SSH key authentication from the auth package.
// During testing we ignore the host key, don't to that when you use this.
clientConfig, _ := auth.PasswordKey("bram", "test", ssh.InsecureIgnoreHostKey())
// Create a new SCP client.
client := scp.NewClient("127.0.0.1:2244", &clientConfig)
// Connect to the remote server.
err := client.Connect()
if err != nil {
t.Fatalf("Couldn't establish a connection to the remote server: %s", err)
}
return client
}
// TestCopy tests the basic functionality of copying a file to the remote
// destination.
//
// It assumes that a Docker container is running an SSH server at port 2244
// that is using password authentication. It also assumes that the directory
// /data is writable within that container and is mapped to ./tmp/ within the
// directory the test is run from.
func TestCopy(t *testing.T) {
client := establishConnection(t)
defer client.Close()
// Open a file we can transfer to the remote container.
f, _ := os.Open("./data/upload_file.txt")
defer f.Close()
// Create a file name with exotic characters and spaces in them.
// If this test works for this, simpler files should not be a problem.
filename := "Exöt1ç uploaded file.txt"
// Finaly, copy the file over.
// Usage: CopyFile(fileReader, remotePath, permission).
err := client.CopyFile(context.Background(), f, "/data/"+filename, "0777")
if err != nil {
t.Errorf("Error while copying file: %s", err)
}
// Read what the receiver have written to disk.
content, err := ioutil.ReadFile("./tmp/" + filename)
if err != nil {
t.Errorf("Result file could not be read: %s", err)
}
text := string(content)
expected := "It Works\n"
if strings.Compare(text, expected) != 0 {
t.Errorf("Got different text than expected, expected %q got, %q", expected, text)
}
}
// TestDownloadFile tests the basic functionality of copying a file from the
// remote destination.
//
// It assumes that a Docker container is running an SSH server at port 2244
// that is using password authentication. It also assumes that the directory
// /data is writable within that container and is mapped to ./tmp/ within the
// directory the test is run from.
func TestDownloadFile(t *testing.T) {
client := establishConnection(t)
defer client.Close()
// Open a file we can transfer to the remote container.
f, _ := os.Open("./data/input.txt")
defer f.Close()
// Create a local file to write to.
f, err := os.OpenFile("./tmp/output.txt", os.O_RDWR|os.O_CREATE, 0777)
if err != nil {
t.Errorf("Couldn't open the output file")
}
defer f.Close()
// Use a file name with exotic characters and spaces in them.
// If this test works for this, simpler files should not be a problem.
err = client.CopyFromRemote(context.Background(), f, "/input/Exöt1ç download file.txt.txt")
if err != nil {
t.Errorf("Copy failed from remote: %s", err.Error())
}
content, err := ioutil.ReadFile("./tmp/output.txt")
if err != nil {
t.Errorf("Result file could not be read: %s", err)
}
text := string(content)
expected := "It works for download!\n"
if strings.Compare(text, expected) != 0 {
t.Errorf("Got different text than expected, expected %q got, %q", expected, text)
}
}
// TestTimeoutDownload tests that a timeout error is produced if the file is not copied in the given
// amount of time.
func TestTimeoutDownload(t *testing.T) {
client := establishConnection(t)
defer client.Close()
client.Timeout = 1 * time.Millisecond
// Open a file we can transfer to the remote container.
f, _ := os.Open("./data/upload_file.txt")
defer f.Close()
// Create a file name with exotic characters and spaces in them.
// If this test works for this, simpler files should not be a problem.
filename := "Exöt1ç uploaded file.txt"
err := client.CopyFile(context.Background(), f, "/data/"+filename, "0777")
if err != context.DeadlineExceeded {
t.Errorf("Expected a timeout error but got succeeded without error")
}
}
// TestContextCancelDownload tests that a a copy is immediately cancelled if we call context.cancel()
func TestContextCancelDownload(t *testing.T) {
client := establishConnection(t)
defer client.Close()
ctx, cancel := context.WithCancel(context.Background())
cancel()
// Open a file we can transfer to the remote container.
f, _ := os.Open("./data/upload_file.txt")
defer f.Close()
// Create a file name with exotic characters and spaces in them.
// If this test works for this, simpler files should not be a problem.
filename := "Exöt1ç uploaded file.txt"
err := client.CopyFile(ctx, f, "/data/"+filename, "0777")
if err != context.Canceled {
t.Errorf("Expected a canceled error but transfer succeeded without error")
}
}
func TestDownloadBadLocalFilePermissions(t *testing.T) {
client := establishConnection(t)
defer client.Close()
// Create a file with local bad permissions
// This happens only on Linux
f, err := os.OpenFile("./tmp/output_bdf.txt", os.O_CREATE, 0644)
if err != nil {
t.Error("Couldn't open the output file", err.Error())
}
defer f.Close()
// This should not timeout and throw an error
err = client.CopyFromRemote(context.Background(), f, "/input/Exöt1ç download file.txt.txt")
if err == nil {
t.Errorf("Expected error thrown. Got nil")
}
}
func TestFileNotFound(t *testing.T) {
client := establishConnection(t)
defer client.Close()
f, err := os.OpenFile("./tmp/output_fnf.txt", os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
t.Error("Couldn't open the output file", err.Error())
}
// This should throw file not found on remote
err = client.CopyFromRemote(context.Background(), f, "/input/no_such_file.txt")
if err == nil {
t.Errorf("Expected error thrown. Got nil")
}
expected := "scp: /input/no_such_file.txt: No such file or directory\n"
if err.Error() != expected {
t.Errorf("Expected %v, got %v", expected, err.Error())
}
}