From 4cc05c0330cd901c0e2cff810fceda55f8304879 Mon Sep 17 00:00:00 2001 From: Benjamin Pineau Date: Fri, 13 Apr 2018 20:08:55 +0200 Subject: [PATCH] Unit tests for the git store Also, add the code coverage badge to README.md. Also, remove gocyclo from the metalinter tests: it was already a pain to comply with, and all of a sudden started to include all the vendor code (not sure why? maybe I've updated it by mistake). --- Makefile | 1 - README.md | 1 + pkg/store/git/git.go | 21 ++--- pkg/store/git/git_test.go | 157 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 169 insertions(+), 11 deletions(-) create mode 100644 pkg/store/git/git_test.go diff --git a/Makefile b/Makefile index 7968028..adf4894 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,6 @@ lint: --enable=misspell \ --enable=gas \ --enable=goimports \ - --enable=gocyclo \ ./... fmt: diff --git a/README.md b/README.md index 972aeb2..4a12683 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # katafygio [![Build Status](https://travis-ci.org/bpineau/katafygio.svg?branch=master)](https://travis-ci.org/bpineau/katafygio) +[![Coverage Status](https://coveralls.io/repos/github/bpineau/katafygio/badge.svg?branch=master)](https://coveralls.io/github/bpineau/katafygio?branch=master) [![Go Report Card](https://goreportcard.com/badge/github.com/bpineau/katafygio)](https://goreportcard.com/report/github.com/bpineau/katafygio) **katafygio** discovers Kubernetes objects (deployments, services, ...), diff --git a/pkg/store/git/git.go b/pkg/store/git/git.go index 6715058..e257d2d 100644 --- a/pkg/store/git/git.go +++ b/pkg/store/git/git.go @@ -12,10 +12,11 @@ package git import ( "context" "fmt" - "os" "os/exec" "time" + "github.com/spf13/afero" + "github.com/bpineau/katafygio/config" "github.com/sirupsen/logrus" ) @@ -25,6 +26,8 @@ const ( checkInterval = 10 * time.Second ) +var appFs = afero.NewOsFs() + // Store will maintain a git repository off dumped kube objects type Store struct { Logger *logrus.Logger @@ -131,15 +134,13 @@ func (s *Store) Status() (changed bool, err error) { return false, nil } -// Clone does git clone, or git init (when there's no GiURL to clone from) -func (s *Store) Clone() error { - if s.DryRun { - return nil - } - - err := os.MkdirAll(s.LocalDir, 0700) - if err != nil { - return fmt.Errorf("failed to created %s: %v", s.LocalDir, err) +// Clone does git clone, or git init (when there's no GitURL to clone from) +func (s *Store) Clone() (err error) { + if !s.DryRun { + err = appFs.MkdirAll(s.LocalDir, 0700) + if err != nil { + return fmt.Errorf("failed to create %s: %v", s.LocalDir, err) + } } if s.URL == "" { diff --git a/pkg/store/git/git_test.go b/pkg/store/git/git_test.go new file mode 100644 index 0000000..5f4893c --- /dev/null +++ b/pkg/store/git/git_test.go @@ -0,0 +1,157 @@ +package git + +import ( + "io/ioutil" + "os" + "os/exec" + "testing" + + "github.com/spf13/afero" + + "github.com/bpineau/katafygio/config" + "github.com/bpineau/katafygio/pkg/log" +) + +var testHasGit bool + +func init() { + // Thanks to Mitchell Hashimoto! + if _, err := exec.LookPath("git"); err == nil { + testHasGit = true + } +} + +func TestGitDryRun(t *testing.T) { + appFs = afero.NewMemMapFs() + + conf := &config.KfConfig{ + DryRun: true, + Logger: log.New("info", "", "test"), + LocalDir: "/tmp/ktest", // fake dir (in memory fs provided by Afero) + } + + repo, err := New(conf).Start() + if err != nil { + t.Errorf("failed to start git: %v", err) + } + + _, err = repo.Status() + if err != nil { + t.Error(err) + } + + repo.Stop() +} + +// testing with real git repositories and commands +func TestGit(t *testing.T) { + if !testHasGit { + t.Log("git not found, skipping") + t.Skip() + } + + dir, err := ioutil.TempDir("", "katafygio-tests") + if err != nil { + t.Fatal("failed to create a temp dir for tests") + } + + defer os.RemoveAll(dir) + + conf := &config.KfConfig{ + Logger: log.New("info", "", "test"), + LocalDir: dir, + } + + repo, err := New(conf).Start() + if err != nil { + t.Errorf("failed to start git: %v", err) + } + + changed, err := repo.Status() + if changed || err != nil { + t.Errorf("Status should return false on empty new repos (%v)", err) + } + + _ = ioutil.WriteFile(dir+"/t.yaml", []byte{42}, 0600) + + changed, err = repo.Status() + if !changed || err != nil { + t.Errorf("Status should return true on non committed files (%v)", err) + } + + changed, err = repo.Commit() + if !changed || err != nil { + t.Errorf("Commit should notify changes and not fail (%v)", err) + } + + changed, err = repo.Status() + if changed || err != nil { + t.Errorf("Status should return false after a add+commit (%v)", err) + } + + changed, err = repo.Commit() + if changed || err != nil { + t.Errorf("Commit shouldn't notify changes on unchanged repos (%v)", err) + } + + // re-use the previous repos for clone tests + + newdir, err := ioutil.TempDir("", "katafygio-tests") + if err != nil { + t.Fatal("failed to create a temp dir for tests") + } + + defer os.RemoveAll(newdir) + + repo.LocalDir = newdir + repo.URL = dir + + err = repo.Clone() + if err != nil { + t.Errorf("clone failed: %v", err) + } + + _ = ioutil.WriteFile(newdir+"/t2.yaml", []byte{42}, 0600) + repo.commitAndPush() + + changed, err = repo.Status() + if changed || err != nil { + t.Errorf("Status should return false after a add+commit+push (%v)", err) + } + + repo.Stop() + + // test various failure modes + + _, err = repo.Start() + if err == nil { + t.Error("Start/Clone on an existing repository should fail") + } + + err = repo.Git("fortzob", "42") + if err == nil { + t.Error("Git should fail with unknown subcommands") + } + + if err == nil { + t.Error("clone should fail on existing repos") + } + + notrepo, err := ioutil.TempDir("", "katafygio-tests") + if err != nil { + t.Fatal("failed to create a temp dir for tests") + } + + defer os.RemoveAll(notrepo) + + repo.LocalDir = notrepo + _, err = repo.Status() + if err == nil { + t.Error("Status should fail on a non-repos") + } + repo.commitAndPush() + _, err = repo.Commit() + if err == nil { + t.Error("Commit should fail on a non-repos") + } +}