func TestErrorMetadata(t *testing.T) { var checkParseErr = func(path string, expErr string) { sc := scanner.Scanner{ Position: scanner.Position{ Filename: path, }, } f, err := util.Open(path) if err != nil { t.Errorf("Couldn't open %s", path) } _, err = parse(*sc.Init(f)) if err.Error() != expErr { t.Errorf("Expected \"%s\"\ngot \"%s\"", expErr, err) return } } var checkEvalErr = func(path string, expErr string) { sc := scanner.Scanner{ Position: scanner.Position{ Filename: path, }, } f, err := util.Open(path) if err != nil { t.Errorf("Couldn't open %s", path) } parsed, err := parse(*sc.Init(f)) if err != nil { t.Errorf("Unexpected parse error: %s", parsed) } _, _, err = eval(astRoot(parsed)) if err.Error() != expErr { t.Errorf("Expected \"%s\"\ngot \"%s\"", expErr, err) return } } util.AppFs = afero.NewMemMapFs() util.WriteFile("paren.spec", []byte(` // This is a comment. (define Test "abc"`), 0644) checkParseErr("paren.spec", "paren.spec:3: unbalanced Parenthesis") util.WriteFile("undefined.spec", []byte(` (+ 1 b)`), 0644) checkEvalErr("undefined.spec", "undefined.spec:2: unassigned variable: b") util.WriteFile("bad_type.spec", []byte(` (define a "1") (+ 1 a)`), 0644) checkEvalErr("bad_type.spec", `bad_type.spec:3: bad arithmetic argument: "1"`) // Test that functions which evaluate generated S-expressions still have proper // error messages. util.WriteFile("generated_sexp.spec", []byte(`(apply + (list 1 "1"))`), 0644) checkEvalErr("generated_sexp.spec", `generated_sexp.spec:1: bad arithmetic argument: "1"`) }
func TestPromptsUser(t *testing.T) { oldConfirm := confirm defer func() { confirm = oldConfirm }() util.AppFs = afero.NewMemMapFs() for _, confirmResp := range []bool{true, false} { confirm = func(in io.Reader, prompt string) (bool, error) { return confirmResp, nil } mockGetter := new(testutils.Getter) c := &clientMock.Client{ ClusterReturn: []db.Cluster{ { Spec: `{"old":"spec"}`, }, }, } mockGetter.On("Client", mock.Anything).Return(c, nil) util.WriteFile("test.js", []byte(""), 0644) runCmd := NewRunCommand() runCmd.clientGetter = mockGetter runCmd.stitch = "test.js" runCmd.Run() assert.Equal(t, confirmResp, c.DeployArg != "") } }
func testCheckSpec(t *testing.T) { initVCSFunc() os.Setenv("QUILT_PATH", ".") util.AppFs = afero.NewMemMapFs() util.AppFs.Mkdir("test", 777) util.WriteFile("test/noDownload.spec", []byte(`(import "nextimport/nextimport")`), 0644) util.AppFs.Mkdir("nextimport", 777) util.WriteFile("nextimport/nextimport.spec", []byte("(define dummy 1)"), 0644) if err := checkSpec("test/noDownload.spec", nil, nil); err != nil { t.Error(err) } if len(created) != 0 { t.Errorf("should not have downloaded, but downloaded %s", created) } // Verify that call is made to GetSpec util.WriteFile("test/toDownload.spec", []byte(`(import "github.com/NetSys/quilt/specs/example")`), 0644) expected := "unable to open import github.com/NetSys/quilt/specs/example" if err := checkSpec("test/toDownload.spec", nil, nil); err.Error() != expected { t.Errorf("expected %s \n but got %s", expected, err.Error()) } if len(created) == 0 { t.Error("did not download dependency!") } expected = "github.com/NetSys/quilt" if created[0] != expected { t.Errorf("expected to download %s \n but got %s", expected, created[0]) } }
func TestAutoDownload(t *testing.T) { util.AppFs = afero.NewMemMapFs() repoName := "autodownload" importPath := filepath.Join(repoName, "foo") util.WriteFile("test.js", []byte(fmt.Sprintf("require(%q);", importPath)), 0644) logger := newRepoLogger() getter := ImportGetter{ Path: ".", repoFactory: logger.newRepoFactory(nil), } expErr := "StitchError: unable to open import autodownload/foo: no loadable file" err := getter.checkSpec("test.js", nil, nil) if err == nil || err.Error() != expErr { t.Errorf("Wrong error, expected %q, got %v", expErr, err) return } assert.Equal(t, map[string][]string{ importPath: {repoName}, }, logger.created, "Should autodownload the repo") assert.Empty(t, logger.updated, "Shouldn't update any repos") }
func Test_filesystemCredentialStore_GetCredentials_SavedCredentialsAreValid_CredentialsAreReturned(t *testing.T) { // arrange fs := afero.NewMemMapFs() credentialFilePath := "/home/user/.dee/credentials.json" // create the initial file f1, _ := fs.Create(credentialFilePath) f1.WriteString(`{"Email":"*****@*****.**","Token":"123456"}`) f1.Close() credentialStore := filesystemCredentialStore{fs, credentialFilePath} // act credentials, err := credentialStore.GetCredentials() // assert if err != nil { t.Fail() t.Logf("GetCredentials returned an error: %s", err.Error()) } if credentials.Email != "*****@*****.**" || credentials.Token != "123456" { t.Fail() t.Logf("GetCredentials did not return the correct credentials. Email: %q, Token: %q", credentials.Email, credentials.Token) } }
func TestCmdExec(t *testing.T) { appFs = afero.NewMemMapFs() outputPath := "output.log" log = logger{ cmdLogger: fileLogger(outputPath), } expStdout := "standard out" expStderr := "standard error" cmd := exec.Command("sh", "-c", fmt.Sprintf("echo %s ; echo %s 1>&2", expStdout, expStderr)) stdout, stderr, err := execCmd(cmd, "PREFIX") if err != nil { t.Errorf("Unexpected error: %s", err.Error()) return } if stdout != expStdout { t.Errorf("Stdout didn't match: expected %s, got %s", expStdout, stdout) } if stderr != expStderr { t.Errorf("Stderr didn't match: expected %s, got %s", expStderr, stderr) } }
func TestUpdateNamespace(t *testing.T) { appFs = afero.NewMemMapFs() specPath := "/test.spec" err := overwrite(specPath, `require("spark"); var deployment = createDeployment({namespace: "replace"}); deployment.deploy(new Machine({}));`) if err != nil { t.Errorf("Unexpected error: %s", err.Error()) } updateNamespace(specPath, "test-namespace") res, err := fileContents(specPath) exp := `require("spark"); var deployment = createDeployment({namespace: "replace"}); deployment.deploy(new Machine({}));; deployment.namespace = "test-namespace";` if err != nil { t.Errorf("Unexpected error: %s", err.Error()) return } if res != exp { t.Errorf("Namespace didn't properly update, expected %s, got %s", exp, res) } }
func TestDefaultKeys(t *testing.T) { util.AppFs = afero.NewMemMapFs() // Don't pull in keys from the host OS. Setting this environment variable // is safe because it won't affect the parent shell. os.Setenv("SSH_AUTH_SOCK", "") dir, err := homedir.Dir() if err != nil { t.Errorf("Failed to get homedir: %q", err.Error()) return } sshDir := filepath.Join(dir, ".ssh") if err := util.AppFs.MkdirAll(sshDir, 0600); err != nil { t.Errorf("Failed to create SSH directory: %q", err.Error()) return } for _, key := range []string{"id_rsa", "id_dsa", "ignored"} { if err := writeRandomKey(filepath.Join(sshDir, key)); err != nil { t.Errorf("Failed to write key: %q", err.Error()) return } } signers := defaultSigners() if len(signers) != 2 { t.Errorf("Expected two default signers, but got %v", signers) } }
func TestCompileAndRun(t *testing.T) { var testProgram = "/$/ {}\n" store := metrics.NewStore() lines := make(chan string) w := watcher.NewFakeWatcher() fs := afero.NewMemMapFs() o := LoaderOptions{store, lines, w, fs, false, false, true} l, err := NewLoader(o) if err != nil { t.Fatalf("couldn't create loader: %s", err) } if err := l.CompileAndRun("Test", strings.NewReader(testProgram)); err != nil { t.Errorf("CompileAndRun returned error: %s", err) } l.handleMu.Lock() if len(l.handles) < 1 { t.Errorf("no vm handles: %v", l.handles) } l.handleMu.Unlock() l.handleMu.Lock() c := l.handles["Test"].done if c == nil { t.Errorf("No done channel in handles: %v", l.handles) } l.handleMu.Unlock() close(lines) <-c { l.handleMu.Lock() defer l.handleMu.Unlock() if len(l.handles) != 0 { t.Errorf("some vm handles: %v", l.handles) } } }
func TestMain(t *testing.T) { util.AppFs = afero.NewMemMapFs() util.WriteFile("test.js", []byte(testStitch), 0644) exitCode := Main([]string{"test.js", "graphviz"}) assert.Zero(t, exitCode) res, err := util.ReadFile("test.dot") assert.Nil(t, err) assert.True(t, isGraphEqual(expGraph, res)) }
func makeTestTail(t *testing.T) (*Tailer, chan string, *watcher.FakeWatcher, afero.Fs) { fs := afero.NewMemMapFs() w := watcher.NewFakeWatcher() lines := make(chan string, 1) o := Options{lines, w, fs} ta, err := New(o) if err != nil { t.Fatal(err) } return ta, lines, w, fs }
func TestSyncKeysError(t *testing.T) { util.AppFs = afero.NewMemMapFs() conn := db.New() err := runOnce(conn) assert.EqualError(t, err, "no self minion") fs := afero.NewMemMapFs() util.AppFs = afero.NewReadOnlyFs(fs) conn.Transact(func(view db.Database) error { m := view.InsertMinion() m.Self = true m.AuthorizedKeys = "keys" view.Commit(m) return nil }) err = runOnce(conn) assert.EqualError(t, err, "open /home/quilt/.ssh/authorized_keys: "+ "file does not exist") fs.Create(authorizedKeysFile) err = runOnce(conn) assert.EqualError(t, err, "operation not permitted") }
func Test_filesystemCredentialStore_SaveCredentials_CredentialsAreValid_NoErrorIsReturned(t *testing.T) { // arrange fs := afero.NewMemMapFs() credentialFilePath := "/home/user/.dee/credentials.json" credentialStore := filesystemCredentialStore{fs, credentialFilePath} // act err := credentialStore.SaveCredentials(deens.APICredentials{"*****@*****.**", "123456"}) // assert if err != nil { t.Fail() t.Logf("SaveCredentials should not return an error (%q)", err.Error()) } }
func Test_filesystemCredentialStore_WithoutSourceFile_DeleteCredentials_credentialsNotFoundErrorIsReturned(t *testing.T) { // arrange fs := afero.NewMemMapFs() credentialFilePath := "/home/user/.dee/credentials.json" credentialStore := filesystemCredentialStore{fs, credentialFilePath} // act err := credentialStore.DeleteCredentials() // assert if !isNoCredentialsError(err) { t.Fail() t.Logf("DeleteCredentials should return a noCredentials-error if the credential store has no source file.") } }
func TestSyncKeys(t *testing.T) { tests := []keyTest{ { dbKeys: "key1\nkey2", expKeyFile: "key1\nkey2", }, { dbKeys: "key1\nkey2", keyFile: "key1", expKeyFile: "key1\nkey2", }, { dbKeys: "key1\nkey2", keyFile: "key1\nkey2", expKeyFile: "key1\nkey2", }, { keyFile: "key1\nkey2", expKeyFile: "", }, } for _, test := range tests { util.AppFs = afero.NewMemMapFs() if test.keyFile != "" { err := util.WriteFile( authorizedKeysFile, []byte(test.keyFile), 0644) assert.NoError(t, err) } conn := db.New() conn.Transact(func(view db.Database) error { m := view.InsertMinion() m.Self = true m.AuthorizedKeys = test.dbKeys view.Commit(m) return nil }) err := runOnce(conn) assert.NoError(t, err) actual, err := util.ReadFile(authorizedKeysFile) assert.NoError(t, err) assert.Equal(t, test.expKeyFile, actual) } }
func Test_filesystemCredentialStore_WithoutFilePath_SaveCredentials_ErrorIsReturned(t *testing.T) { // arrange filesystem := afero.NewMemMapFs() credentialStore := filesystemCredentialStore{ fs: filesystem, } // act err := credentialStore.SaveCredentials(deens.APICredentials{"*****@*****.**", "123456"}) // assert if err == nil { t.Fail() t.Logf("SaveCredentials should return an error if the credential store file path configured.") } }
func Test_filesystemCredentialStore_SaveCredentials_CredentialsAreValid_JSONIsWrittenToFile(t *testing.T) { // arrange fs := afero.NewMemMapFs() credentialFilePath := "/home/user/.dee/credentials.json" credentialStore := filesystemCredentialStore{fs, credentialFilePath} // act credentialStore.SaveCredentials(deens.APICredentials{"*****@*****.**", "123456"}) // assert expectedResult := `{"Email":"*****@*****.**","Token":"123456"}` content, _ := afero.ReadFile(fs, credentialFilePath) if string(content) != expectedResult { t.Fail() t.Logf("SaveCredentials should have written the credentials as JSON to %q. Expected: %q, Actual: %q", credentialFilePath, expectedResult, string(content)) } }
func TestImportExists(t *testing.T) { util.AppFs = afero.NewMemMapFs() util.WriteFile("test.js", []byte(`require("existingImport")`), 0644) util.WriteFile("existingImport.js", []byte(""), 0644) logger := newRepoLogger() getter := ImportGetter{ Path: ".", repoFactory: logger.newRepoFactory(nil), } if err := getter.checkSpec("test.js", nil, nil); err != nil { t.Error(err) return } assert.Empty(t, logger.created, "Shouldn't create any repos") assert.Empty(t, logger.updated, "Shouldn't update any repos") }
func TestGetWalk(t *testing.T) { util.AppFs = afero.NewMemMapFs() quiltPath := "getspecs" repoOne := "repoOne" importOne := filepath.Join(repoOne, "file") repoTwo := "anotherRepo" fileTwo := "importTwo" importTwo := filepath.Join(repoTwo, fileTwo) logger := newRepoLogger() getter := ImportGetter{ Path: quiltPath, repoFactory: logger.newRepoFactory(map[string][]file{ importOne: { { name: "foo.js", contents: fmt.Sprintf("require(%q);", importTwo), }, }, importTwo: { { name: fmt.Sprintf("%s.js", fileTwo), }, }, }), } if err := getter.Get(importOne); err != nil { t.Error(err) return } assert.Equal(t, map[string][]string{ importOne: {filepath.Join(quiltPath, repoOne)}, importTwo: {filepath.Join(quiltPath, repoTwo)}, }, logger.created, "Should autodownload the imported repo") assert.Empty(t, logger.updated, "Shouldn't update any repos") }
// getFileWithContent returns an afero.File with the given name and content. func getFileWithContent(name, content string) (afero.File, error) { fs := afero.NewMemMapFs() fs.MkdirAll(path.Base(name), 0755) f, createFileError := fs.OpenFile(name, os.O_CREATE|os.O_RDWR, 0744) if createFileError != nil { return nil, createFileError } _, writeError := f.WriteString(content) if writeError != nil { return nil, writeError } f.Close() f2, openFileError := fs.OpenFile(name, os.O_CREATE|os.O_RDWR, 0744) if openFileError != nil { return nil, openFileError } return f2, nil }
func Test_filesystemCredentialStore_SourceFileExists_DeleteCredentials_NoErrorIsReturned(t *testing.T) { // arrange fs := afero.NewMemMapFs() credentialFilePath := "/home/user/.dee/credentials.json" // create the initial file f1, _ := fs.Create(credentialFilePath) f1.WriteString("Some content") credentialStore := filesystemCredentialStore{fs, credentialFilePath} // act err := credentialStore.DeleteCredentials() // assert if err != nil { t.Fail() t.Logf("DeleteCredentials should not return an error if the credential file exists and was successfully deleted.") } }
func Test_filesystemCredentialStore_GetCredentials_SavedCredentialsAreEmpty_ErrorIsReturned(t *testing.T) { // arrange fs := afero.NewMemMapFs() credentialFilePath := "/home/user/.dee/credentials.json" // create the initial file f1, _ := fs.Create(credentialFilePath) f1.WriteString(``) f1.Close() credentialStore := filesystemCredentialStore{fs, credentialFilePath} // act _, err := credentialStore.GetCredentials() // assert if err == nil { t.Fail() t.Logf("GetCredentials should return an error if the given file is empty.") } }
func Test_filesystemCredentialStore_GetCredentials_JSONIsInvalid_ErrorIsReturned(t *testing.T) { // arrange fs := afero.NewMemMapFs() credentialFilePath := "/home/user/.dee/credentials.json" // create the initial file f1, _ := fs.Create(credentialFilePath) f1.WriteString("dsakldjasl ---") f1.Close() credentialStore := filesystemCredentialStore{fs, credentialFilePath} // act _, err := credentialStore.GetCredentials() // assert if err == nil { t.Fail() t.Logf("GetCredentials should return an error if the given file content is invalid.") } }
func TestGetCreate(t *testing.T) { util.AppFs = afero.NewMemMapFs() quiltPath := "./getspecs" repoName := "github.com/NetSys/quilt" importPath := filepath.Join(repoName, "foo") logger := newRepoLogger() getter := ImportGetter{ Path: quiltPath, repoFactory: logger.newRepoFactory(nil), } if err := getter.Get(importPath); err != nil { t.Error(err) return } assert.Equal(t, map[string][]string{ importPath: {filepath.Join(quiltPath, repoName)}, }, logger.created, "Should download the repo") assert.Empty(t, logger.updated, "Shouldn't update any repos") }
func Test_filesystemCredentialStore_SourceFileExists_DeleteCredentials_FileIsDeleted(t *testing.T) { // arrange fs := afero.NewMemMapFs() credentialFilePath := "/home/user/.dee/credentials.json" // create the initial file f1, _ := fs.Create(credentialFilePath) f1.WriteString("Some content") credentialStore := filesystemCredentialStore{fs, credentialFilePath} // act credentialStore.DeleteCredentials() // assert fileInfo, _ := fs.Stat(credentialFilePath) fileExists := fileInfo != nil if fileExists { t.Fail() t.Logf("The file %q should be deleted after DeleteCredentials is executed.", credentialFilePath) } }
// Integration test. func Test_loginAction_ValidArguments_CredentialFileIsCreated(t *testing.T) { // arrange filesystem := afero.NewMemMapFs() credentialStore := newFilesystemCredentialStore(filesystem, "/home/testuser/.dee/credentials.json") arguments := []string{ "-email", "*****@*****.**", "-apitoken", "123456", } login := loginAction{credentialStore} // act login.Execute(arguments) // assert fileInfo, err := filesystem.Stat("/home/testuser/.dee/credentials.json") if fileInfo == nil || err != nil { t.Fail() t.Logf("login.Execute(%q) create the credential file and should not return an error: %s", arguments, err.Error()) } }
// Due to limitations with git and afero, GetSpec will error at resolveSpecImports. // Instead, resolveSpecImports is covered above. func TestGetSpec(t *testing.T) { initVCSFunc() util.AppFs = afero.NewMemMapFs() util.AppFs.Mkdir("getspecs", 777) os.Setenv("QUILT_PATH", "./getspecs") importPath := "github.com/NetSys/quilt" // Clone if _, err := getSpec(importPath); err != nil { t.Error(err) } if len(created) == 0 { t.Errorf("did not download dependency %s", importPath) } expected := "getspecs/github.com/NetSys/quilt" if created[0] != expected { t.Errorf("expected to download %s \n but got %s", expected, created[0]) } fmt.Println(created) util.AppFs.Mkdir("getspecs/github.com/NetSys/quilt", 777) // Update if _, err := getSpec(importPath); err != nil { t.Error(err) } if len(updated) == 0 { t.Errorf("did not update dependency %s", importPath) } expected = "getspecs/github.com/NetSys/quilt" if updated[0] != expected { t.Errorf("expected to update %s \n but got %s", expected, updated[0]) } }
func Test_filesystemCredentialStore_SaveCredentials_FileExists_FileIsOverridden(t *testing.T) { // arrange fs := afero.NewMemMapFs() credentialFilePath := "/home/user/.dee/credentials.json" // create the initial file f1, _ := fs.Create(credentialFilePath) f1.WriteString(`{"Email":"*****@*****.**","Token":"543"}`) f1.Close() credentialStore := filesystemCredentialStore{fs, credentialFilePath} // act credentialStore.SaveCredentials(deens.APICredentials{"*****@*****.**", "123456"}) // assert expectedResult := `{"Email":"*****@*****.**","Token":"123456"}` content, _ := afero.ReadFile(fs, credentialFilePath) if string(content) != expectedResult { t.Fail() t.Logf("SaveCredentials should have written the credentials as JSON to %q. Expected: %q, Actual: %q", credentialFilePath, expectedResult, string(content)) } }
func TestNewLoader(t *testing.T) { w := watcher.NewFakeWatcher() store := metrics.NewStore() inLines := make(chan string) fs := afero.NewMemMapFs() o := LoaderOptions{store, inLines, w, fs, false, false, true} l, err := NewLoader(o) if err != nil { t.Fatalf("couldn't create loader: %s", err) } done := make(chan struct{}) outLines := make(chan string) handle := &vmHandle{outLines, done} l.handleMu.Lock() l.handles["test"] = handle l.handleMu.Unlock() go func() { for _ = range outLines { } close(done) }() close(inLines) <-outLines }
func TestProcessEvents(t *testing.T) { for _, tt := range testProcessEvents { w := watcher.NewFakeWatcher() w.Add(".") store := metrics.NewStore() lines := make(chan string) fs := afero.NewMemMapFs() o := LoaderOptions{store, lines, w, fs, false, false, true} l, err := NewLoader(o) if err != nil { t.Fatalf("couldn't create loader: %s", err) } for i := range tt.events { e := tt.events[i] switch e := e.(type) { case watcher.CreateEvent: if e.Pathname != "notexist.mtail" { _, err := fs.Create(e.Pathname) if err != nil { t.Fatalf("Create failed for %s: %s", e.Pathname, err) } } w.InjectCreate(e.Pathname) case watcher.DeleteEvent: err := fs.Remove(e.Pathname) if err != nil { t.Fatalf("Remove failed for %s: %s", e.Pathname, err) } w.InjectDelete(e.Pathname) case watcher.UpdateEvent: if e.Pathname != "notexist.mtail" { f, err := fs.Create(e.Pathname) if err != nil { t.Fatalf("Couldn't open file %s for test: %s", e.Pathname, err) } _, err = f.WriteString(testProgram) if err != nil { t.Fatalf("Couldn't write file contents: %s", err) } if err = f.Close(); err != nil { t.Fatalf("Close failed: %s", err) } } w.InjectUpdate(e.Pathname) } } w.Close() <-l.watcherDone l.handleMu.RLock() var programs []string for program := range l.handles { programs = append(programs, program) } l.handleMu.RUnlock() l.handleMu.RLock() if diff := pretty.Compare(tt.expectedPrograms, programs); len(diff) > 0 { t.Errorf("%q: loaded programs don't match.\nl.handles: %+#v\n%s", tt.name, l.handles, diff) } l.handleMu.RUnlock() close(lines) } }