From 1db50882e9c44b940237ad5c1f42366d35c3c6de Mon Sep 17 00:00:00 2001 From: jguer Date: Sat, 22 Aug 2020 00:39:26 +0200 Subject: [PATCH] feat(vcs): refactor and test cover --- cmd.go | 4 +- config.go | 4 - .../.snapshots/TestInfoStore_Update-simple | 11 + pkg/vcs/vcs.go | 2 +- pkg/vcs/vcs_test.go | 289 ++++++++++++++++++ upgrade.go | 4 +- upgrade_test.go | 2 +- vcs.go | 2 +- 8 files changed, 307 insertions(+), 11 deletions(-) create mode 100644 pkg/vcs/.snapshots/TestInfoStore_Update-simple diff --git a/cmd.go b/cmd.go index 7586f4b7..ba7f2260 100644 --- a/cmd.go +++ b/cmd.go @@ -160,7 +160,7 @@ func handleCmd(cmdArgs *settings.Arguments, dbExecutor db.Executor) error { case "Q", "query": return handleQuery(cmdArgs, dbExecutor) case "R", "remove": - return handleRemove(cmdArgs, savedInfo) + return handleRemove(cmdArgs, config.Runtime.VCSStore) case "S", "sync": return handleSync(cmdArgs, dbExecutor) case "T", "deptest": @@ -285,7 +285,7 @@ func handleSync(cmdArgs *settings.Arguments, dbExecutor db.Executor) error { return nil } -func handleRemove(cmdArgs *settings.Arguments, localCache vcs.InfoStore) error { +func handleRemove(cmdArgs *settings.Arguments, localCache *vcs.InfoStore) error { err := config.Runtime.CmdRunner.Show(passToPacman(cmdArgs)) if err == nil { localCache.RemovePackage(cmdArgs.Targets) diff --git a/config.go b/config.go index b796704e..bd0255a3 100644 --- a/config.go +++ b/config.go @@ -11,7 +11,6 @@ import ( "github.com/Jguer/yay/v10/pkg/settings" "github.com/Jguer/yay/v10/pkg/text" - "github.com/Jguer/yay/v10/pkg/vcs" ) // Verbosity settings for search @@ -25,9 +24,6 @@ var yayVersion = "10.0.0" var localePath = "/usr/share/locale" -// savedInfo holds the current vcs info -var savedInfo vcs.InfoStore - // YayConf holds the current config values for yay. var config *settings.Configuration diff --git a/pkg/vcs/.snapshots/TestInfoStore_Update-simple b/pkg/vcs/.snapshots/TestInfoStore_Update-simple new file mode 100644 index 00000000..b185ae6a --- /dev/null +++ b/pkg/vcs/.snapshots/TestInfoStore_Update-simple @@ -0,0 +1,11 @@ +{ + "hello": { + "github.com/jguer/yay.git": { + "protocols": [ + "git" + ], + "branch": "master", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + } + } +} diff --git a/pkg/vcs/vcs.go b/pkg/vcs/vcs.go index 0749efe5..dbda8aa9 100644 --- a/pkg/vcs/vcs.go +++ b/pkg/vcs/vcs.go @@ -200,7 +200,7 @@ func (v *InfoStore) NeedsUpdate(infos OriginInfoByURL) bool { } func (v *InfoStore) Save() error { - marshalledinfo, err := json.MarshalIndent(v, "", "\t") + marshalledinfo, err := json.MarshalIndent(v.OriginsByPackage, "", "\t") if err != nil || string(marshalledinfo) == "null" { return err } diff --git a/pkg/vcs/vcs_test.go b/pkg/vcs/vcs_test.go index eb51c1ec..e1c877df 100644 --- a/pkg/vcs/vcs_test.go +++ b/pkg/vcs/vcs_test.go @@ -1,9 +1,20 @@ package vcs import ( + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "os" + "os/exec" + "sync" "testing" + gosrc "github.com/Morganamilo/go-srcinfo" + "github.com/bradleyjkemp/cupaloy" "github.com/stretchr/testify/assert" + + "github.com/Jguer/yay/v10/pkg/settings/exe" ) func TestParsing(t *testing.T) { @@ -40,3 +51,281 @@ func TestParsing(t *testing.T) { assert.Equal(t, compare.Protocols, protocols) } } + +func TestNewInfoStore(t *testing.T) { + type args struct { + filePath string + runner exe.Runner + cmdBuilder *exe.CmdBuilder + } + tests := []struct { + name string + args args + }{ + { + name: "normal", + args: args{"/tmp/a.json", &exe.OSRunner{}, exe.NewCmdBuilder("git", "--a --b")}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := NewInfoStore(tt.args.filePath, tt.args.runner, tt.args.cmdBuilder) + assert.NotNil(t, got) + assert.Equal(t, []string{"--a", "--b"}, got.CmdBuilder.GitFlags) + assert.Equal(t, tt.args.cmdBuilder, got.CmdBuilder) + assert.Equal(t, tt.args.runner, got.Runner) + assert.Equal(t, "/tmp/a.json", got.FilePath) + }) + } +} + +type MockRunner struct { + Returned []string + Index int +} + +func (r *MockRunner) Show(cmd *exec.Cmd) error { + return nil +} + +func (r *MockRunner) Capture(cmd *exec.Cmd, timeout int64) (stdout, stderr string, err error) { + stdout = r.Returned[r.Index] + if r.Returned[0] == "error" { + err = errors.New("possible error") + } + return stdout, stderr, err +} + +func TestInfoStore_NeedsUpdate(t *testing.T) { + type fields struct { + Runner exe.Runner + CmdBuilder *exe.CmdBuilder + } + type args struct { + infos OriginInfoByURL + } + tests := []struct { + name string + fields fields + args args + want bool + }{ + { + name: "simple-has_update", + args: args{infos: OriginInfoByURL{ + "github.com/Jguer/z.git": OriginInfo{ + Protocols: []string{"https"}, + Branch: "0", + SHA: "991c5b4146fd27f4aacf4e3111258a848934aaa1", + }, + }}, fields: fields{ + Runner: &MockRunner{ + Returned: []string{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa HEAD"}, + }, + CmdBuilder: exe.NewCmdBuilder("git", ""), + }, + want: true, + }, + { + name: "double-has_update", + args: args{infos: OriginInfoByURL{ + "github.com/Jguer/z.git": OriginInfo{ + Protocols: []string{"https"}, + Branch: "0", + SHA: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + }, + "github.com/Jguer/a.git": OriginInfo{ + Protocols: []string{"https"}, + Branch: "0", + SHA: "991c5b4146fd27f4aacf4e3111258a848934aaa1", + }, + }}, fields: fields{ + Runner: &MockRunner{ + Returned: []string{ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa HEAD", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa HEAD", + }, + }, + CmdBuilder: exe.NewCmdBuilder("git", ""), + }, + want: true, + }, + { + name: "simple-no_update", + args: args{infos: OriginInfoByURL{ + "github.com/Jguer/z.git": OriginInfo{ + Protocols: []string{"https"}, + Branch: "0", + SHA: "991c5b4146fd27f4aacf4e3111258a848934aaa1", + }, + }}, fields: fields{ + Runner: &MockRunner{ + Returned: []string{"991c5b4146fd27f4aacf4e3111258a848934aaa1 HEAD"}, + }, + CmdBuilder: exe.NewCmdBuilder("git", ""), + }, + want: false, + }, + { + name: "simple-no_split", + args: args{infos: OriginInfoByURL{ + "github.com/Jguer/z.git": OriginInfo{ + Protocols: []string{"https"}, + Branch: "0", + SHA: "991c5b4146fd27f4aacf4e3111258a848934aaa1", + }, + }}, fields: fields{ + Runner: &MockRunner{ + Returned: []string{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, + }, + CmdBuilder: exe.NewCmdBuilder("git", ""), + }, + want: false, + }, + { + name: "simple-error", + args: args{infos: OriginInfoByURL{ + "github.com/Jguer/z.git": OriginInfo{ + Protocols: []string{"https"}, + Branch: "0", + SHA: "991c5b4146fd27f4aacf4e3111258a848934aaa1", + }, + }}, fields: fields{ + Runner: &MockRunner{ + Returned: []string{"error"}, + }, + CmdBuilder: exe.NewCmdBuilder("git", ""), + }, + want: false, + }, + { + name: "simple-no protocol", + args: args{infos: OriginInfoByURL{ + "github.com/Jguer/z.git": OriginInfo{ + Protocols: []string{}, + Branch: "0", + SHA: "991c5b4146fd27f4aacf4e3111258a848934aaa1", + }, + }}, fields: fields{ + Runner: &MockRunner{ + Returned: []string{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, + }, + CmdBuilder: exe.NewCmdBuilder("git", ""), + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + v := &InfoStore{ + Runner: tt.fields.Runner, + CmdBuilder: tt.fields.CmdBuilder, + } + got := v.NeedsUpdate(tt.args.infos) + assert.Equal(t, tt.want, got) + }) + } +} + +func TestInfoStore_Update(t *testing.T) { + type fields struct { + OriginsByPackage map[string]OriginInfoByURL + Runner exe.Runner + CmdBuilder *exe.CmdBuilder + } + type args struct { + pkgName string + sources []gosrc.ArchString + } + tests := []struct { + name string + fields fields + args args + }{ + {name: "simple", + args: args{pkgName: "hello", + sources: []gosrc.ArchString{{Value: "git://github.com/jguer/yay.git#branch=master"}}}, + fields: fields{ + OriginsByPackage: make(map[string]OriginInfoByURL), + CmdBuilder: exe.NewCmdBuilder("git", ""), + Runner: &MockRunner{Returned: []string{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa HEAD"}}, + }, + }, + } + + file, err := ioutil.TempFile("/tmp", "yay-vcs-test") + assert.NoError(t, err) + defer os.Remove(file.Name()) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + v := &InfoStore{ + OriginsByPackage: tt.fields.OriginsByPackage, + FilePath: file.Name(), + Runner: tt.fields.Runner, + CmdBuilder: tt.fields.CmdBuilder, + } + var mux sync.Mutex + var wg sync.WaitGroup + wg.Add(1) + v.Update(tt.args.pkgName, tt.args.sources, &mux, &wg) + wg.Wait() + assert.Len(t, tt.fields.OriginsByPackage, 1) + + marshalledinfo, err := json.MarshalIndent(tt.fields.OriginsByPackage, "", "\t") + assert.NoError(t, err) + + cupaloy.SnapshotT(t, marshalledinfo) + + v.Load() + fmt.Println(v.OriginsByPackage) + assert.Len(t, tt.fields.OriginsByPackage, 1) + + marshalledinfo, err = json.MarshalIndent(tt.fields.OriginsByPackage, "", "\t") + assert.NoError(t, err) + + cupaloy.SnapshotT(t, marshalledinfo) + }) + } +} + +func TestInfoStore_Remove(t *testing.T) { + type fields struct { + OriginsByPackage map[string]OriginInfoByURL + } + type args struct { + pkgs []string + } + tests := []struct { + name string + fields fields + args args + }{ + {name: "simple", + args: args{pkgs: []string{"a", "c"}}, + fields: fields{ + OriginsByPackage: map[string]OriginInfoByURL{ + "a": {}, + "b": {}, + "c": {}, + "d": {}, + }, + }, + }, + } + + file, err := ioutil.TempFile("/tmp", "yay-vcs-test") + assert.NoError(t, err) + defer os.Remove(file.Name()) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + v := &InfoStore{ + OriginsByPackage: tt.fields.OriginsByPackage, + FilePath: file.Name(), + } + v.RemovePackage(tt.args.pkgs) + assert.Len(t, tt.fields.OriginsByPackage, 2) + }) + } +} diff --git a/upgrade.go b/upgrade.go index aa432fa4..954bb7fa 100644 --- a/upgrade.go +++ b/upgrade.go @@ -70,7 +70,7 @@ func upList(warnings *query.AURWarnings, dbExecutor db.Executor, enableDowngrade text.OperationInfoln(gotext.Get("Checking development packages...")) wg.Add(1) go func() { - develUp = upDevel(remote, aurdata, savedInfo) + develUp = upDevel(remote, aurdata, config.Runtime.VCSStore) wg.Done() }() } @@ -101,7 +101,7 @@ func upList(warnings *query.AURWarnings, dbExecutor db.Executor, enableDowngrade func upDevel( remote []db.RepoPackage, aurdata map[string]*rpc.Pkg, - localCache vcs.InfoStore) upgrade.UpSlice { + localCache *vcs.InfoStore) upgrade.UpSlice { toUpdate := make([]db.RepoPackage, 0, len(aurdata)) toRemove := make([]string, 0) diff --git a/upgrade_test.go b/upgrade_test.go index 52e48cf8..e58f145a 100644 --- a/upgrade_test.go +++ b/upgrade_test.go @@ -266,7 +266,7 @@ func Test_upDevel(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { config.Runtime.CmdRunner.(*MockRunner).t = t - got := upDevel(tt.args.remote, tt.args.aurdata, tt.args.cached) + got := upDevel(tt.args.remote, tt.args.aurdata, &tt.args.cached) assert.ElementsMatch(t, tt.want, got) assert.Equal(t, tt.finalLen, len(tt.args.cached.OriginsByPackage)) }) diff --git a/vcs.go b/vcs.go index c3765869..0b9b68e5 100644 --- a/vcs.go +++ b/vcs.go @@ -43,7 +43,7 @@ func createDevelDB(config *settings.Configuration, dbExecutor db.Executor) error for i := range srcinfos { for iP := range srcinfos[i].Packages { wg.Add(1) - go savedInfo.Update(srcinfos[i].Packages[iP].Pkgname, srcinfos[i].Source, &mux, &wg) + go config.Runtime.VCSStore.Update(srcinfos[i].Packages[iP].Pkgname, srcinfos[i].Source, &mux, &wg) } }