package app import ( "fmt" "os" "reflect" "testing" "gitlab.com/revalus/grm/commands" "gitlab.com/revalus/grm/config" "gitlab.com/revalus/grm/echo" ) type FakeCommandToTest struct { triggerError bool triggerChanged bool } type ExpectedMessageTester struct { expectedMessages []string } func (emt ExpectedMessageTester) Write(p []byte) (n int, err error) { msg := string(p) if !checkIsItemInSlice(msg, emt.expectedMessages) { panic(fmt.Sprintf("the message \"%v\"does not match any of the given patterns: %#v", msg, emt.expectedMessages)) } else { fmt.Println(msg) } return 0, nil } func (fk FakeCommandToTest) Command(repoCfg config.RepositoryConfig) commands.CommandStatus { status := commands.CommandStatus{ Name: repoCfg.Name, Changed: false, Message: "response from fake command", Error: false, } if fk.triggerError { status.Error = true } if fk.triggerChanged { status.Changed = true } return status } func prepareConfigContent() (string, string) { checkErrorDuringPreparation := func(err error) { if err != nil { fmt.Printf("Cannot prepare a temporary directory for testing! %v ", err.Error()) os.Exit(2) } } baseTmp := fmt.Sprintf("%v/grmTest", os.TempDir()) if _, ok := os.Stat(baseTmp); ok != nil { err := os.Mkdir(baseTmp, 0777) checkErrorDuringPreparation(err) } tempDir, err := os.MkdirTemp(baseTmp, "*") checkErrorDuringPreparation(err) configFilePath := fmt.Sprintf("%v/config-file.yaml", tempDir) file, err := os.Create(configFilePath) checkErrorDuringPreparation(err) defer file.Close() yamlConfig := fmt.Sprintf(` workspace: %v repositories: - src: "https://github.com/golang/example.git" tags: ['example'] `, tempDir) _, err = file.WriteString(yamlConfig) checkErrorDuringPreparation(err) return tempDir, configFilePath } func TestParseApplication(t *testing.T) { workdir, configFile := prepareConfigContent() t.Cleanup(func() { os.Remove(workdir) }) args := []string{"custom-app", "sync", "-c", configFile} grm := GitRepositoryManager{} grm.Parse(args) if workdir != grm.configuration.Workspace { t.Errorf("Expected to get %v, instead of this got %v", workdir, grm.configuration.Repositories) } if !grm.cliArguments.Sync { t.Error("The value of \"sync\" is expected to be true") } expectedRepo := config.RepositoryConfig{ Name: "example", Src: "https://github.com/golang/example.git", Dest: "example", Tags: []string{"example"}, } if !reflect.DeepEqual(expectedRepo, grm.configuration.Repositories[0]) { t.Errorf("Expected to get %v, instead of this got %v", expectedRepo, grm.configuration.Repositories[0]) } } func TestOutputFromSync(t *testing.T) { grm := GitRepositoryManager{ configuration: config.Configuration{ Workspace: "/tmp", }, cliArguments: config.CliArguments{ Sync: true, Version: true, Color: false, Routines: 10, }, } emt := ExpectedMessageTester{ expectedMessages: []string{ "Info: Synchronizing repositories\n", "Info: All repositories are synced\n", fmt.Sprintf("Info: Current version: %v\n", VERSION), }, } grm.Run(emt) } func TestLimitTags(t *testing.T) { grm := GitRepositoryManager{ cliArguments: config.CliArguments{ LimitToTags: []string{"example"}, Routines: 10, }, configuration: config.Configuration{ Repositories: []config.RepositoryConfig{ {Name: "example1", Tags: []string{"example"}}, {Name: "example2", Tags: []string{"example"}}, {Name: "notExample"}, }, }, } fakeCommand := FakeCommandToTest{ triggerError: false, triggerChanged: false, } emt := ExpectedMessageTester{ expectedMessages: []string{ "Repository \"example1\": response from fake command\n", "Repository \"example2\": response from fake command\n", }, } echo.Color(false) echo.Output(emt) grm.limitTags() grm.runCommand(fakeCommand) } func TestLimitName(t *testing.T) { grm := GitRepositoryManager{ cliArguments: config.CliArguments{ LimitToName: "notExample", Routines: 10, }, configuration: config.Configuration{ Repositories: []config.RepositoryConfig{ {Name: "example1", Tags: []string{"example"}}, {Name: "example2", Tags: []string{"example"}}, {Name: "notExample"}, }, }, } fakeCommand := FakeCommandToTest{ triggerError: false, triggerChanged: false, } emt := ExpectedMessageTester{ expectedMessages: []string{ "Repository \"notExample\": response from fake command\n", }, } echo.Color(false) echo.Output(emt) grm.limitName() grm.runCommand(fakeCommand) } func TestRunWithNotExistingNameInLimit(t *testing.T) { grm := GitRepositoryManager{ cliArguments: config.CliArguments{ LimitToName: "not-existing-name", Routines: 10, }, configuration: config.Configuration{ Repositories: []config.RepositoryConfig{ {Name: "example1", Tags: []string{"example"}}, {Name: "example2", Tags: []string{"example"}}, {Name: "notExample"}, }, }, } emt := ExpectedMessageTester{ expectedMessages: []string{ "Error: no repository was found with the specified name\n", }, } echo.Color(false) status := grm.Run(emt) if status != 1 { t.Errorf("Expected to get status %v, instead o this got %v", 1, status) } } func TestRunWithNotExistingTagsInLimit(t *testing.T) { grm := GitRepositoryManager{ cliArguments: config.CliArguments{ LimitToTags: []string{"not-existing-tag"}, Routines: 10, }, configuration: config.Configuration{ Repositories: []config.RepositoryConfig{ {Name: "example1", Tags: []string{"example"}}, {Name: "example2", Tags: []string{"example"}}, {Name: "notExample"}, }, }, } emt := ExpectedMessageTester{ expectedMessages: []string{ "Error: no repository was found with the specified tags\n", }, } echo.Color(false) status := grm.Run(emt) if status != 1 { t.Errorf("Expected to get status %v, instead o this got %v", 1, status) } } func TestGetStatusOutput(t *testing.T) { grm := GitRepositoryManager{ configuration: config.Configuration{ Workspace: "/tmp", }, cliArguments: config.CliArguments{ Status: true, Routines: 10, }, } emt := ExpectedMessageTester{ expectedMessages: []string{ "Info: Current status of repositories\n", }, } echo.Color(false) status := grm.Run(emt) if status != 0 { t.Errorf("Expected to get status %v, instead o this got %v", 1, status) } } func TestDescribeStatusErrorNoColor(t *testing.T) { emt := ExpectedMessageTester{ expectedMessages: []string{ "Repository \"Test\": an error occurred: test\n", }, } echo.Color(false) echo.Output(emt) status := commands.CommandStatus{ Name: "Test", Message: "test", Error: true, } describeStatus(status) } func TestDescribeStatusErrorColor(t *testing.T) { emt := ExpectedMessageTester{ expectedMessages: []string{ fmt.Sprintf("%vRepository \"Test\": an error occurred: test%v\n", echo.ColorRed, echo.ColorReset), }, } echo.Color(true) echo.Output(emt) status := commands.CommandStatus{ Name: "Test", Message: "test", Error: true, } describeStatus(status) } func TestDescribeStatusChangedNoColor(t *testing.T) { emt := ExpectedMessageTester{ expectedMessages: []string{ "Repository \"Test\": test\n", }, } echo.Color(false) echo.Output(emt) status := commands.CommandStatus{ Name: "Test", Message: "test", Changed: true, } describeStatus(status) } func TestDescribeStatusChangedColor(t *testing.T) { emt := ExpectedMessageTester{ expectedMessages: []string{ fmt.Sprintf("%vRepository \"Test\": test%v\n", echo.ColorYellow, echo.ColorReset), }, } echo.Color(true) echo.Output(emt) status := commands.CommandStatus{ Name: "Test", Message: "test", Changed: true, } describeStatus(status) } func TestDescribeStatusNoChangeNoColor(t *testing.T) { emt := ExpectedMessageTester{ expectedMessages: []string{ "Repository \"Test\": test\n", }, } echo.Color(false) echo.Output(emt) status := commands.CommandStatus{ Name: "Test", Message: "test", Changed: false, } describeStatus(status) } func TestDescribeStatusNoChangeColor(t *testing.T) { emt := ExpectedMessageTester{ expectedMessages: []string{ fmt.Sprintf("%vRepository \"Test\": test%v\n", echo.ColorGreen, echo.ColorReset), }, } echo.Color(true) echo.Output(emt) status := commands.CommandStatus{ Name: "Test", Message: "test", Changed: false, } describeStatus(status) } func TestSkipRepository(t *testing.T) { grm := GitRepositoryManager{ cliArguments: config.CliArguments{ LimitToTags: []string{"example"}, Routines: 10, }, configuration: config.Configuration{ Repositories: []config.RepositoryConfig{ {Name: "example1"}, {Name: "example2", Skip: true}, {Name: "example3"}, }, }, } fakeCommand := FakeCommandToTest{ triggerError: false, triggerChanged: false, } emt := ExpectedMessageTester{ expectedMessages: []string{ "Repository \"example1\": response from fake command\n", "Repository \"example3\": response from fake command\n", }, } echo.Color(false) echo.Output(emt) grm.runCommand(fakeCommand) } func TestSkipRepositoryWithIgnore(t *testing.T) { grm := GitRepositoryManager{ cliArguments: config.CliArguments{ LimitToTags: []string{"example"}, Routines: 10, IgnoreSkipped: true, }, configuration: config.Configuration{ Repositories: []config.RepositoryConfig{ {Name: "example1"}, {Name: "example2", Skip: true}, {Name: "example3"}, }, }, } fakeCommand := FakeCommandToTest{ triggerError: false, triggerChanged: false, } emt := ExpectedMessageTester{ expectedMessages: []string{ "Repository \"example1\": response from fake command\n", "Repository \"example2\": response from fake command\n", "Repository \"example3\": response from fake command\n", }, } echo.Color(false) echo.Output(emt) grm.runCommand(fakeCommand) }