diff --git a/backend.go b/backend.go index fa4fe68..42fba2d 100644 --- a/backend.go +++ b/backend.go @@ -6,11 +6,9 @@ import ( "io/ioutil" "net/http" "os" + "path/filepath" "strings" "time" - "path/filepath" - - log "github.com/sirupsen/logrus" ) // ConflictError if there is a locking conflict @@ -51,7 +49,7 @@ func (b *Backend) getTfstateFilename(tfID string) string { if strings.HasSuffix(tfID, ".tfstate") { return filepath.Join(b.dir, tfID) } - return filepath.Join(b.dir, tfID + ".tfstate") + return filepath.Join(b.dir, tfID+".tfstate") } func (b *Backend) get(tfID string) ([]byte, error) { @@ -60,11 +58,11 @@ func (b *Backend) get(tfID string) ([]byte, error) { var err error if _, err := os.Stat(tfstateFilename); os.IsNotExist(err) { - log.Infof("File %s not found", tfstateFilename) + logger.Infof("File %s not found", tfstateFilename) return nil, err } if tfstate, err = ioutil.ReadFile(tfstateFilename); err != nil { - log.Warnf("Can't read file %s. With follow error %v", tfstateFilename, err) + logger.Warnf("Can't read file %s. With follow error %v", tfstateFilename, err) return nil, err } @@ -75,13 +73,14 @@ func (b *Backend) update(tfID string, tfstate []byte) error { var tfstateFilename = b.getTfstateFilename(tfID) if err := ioutil.WriteFile(tfstateFilename, tfstate, 0644); err != nil { - log.Warnf("Can't write file %s. Got follow error %v", tfstateFilename, err) + logger.Warnf("Can't write file %s. Got follow error %v", tfstateFilename, err) return err } return nil } func (b *Backend) purge(tfID string) error { + var log = GetLogger() var tfstateFilename = b.getTfstateFilename(tfID) if _, err := os.Stat(tfstateFilename); os.IsNotExist(err) { @@ -103,27 +102,27 @@ func (b *Backend) lock(tfID string, lock []byte) ([]byte, error) { var err error if err := json.Unmarshal(lock, &lockInfo); err != nil { - log.Errorf("unexpected decoding json error %v", err) + logger.Errorf("unexpected decoding json error %v", err) return nil, err } if _, err := os.Stat(lockFilename); os.IsNotExist(err) { if err = ioutil.WriteFile(lockFilename, lock, 0644); err != nil { - log.Errorf("Can't write lock file %s. Got follow error %v", lockFilename, err) + logger.Errorf("Can't write lock file %s. Got follow error %v", lockFilename, err) return nil, err } return lock, nil } if lockFile, err = ioutil.ReadFile(lockFilename); err != nil { - log.Errorf("Can't read file %s. With follow error %v", lockFilename, err) + logger.Errorf("Can't read file %s. With follow error %v", lockFilename, err) return nil, err } if err := json.Unmarshal(lockFile, ¤tLockInfo); err != nil { - log.Errorf("unexpected decoding json error %v", err) + logger.Errorf("unexpected decoding json error %v", err) return nil, err } if currentLockInfo.ID != lockInfo.ID { - log.Infof("state is locked with diffrend id %s, but follow id requestd lock %s", currentLockInfo.ID, lockInfo.ID) + logger.Infof("state is locked with diffrend id %s, but follow id requestd lock %s", currentLockInfo.ID, lockInfo.ID) return nil, &ConflictError{ StatusCode: http.StatusConflict, } @@ -138,29 +137,29 @@ func (b *Backend) unlock(tfID string, lock []byte) error { var lockInfo, currentLockInfo LockInfo if err := json.Unmarshal(lock, &lockInfo); err != nil { - log.Errorf("unexpected decoding json error %v", err) + logger.Errorf("unexpected decoding json error %v", err) return err } if _, err := os.Stat(lockFilename); os.IsNotExist(err) { - log.Infof("lock file %s is deleted so notting to do.", lockFilename) + logger.Infof("lock file %s is deleted so notting to do.", lockFilename) return nil } if lockFile, err = ioutil.ReadFile(lockFilename); err != nil { - log.Errorf("Can't read file %s. With follow error %v", lockFilename, err) + logger.Errorf("Can't read file %s. With follow error %v", lockFilename, err) return err } if err := json.Unmarshal(lockFile, ¤tLockInfo); err != nil { - log.Errorf("unexpected decoding json error %v", err) + logger.Errorf("unexpected decoding json error %v", err) return err } if currentLockInfo.ID != lockInfo.ID { - log.Infof("state is locked with diffrend id %s, but follow id requestd lock %s", currentLockInfo.ID, lockInfo.ID) + logger.Infof("state is locked with diffrend id %s, but follow id requestd lock %s", currentLockInfo.ID, lockInfo.ID) return &ConflictError{ StatusCode: http.StatusConflict, } } if err := os.Remove(lockFilename); err != nil { - log.Warnf("Can't delete file %s. Got follow error %v", lockFilename, err) + logger.Warnf("Can't delete file %s. Got follow error %v", lockFilename, err) return err } diff --git a/backend_test.go b/backend_test.go index 2243926..8ef924b 100644 --- a/backend_test.go +++ b/backend_test.go @@ -1,17 +1,20 @@ package main import ( - "bytes" "encoding/json" "os" "path/filepath" - "reflect" "testing" "time" + + "github.com/sirupsen/logrus/hooks/test" + "github.com/stretchr/testify/assert" ) func TestBackend_get(t *testing.T) { tmpTestDir, cleanup := createDirectory() + testLogger, hooks := test.NewNullLogger() + SetLogger(testLogger) defer cleanup() @@ -29,11 +32,12 @@ func TestBackend_get(t *testing.T) { tfID string } tests := []struct { - name string - fields fields - args args - want []byte - wantErr bool + name string + fields fields + args args + want []byte + wantErr bool + wantLogs []string }{ { "success get file content", @@ -41,6 +45,7 @@ func TestBackend_get(t *testing.T) { args{case1Filename}, []byte(case1Content), false, + nil, }, { "success get file content with given .tfstate extension", @@ -48,6 +53,7 @@ func TestBackend_get(t *testing.T) { args{case2Filename}, []byte(case2Content), false, + nil, }, { "try to get not existing file", @@ -55,6 +61,7 @@ func TestBackend_get(t *testing.T) { args{"this_file_not_exists"}, nil, true, + []string{"this_file_not_exists.tfstate not found"}, }, } for _, tt := range tests { @@ -63,13 +70,12 @@ func TestBackend_get(t *testing.T) { dir: tt.fields.dir, } got, err := b.get(tt.args.tfID) - if (err != nil) != tt.wantErr { - t.Errorf("get() error = %v, wantErr %v", err, tt.wantErr) + if tt.wantErr { + assert.Error(t, err) return } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("get() got = %v, want %v", got, tt.want) - } + checkLogMessage(t, tt.wantLogs, hooks) + assert.Equal(t, tt.want, got) }) } } @@ -95,15 +101,17 @@ func TestBackend_getTfstateFilename(t *testing.T) { b := &Backend{ dir: tt.fields.dir, } - if got := b.getTfstateFilename(tt.args.tfID); got != tt.want { - t.Errorf("getTfstateFilename() = %v, want %v", got, tt.want) - } + got := b.getTfstateFilename(tt.args.tfID) + + assert.Equal(t, tt.want, got) }) } } func TestBackend_lock(t *testing.T) { tmpTestDir, cleanup := createDirectory() + testLogger, hooks := test.NewNullLogger() + SetLogger(testLogger) var lockInfo1, lockInfo2 LockInfo lockInfo1 = LockInfo{"myid1", "START", "ThisInfo", "", "", time.Now(), ""} lockInfo1Bytes, _ := json.Marshal(lockInfo1) @@ -119,11 +127,12 @@ func TestBackend_lock(t *testing.T) { lock []byte } tests := []struct { - name string - fields fields - args args - want []byte - wantErr bool + name string + fields fields + args args + want []byte + wantErr bool + wantLogs []string }{ { "set lock", @@ -131,6 +140,7 @@ func TestBackend_lock(t *testing.T) { args{"this_state", lockInfo1Bytes}, lockInfo1Bytes, false, + nil, }, { "update lock", @@ -138,6 +148,7 @@ func TestBackend_lock(t *testing.T) { args{"this_state", lockInfo1Bytes}, lockInfo1Bytes, false, + nil, }, { "trigger conflict", @@ -145,6 +156,7 @@ func TestBackend_lock(t *testing.T) { args{"this_state", lockInfo2Bytes}, nil, true, + []string{"state is locked with diffrend id myid1, but follow id requestd lock myid2"}, }, } for _, tt := range tests { @@ -153,19 +165,20 @@ func TestBackend_lock(t *testing.T) { dir: tt.fields.dir, } got, err := b.lock(tt.args.tfID, tt.args.lock) - if (err != nil) != tt.wantErr { - t.Errorf("lock() error = %v, wantErr %v", err, tt.wantErr) + if tt.wantErr { + assert.Error(t, err) return } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("lock() got = %v, want %v", got, tt.want) - } + assert.Equal(t, tt.want, got) + checkLogMessage(t, tt.wantLogs, hooks) }) } } func TestBackend_purge(t *testing.T) { tmpTestDir, cleanup := createDirectory() + testLogger, hooks := test.NewNullLogger() + SetLogger(testLogger) defer cleanup() case1TfStateFile := "existing.tfstate" @@ -177,22 +190,24 @@ func TestBackend_purge(t *testing.T) { tfID string } tests := []struct { - name string - fields fields - args args - wantErr bool + name string + fields fields + args args + wantErr bool + wantLogs []string }{ - {"purge state", fields{tmpTestDir}, args{case1TfStateFile}, false}, - {"ignore purge for not existing file", fields{tmpTestDir}, args{"not_existing_file"}, false}, + {"purge state", fields{tmpTestDir}, args{case1TfStateFile}, false, nil}, + {"ignore purge for not existing file", fields{tmpTestDir}, args{"not_existing_file"}, false, []string{"not_existing_file.tfstate not found"}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { b := &Backend{ dir: tt.fields.dir, } - if err := b.purge(tt.args.tfID); (err != nil) != tt.wantErr { - t.Errorf("pruge() error = %v, wantErr %v", err, tt.wantErr) + if err := b.purge(tt.args.tfID); err != nil { + assert.Error(t, err) } + checkLogMessage(t, tt.wantLogs, hooks) }) } } @@ -200,6 +215,8 @@ func TestBackend_purge(t *testing.T) { func TestBackend_unlock(t *testing.T) { var lockInfo1, lockInfo2 LockInfo tmpTestDir, cleanup := createDirectory() + testLogger, hooks := test.NewNullLogger() + SetLogger(testLogger) defer cleanup() lockInfo1 = LockInfo{"myid1", "START", "ThisInfo", "", "", time.Now(), ""} @@ -218,23 +235,28 @@ func TestBackend_unlock(t *testing.T) { lock []byte } tests := []struct { - name string - fields fields - args args - wantErr bool + name string + fields fields + args args + wantErr bool + wantLogs []string }{ - {"case1", fields{tmpTestDir}, args{"unlock_no_exists", lockInfo1Bytes}, false}, - {"case2", fields{tmpTestDir}, args{"lockInfo1", lockInfo1Bytes}, false}, - {"case3", fields{tmpTestDir}, args{"lockInfo2", lockInfo1Bytes}, true}, + {"case1", fields{tmpTestDir}, args{"unlock_no_exists", lockInfo1Bytes}, false, []string{"unlock_no_exists.lock is deleted so notting to do."}}, + {"case2", fields{tmpTestDir}, args{"lockInfo1", lockInfo1Bytes}, false, nil}, + {"case3", fields{tmpTestDir}, args{"lockInfo2", lockInfo1Bytes}, true, []string{"state is locked with diffrend id myid2, but follow id requestd lock myid1"}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { b := &Backend{ dir: tt.fields.dir, } - if err := b.unlock(tt.args.tfID, tt.args.lock); (err != nil) != tt.wantErr { - t.Errorf("unlock() error = %v, wantErr %v", err, tt.wantErr) + err := b.unlock(tt.args.tfID, tt.args.lock) + if tt.wantErr { + assert.Error(t, err) + } else { + assert.Nil(t, err) } + checkLogMessage(t, tt.wantLogs, hooks) }) } } @@ -266,13 +288,14 @@ func TestBackend_update(t *testing.T) { b := &Backend{ dir: tt.fields.dir, } - if err := b.update(tt.args.tfID, tt.args.tfstate); (err != nil) != tt.wantErr { - t.Errorf("update() error = %v, wantErr %v", err, tt.wantErr) + err := b.update(tt.args.tfID, tt.args.tfstate) + if tt.wantErr { + assert.Error(t, err) + } else { + assert.Nil(t, err) } fileContent, _ := os.ReadFile(b.getTfstateFilename(tt.args.tfID)) - if !bytes.Equal(tt.args.tfstate, fileContent) { - t.Errorf("update() got %s want %s", string(fileContent), string(tt.args.tfstate)) - } + assert.Equal(t, tt.args.tfstate, fileContent) }) } } @@ -293,9 +316,8 @@ func TestConflictError_Error(t *testing.T) { c := &ConflictError{ StatusCode: tt.fields.StatusCode, } - if got := c.Error(); got != tt.want { - t.Errorf("Error() = %v, want %v", got, tt.want) - } + got := c.Error() + assert.Equal(t, tt.want, got) }) } } @@ -316,9 +338,8 @@ func TestFileNotExistsError_Error(t *testing.T) { n := &FileNotExistsError{ Info: tt.fields.Info, } - if got := n.Error(); got != tt.want { - t.Errorf("Error() = %v, want %v", got, tt.want) - } + got := n.Error() + assert.Equal(t, tt.want, got) }) } } diff --git a/go.mod b/go.mod index 6ecbc82..8bdf8f4 100644 --- a/go.mod +++ b/go.mod @@ -6,14 +6,17 @@ require ( github.com/go-chi/chi/v5 v5.0.4 github.com/sirupsen/logrus v1.8.1 github.com/spf13/viper v1.9.0 + github.com/stretchr/testify v1.7.0 ) require ( + github.com/davecgh/go-spew v1.1.1 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/magiconair/properties v1.8.5 // indirect github.com/mitchellh/mapstructure v1.4.2 // indirect github.com/pelletier/go-toml v1.9.4 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/afero v1.6.0 // indirect github.com/spf13/cast v1.4.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect @@ -23,4 +26,5 @@ require ( golang.org/x/text v0.3.6 // indirect gopkg.in/ini.v1 v1.63.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/helper_test.go b/helper_test.go index cc65111..83ac0f4 100644 --- a/helper_test.go +++ b/helper_test.go @@ -7,6 +7,9 @@ import ( "net/http/httptest" "os" "testing" + + "github.com/sirupsen/logrus/hooks/test" + "github.com/stretchr/testify/assert" ) func createDirectory() (string, func()) { @@ -45,3 +48,23 @@ func testRequest(t *testing.T, ts *httptest.Server, method, path string, body io return resp, string(respBody) } + +func checkLogMessage(t *testing.T, wantLogs []string, hooks *test.Hook) { + if wantLogs != nil { + entries := hooks.AllEntries() + for _, logMessage := range wantLogs { + found := false + var position int + for id, entry := range entries { + if !found { + if logMessage == entry.Message { + found = true + position = id + } + } + } + assert.Contains(t, entries[position].Message, logMessage) + } + } + hooks.Reset() +} diff --git a/logger.go b/logger.go new file mode 100644 index 0000000..dae3a0d --- /dev/null +++ b/logger.go @@ -0,0 +1,20 @@ +package main + +import ( + "github.com/sirupsen/logrus" +) + +var logger *logrus.Logger + +// GetLogger returns the logger instance. +// This instance is the entry point for all logging +func GetLogger() *logrus.Logger { + return logger +} + +// SetLogger sets the logger instance +// This is useful in testing as the logger can be overridden +// with a test logger +func SetLogger(l *logrus.Logger) { + logger = l +} diff --git a/main.go b/main.go index fe3b415..24a3f71 100644 --- a/main.go +++ b/main.go @@ -6,10 +6,9 @@ import ( "io/ioutil" "net/http" - log "github.com/sirupsen/logrus" - "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" + "github.com/sirupsen/logrus" ) var storageBackend Backend @@ -23,10 +22,18 @@ func getTfstate(w http.ResponseWriter, r *http.Request) { tfID := chi.URLParam(r, "id") if body, err = storageBackend.get(tfID); err != nil { if errors.As(err, &e) { - w.WriteHeader(http.StatusNotFound) - _, _ = w.Write([]byte(http.StatusText(http.StatusNotFound))) + var operation = err.(*fs.PathError).Op + if operation == "stat" || operation == "CreateFile" { + w.WriteHeader(http.StatusNotFound) + _, _ = w.Write([]byte(http.StatusText(http.StatusNotFound))) + } else { + logger.Warnf("Can not Access File: %v", err) + w.WriteHeader(http.StatusInternalServerError) + _, _ = w.Write([]byte(http.StatusText(http.StatusInternalServerError))) + } return } + logger.Warnf("Complete unexpected Error: %v", err) w.WriteHeader(http.StatusInternalServerError) _, _ = w.Write([]byte(http.StatusText(http.StatusInternalServerError))) return @@ -96,7 +103,7 @@ func unlockTfstate(w http.ResponseWriter, r *http.Request) { } func handleRequests() { - log.Debugf("current storage path: %s", config.storageDirectory) + logger.Debugf("current storage path: %s", config.storageDirectory) storageBackend = Backend{dir: config.storageDirectory} r := chi.NewRouter() @@ -115,10 +122,14 @@ func handleRequests() { r.Delete("/{id}", purgeTfstate) r.MethodFunc("LOCK", "/{id}", lockTfstate) r.MethodFunc("UNLOCK", "/{id}", unlockTfstate) - log.Fatal(http.ListenAndServe(":8080", r)) + logger.Fatal(http.ListenAndServe(":8080", r)) } -func main() { +func init() { + SetLogger(logrus.New()) config.loadConfig(".env") +} + +func main() { handleRequests() } diff --git a/main_test.go b/main_test.go index fe0e2fe..e1fd66e 100644 --- a/main_test.go +++ b/main_test.go @@ -2,15 +2,20 @@ package main import ( "encoding/json" - "github.com/go-chi/chi/v5" "net/http/httptest" "strings" "testing" "time" + + "github.com/go-chi/chi/v5" + "github.com/sirupsen/logrus/hooks/test" + "github.com/stretchr/testify/assert" ) func Test_getTfstate(t *testing.T) { tmpTestDir, cleanup := createDirectory() + testLogger, hooks := test.NewNullLogger() + SetLogger(testLogger) defer cleanup() createFile(tmpTestDir, "state_file1.tfstate", "This is the content") @@ -23,9 +28,10 @@ func Test_getTfstate(t *testing.T) { args wantStatus int wantBody string + wantLogs []string }{ - {"First case", args{"state_file1"}, 200, "This is the content"}, - {"request unknown file", args{"no_file1"}, 404, "Not Found"}, + {"First case", args{"state_file1"}, 200, "This is the content", nil}, + {"request unknown file", args{"no_file1"}, 404, "Not Found", []string{"no_file1.tfstate not found"}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -37,33 +43,17 @@ func Test_getTfstate(t *testing.T) { rr, got := testRequest(t, ts, "GET", "/"+tt.args.suburl, nil) - if tt.wantStatus != rr.StatusCode { - t.Errorf("handler returned wrong status code: got %v want %v", - rr.StatusCode, tt.wantStatus) - } - if got != tt.wantBody { - t.Errorf("handler returned unexpected body: got %v want %v", got, tt.wantBody) - } + assert.Equal(t, tt.wantStatus, rr.StatusCode) + assert.Equal(t, tt.wantBody, got) + checkLogMessage(t, tt.wantLogs, hooks) }) } } -/* -func Test_handleRequests(t *testing.T) { - tests := []struct { - name string - }{ - // T O D O: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - }) - } -} -*/ - func Test_lockTfstate(t *testing.T) { tmpTestDir, cleanup := createDirectory() + testLogger, hooks := test.NewNullLogger() + SetLogger(testLogger) defer cleanup() var lockInfo1, lockInfo2 LockInfo @@ -82,10 +72,11 @@ func Test_lockTfstate(t *testing.T) { args args wantStatus int wantBody string + wantLogs []string }{ - {"Defect lock json body", args{"jfkdslf", "not_file"}, 500, "Internal Server Error"}, - {"create new lock", args{string(lockInfo1Bytes), "not_file"}, 200, string(lockInfo1Bytes)}, - {"conflict with existing lock", args{string(lockInfo1Bytes), "exists_statelock"}, 409, "Conflict"}, + {"Defect lock json body", args{"jfkdslf", "not_file"}, 500, "Internal Server Error", []string{"unexpected decoding json error"}}, + {"create new lock", args{string(lockInfo1Bytes), "not_file"}, 200, string(lockInfo1Bytes), nil}, + {"conflict with existing lock", args{string(lockInfo1Bytes), "exists_statelock"}, 409, "Conflict", []string{"state is locked with diffrend id myid2, but follow id requestd lock myid1"}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -97,19 +88,17 @@ func Test_lockTfstate(t *testing.T) { defer ts.Close() rr, got := testRequest(t, ts, "LOCK", "/"+tt.args.suburl, strings.NewReader(tt.args.body)) - if rr.StatusCode != tt.wantStatus { - t.Errorf("handler returned wrong status code: got %v want %v", - rr.StatusCode, tt.wantStatus) - } - if got != tt.wantBody { - t.Errorf("handler returned unexpected body: got %v want %v", got, tt.wantBody) - } + assert.Equal(t, tt.wantStatus, rr.StatusCode) + assert.Equal(t, tt.wantBody, got) + checkLogMessage(t, tt.wantLogs, hooks) }) } } func Test_purgeTfstate(t *testing.T) { tmpTestDir, cleanup := createDirectory() + testLogger, hooks := test.NewNullLogger() + SetLogger(testLogger) defer cleanup() createFile(tmpTestDir, "existing_state.tfstate", "This is the Content") @@ -122,9 +111,22 @@ func Test_purgeTfstate(t *testing.T) { args args wantStatus int wantBody string + wantLogs []string }{ - {"Delete existing file", args{"existing_state"}, 200, `{"state": "tfstate deleted"}`}, - {"Delete not existing file", args{"no_file_exists"}, 200, `{"state": "tfstate deleted"}`}, + { + "Delete existing file", + args{"existing_state"}, + 200, + `{"state": "tfstate deleted"}`, + nil, + }, + { + "Delete not existing file", + args{"no_file_exists"}, + 200, + `{"state": "tfstate deleted"}`, + []string{"no_file_exists.tfstate not found"}, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -135,19 +137,18 @@ func Test_purgeTfstate(t *testing.T) { defer ts.Close() rr, got := testRequest(t, ts, "DELETE", "/"+tt.args.suburl, nil) - if rr.StatusCode != tt.wantStatus { - t.Errorf("handler returned wrong status code: got %v want %v", - rr.StatusCode, tt.wantStatus) - } - if got != tt.wantBody { - t.Errorf("handler returned unexpected body: got %v want %v", got, tt.wantBody) - } + assert.Equal(t, tt.wantStatus, rr.StatusCode) + assert.Equal(t, tt.wantBody, got) + checkLogMessage(t, tt.wantLogs, hooks) }) } } func Test_unlockTfstate(t *testing.T) { tmpTestDir, cleanup := createDirectory() + testLogger, hooks := test.NewNullLogger() + SetLogger(testLogger) + defer cleanup() var lockInfo1, lockInfo2 LockInfo @@ -166,11 +167,36 @@ func Test_unlockTfstate(t *testing.T) { args args wantStatus int wantBody string + wantLogs []string }{ - {"Defect lock json body", args{"not_file", "jfkdslf"}, 500, "Internal Server Error"}, - {"unlock success on no file", args{"not_file", string(lockInfo1Bytes)}, 200, string(lockInfo1Bytes)}, - {"conflict with existing lock", args{"exists_statelock", string(lockInfo1Bytes)}, 409, "Conflict"}, - {"unlock success on existing lock", args{"exists_statelock", string(lockInfo2Bytes)}, 200, string(lockInfo2Bytes)}, + { + "Defect lock json body", + args{"not_file", "jfkdslf"}, + 500, + "Internal Server Error", + []string{"unexpected decoding json error"}, + }, + { + "unlock success on no file", + args{"not_file", string(lockInfo1Bytes)}, + 200, + string(lockInfo1Bytes), + []string{"not_file.lock is deleted so notting to do"}, + }, + { + "conflict with existing lock", + args{"exists_statelock", string(lockInfo1Bytes)}, + 409, + "Conflict", + []string{"state is locked with diffrend id myid2, but follow id requestd lock myid1"}, + }, + { + "unlock success on existing lock", + args{"exists_statelock", string(lockInfo2Bytes)}, + 200, + string(lockInfo2Bytes), + nil, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -182,13 +208,9 @@ func Test_unlockTfstate(t *testing.T) { defer ts.Close() rr, got := testRequest(t, ts, "UNLOCK", "/"+tt.args.suburl, strings.NewReader(tt.args.body)) - if rr.StatusCode != tt.wantStatus { - t.Errorf("handler returned wrong status code: got %v want %v", - rr.StatusCode, tt.wantStatus) - } - if got != tt.wantBody { - t.Errorf("handler returned unexpected body: got %v want %v", got, tt.wantBody) - } + assert.Equal(t, tt.wantStatus, rr.StatusCode) + assert.Equal(t, tt.wantBody, got) + checkLogMessage(t, tt.wantLogs, hooks) }) } }