From 1c75e201d9377f9bf7016a9afa593ebd89dff4cd Mon Sep 17 00:00:00 2001 From: Alexander Rakoczy Date: Fri, 31 Jul 2020 16:17:15 -0400 Subject: [PATCH] cmd/relui: add persistence to development database This change renames memoryStore to fileStore, and persists data created in the UI. This will help make local development less painful when testing changes. Data stored is intended to be loaded at start-up, which will be implemented in a future change. For golang/go#40279 Co-authored-by: Carlos Amedee Change-Id: Id2390c35b8e1d1d368fbf7ac13b3cdef0776ad87 Reviewed-on: https://go-review.googlesource.com/c/build/+/246298 Run-TryBot: Alexander Rakoczy TryBot-Result: Gobot Gobot Reviewed-by: Dmitri Shuralyov Reviewed-by: Andrew Bonventre --- cmd/relui/main.go | 17 ++++++- cmd/relui/protos/relui.pb.go | 96 ++++++++++++++++++++++++++---------- cmd/relui/protos/relui.proto | 6 +++ cmd/relui/store.go | 79 ++++++++++++++++++++++------- cmd/relui/store_test.go | 52 +++++++++++++++++++ cmd/relui/web.go | 3 +- cmd/relui/web_test.go | 18 +++---- 7 files changed, 216 insertions(+), 55 deletions(-) create mode 100644 cmd/relui/store_test.go diff --git a/cmd/relui/main.go b/cmd/relui/main.go index fced950835..21c52dbaae 100644 --- a/cmd/relui/main.go +++ b/cmd/relui/main.go @@ -6,6 +6,7 @@ package main import ( + "flag" "io/ioutil" "log" "net/http" @@ -16,8 +17,13 @@ import ( reluipb "golang.org/x/build/cmd/relui/protos" ) +var ( + devDataDir = flag.String("dev-data-directory", defaultDevDataDir(), "Development-only directory to use for storage of application state.") +) + func main() { - s := &server{store: &memoryStore{}, configs: loadWorkflowConfig("./workflows")} + flag.Parse() + s := &server{store: newFileStore(*devDataDir), configs: loadWorkflowConfig("./workflows")} http.Handle("/workflows/create", http.HandlerFunc(s.createWorkflowHandler)) http.Handle("/workflows/new", http.HandlerFunc(s.newWorkflowHandler)) http.Handle("/", fileServerHandler(relativeFile("./static"), http.HandlerFunc(s.homeHandler))) @@ -54,3 +60,12 @@ func loadWorkflowConfig(dir string) []*reluipb.Workflow { } return ws } + +// defaultDevDataDir returns a directory suitable for storage of data when developing relui on most platforms. +func defaultDevDataDir() string { + c, err := os.UserConfigDir() + if err != nil { + c = os.TempDir() + } + return filepath.Join(c, "go-build", "relui") +} diff --git a/cmd/relui/protos/relui.pb.go b/cmd/relui/protos/relui.pb.go index 039aaa6a44..6cca73abcf 100644 --- a/cmd/relui/protos/relui.pb.go +++ b/cmd/relui/protos/relui.pb.go @@ -195,6 +195,47 @@ func (m *BuildableTask) GetTaskType() string { return "" } +// LocalStorage is the persisted data of relui. It is used in development mode for saving application state. +type LocalStorage struct { + // workflows are a list of user-created workflows. + Workflows []*Workflow `protobuf:"bytes,1,rep,name=workflows,proto3" json:"workflows,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *LocalStorage) Reset() { *m = LocalStorage{} } +func (m *LocalStorage) String() string { return proto.CompactTextString(m) } +func (*LocalStorage) ProtoMessage() {} +func (*LocalStorage) Descriptor() ([]byte, []int) { + return fileDescriptor_6de8859f82adce0a, []int{2} +} + +func (m *LocalStorage) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_LocalStorage.Unmarshal(m, b) +} +func (m *LocalStorage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_LocalStorage.Marshal(b, m, deterministic) +} +func (m *LocalStorage) XXX_Merge(src proto.Message) { + xxx_messageInfo_LocalStorage.Merge(m, src) +} +func (m *LocalStorage) XXX_Size() int { + return xxx_messageInfo_LocalStorage.Size(m) +} +func (m *LocalStorage) XXX_DiscardUnknown() { + xxx_messageInfo_LocalStorage.DiscardUnknown(m) +} + +var xxx_messageInfo_LocalStorage proto.InternalMessageInfo + +func (m *LocalStorage) GetWorkflows() []*Workflow { + if m != nil { + return m.Workflows + } + return nil +} + type GitSource struct { Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` Ref string `protobuf:"bytes,2,opt,name=ref,proto3" json:"ref,omitempty"` @@ -207,7 +248,7 @@ func (m *GitSource) Reset() { *m = GitSource{} } func (m *GitSource) String() string { return proto.CompactTextString(m) } func (*GitSource) ProtoMessage() {} func (*GitSource) Descriptor() ([]byte, []int) { - return fileDescriptor_6de8859f82adce0a, []int{2} + return fileDescriptor_6de8859f82adce0a, []int{3} } func (m *GitSource) XXX_Unmarshal(b []byte) error { @@ -247,35 +288,38 @@ func init() { proto.RegisterType((*Workflow)(nil), "protos.Workflow") proto.RegisterMapType((map[string]string)(nil), "protos.Workflow.ParamsEntry") proto.RegisterType((*BuildableTask)(nil), "protos.BuildableTask") + proto.RegisterType((*LocalStorage)(nil), "protos.LocalStorage") proto.RegisterType((*GitSource)(nil), "protos.GitSource") } func init() { proto.RegisterFile("relui.proto", fileDescriptor_6de8859f82adce0a) } var fileDescriptor_6de8859f82adce0a = []byte{ - // 384 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x52, 0x4d, 0x6f, 0xda, 0x40, - 0x10, 0xed, 0x1a, 0xb0, 0xf0, 0xb8, 0xa5, 0x74, 0xdb, 0xaa, 0x56, 0x3f, 0x24, 0xca, 0xc9, 0xe2, - 0x40, 0x2b, 0xda, 0x43, 0x9b, 0x43, 0x24, 0x27, 0x41, 0x39, 0x20, 0x41, 0x64, 0x1b, 0x71, 0xb4, - 0xd6, 0xb0, 0x20, 0xcb, 0x8b, 0x6d, 0xed, 0xae, 0x13, 0xf9, 0x57, 0xe6, 0x2f, 0xe4, 0xa7, 0x44, - 0xbb, 0xd8, 0x09, 0x41, 0x39, 0xf9, 0xed, 0x7b, 0x33, 0x6f, 0xde, 0x8c, 0x0c, 0x36, 0xa7, 0xac, - 0x4c, 0xc6, 0x05, 0xcf, 0x65, 0x8e, 0x4d, 0xfd, 0x11, 0xc3, 0x7b, 0x04, 0xdd, 0x55, 0xce, 0xd3, - 0x2d, 0xcb, 0xef, 0x30, 0x86, 0x76, 0x46, 0xf6, 0xd4, 0x41, 0x03, 0xe4, 0x5a, 0xbe, 0xc6, 0xf8, - 0x1c, 0xde, 0xc7, 0x65, 0xc2, 0x36, 0x24, 0x66, 0x34, 0x92, 0x44, 0xa4, 0xc2, 0x31, 0x06, 0x2d, - 0xd7, 0x9e, 0x7c, 0x3e, 0x38, 0x89, 0xf1, 0x45, 0x23, 0x87, 0x44, 0xa4, 0x7e, 0x2f, 0x3e, 0x7e, - 0x0a, 0xfc, 0x17, 0xcc, 0x82, 0x70, 0xb2, 0x17, 0x4e, 0x4b, 0xb7, 0x7d, 0x6f, 0xda, 0x9a, 0xa9, - 0xe3, 0x1b, 0x2d, 0x4f, 0x33, 0xc9, 0x2b, 0xbf, 0xae, 0xfd, 0xfa, 0x1f, 0xec, 0x23, 0x1a, 0xf7, - 0xa1, 0x95, 0xd2, 0xaa, 0xce, 0xa5, 0x20, 0xfe, 0x04, 0x9d, 0x5b, 0xc2, 0x4a, 0xea, 0x18, 0x9a, - 0x3b, 0x3c, 0xce, 0x8c, 0x7f, 0x68, 0xf8, 0x80, 0xe0, 0xdd, 0x8b, 0x48, 0xaf, 0xae, 0xf5, 0x03, - 0x60, 0x43, 0x0b, 0x9a, 0x6d, 0x44, 0x94, 0x67, 0xb5, 0x89, 0x55, 0x33, 0x8b, 0x0c, 0x8f, 0xc0, - 0x14, 0x92, 0xc8, 0x52, 0xa5, 0x46, 0x6e, 0x6f, 0x82, 0x9b, 0xd4, 0xca, 0x30, 0xd0, 0x8a, 0x5f, - 0x57, 0xe0, 0x9f, 0xf0, 0x96, 0x70, 0x99, 0x6c, 0xc9, 0x5a, 0x46, 0x25, 0x67, 0x4e, 0x5b, 0x9b, - 0xd9, 0x0d, 0xb7, 0xe4, 0x0c, 0xff, 0x06, 0xd8, 0x25, 0x32, 0x12, 0x79, 0xc9, 0xd7, 0xd4, 0xe9, - 0x0c, 0x90, 0x6b, 0x4f, 0x3e, 0x34, 0x96, 0xd7, 0x89, 0x0c, 0xb4, 0xe0, 0x5b, 0xbb, 0x06, 0xe2, - 0x6f, 0x60, 0xa9, 0x63, 0x47, 0xb2, 0x2a, 0xa8, 0x63, 0x6a, 0xc7, 0xae, 0x22, 0xc2, 0xaa, 0xa0, - 0xc3, 0x5f, 0x60, 0x3d, 0x35, 0xa9, 0xdb, 0xa8, 0xa9, 0xf5, 0x6d, 0x4a, 0xce, 0x14, 0xc3, 0xe9, - 0xb6, 0x5e, 0x4a, 0xc1, 0xd1, 0x0a, 0xe0, 0x39, 0x38, 0xfe, 0x02, 0x1f, 0x43, 0x2f, 0x98, 0x45, - 0x41, 0xe8, 0x85, 0xcb, 0x20, 0x5a, 0xce, 0x67, 0xf3, 0xc5, 0x6a, 0xde, 0x7f, 0x73, 0x2a, 0x5c, - 0xfa, 0x53, 0x2f, 0x9c, 0x5e, 0xf5, 0xd1, 0xa9, 0x10, 0x84, 0x9e, 0xaf, 0x04, 0x23, 0x3e, 0xfc, - 0x46, 0x7f, 0x1e, 0x03, 0x00, 0x00, 0xff, 0xff, 0x73, 0x67, 0x81, 0x13, 0x5c, 0x02, 0x00, 0x00, + // 411 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x52, 0x4f, 0x6f, 0xd3, 0x30, + 0x1c, 0xc5, 0xed, 0x56, 0x2d, 0xbf, 0x8c, 0x51, 0x0c, 0x08, 0x8b, 0x3f, 0x52, 0xe9, 0x29, 0xda, + 0x21, 0xa0, 0xc2, 0x01, 0x38, 0x4c, 0x0a, 0x50, 0x71, 0x18, 0xea, 0x90, 0x93, 0xaa, 0xc7, 0xc8, + 0x69, 0xdd, 0x2a, 0x8a, 0x17, 0x47, 0xb6, 0xc3, 0x94, 0x4f, 0xc9, 0x57, 0xe0, 0xa3, 0x20, 0xbb, + 0x0e, 0x1b, 0xd5, 0x4e, 0x79, 0x7e, 0xef, 0xe7, 0xe7, 0xf7, 0x7b, 0x0a, 0x84, 0x8a, 0x8b, 0xb6, + 0x8c, 0x1b, 0x25, 0x8d, 0xc4, 0x23, 0xf7, 0xd1, 0xd3, 0xdf, 0x08, 0x4e, 0x56, 0x52, 0x55, 0x5b, + 0x21, 0x6f, 0x30, 0x86, 0xa3, 0x9a, 0x5d, 0x73, 0x82, 0x26, 0x28, 0x0a, 0xa8, 0xc3, 0xf8, 0x02, + 0x1e, 0x15, 0x6d, 0x29, 0x36, 0xac, 0x10, 0x3c, 0x37, 0x4c, 0x57, 0x9a, 0x0c, 0x26, 0xc3, 0x28, + 0x9c, 0x3d, 0xdb, 0x3b, 0xe9, 0xf8, 0x4b, 0x2f, 0x67, 0x4c, 0x57, 0xf4, 0xac, 0xb8, 0x7b, 0xd4, + 0xf8, 0x03, 0x8c, 0x1a, 0xa6, 0xd8, 0xb5, 0x26, 0x43, 0x77, 0xed, 0x55, 0x7f, 0xad, 0x7f, 0x35, + 0xfe, 0xe9, 0xe4, 0x79, 0x6d, 0x54, 0x47, 0xfd, 0xec, 0x8b, 0x4f, 0x10, 0xde, 0xa1, 0xf1, 0x18, + 0x86, 0x15, 0xef, 0x7c, 0x2e, 0x0b, 0xf1, 0x53, 0x38, 0xfe, 0xc5, 0x44, 0xcb, 0xc9, 0xc0, 0x71, + 0xfb, 0xc3, 0xe7, 0xc1, 0x47, 0x34, 0xfd, 0x83, 0xe0, 0xe1, 0x7f, 0x91, 0xee, 0x5d, 0xeb, 0x35, + 0xc0, 0x86, 0x37, 0xbc, 0xde, 0xe8, 0x5c, 0xd6, 0xde, 0x24, 0xf0, 0xcc, 0x55, 0x8d, 0xcf, 0x61, + 0xa4, 0x0d, 0x33, 0xad, 0x4d, 0x8d, 0xa2, 0xb3, 0x19, 0xee, 0x53, 0x5b, 0xc3, 0xd4, 0x29, 0xd4, + 0x4f, 0xe0, 0x37, 0x70, 0xca, 0x94, 0x29, 0xb7, 0x6c, 0x6d, 0xf2, 0x56, 0x09, 0x72, 0xe4, 0xcc, + 0xc2, 0x9e, 0x5b, 0x2a, 0x81, 0xdf, 0x01, 0xec, 0x4a, 0x93, 0x6b, 0xd9, 0xaa, 0x35, 0x27, 0xc7, + 0x13, 0x14, 0x85, 0xb3, 0xc7, 0xbd, 0xe5, 0xf7, 0xd2, 0xa4, 0x4e, 0xa0, 0xc1, 0xae, 0x87, 0xf8, + 0x25, 0x04, 0xb6, 0xec, 0xdc, 0x74, 0x0d, 0x27, 0x23, 0xe7, 0x78, 0x62, 0x89, 0xac, 0x6b, 0xf8, + 0xf4, 0x02, 0x4e, 0x7f, 0xc8, 0x35, 0x13, 0xa9, 0x91, 0x8a, 0xed, 0x38, 0x8e, 0x21, 0xb8, 0xf1, + 0x6d, 0x6a, 0x82, 0x5c, 0xcd, 0xe3, 0xc3, 0x9a, 0xe9, 0xed, 0xc8, 0xf4, 0x2d, 0x04, 0xff, 0x1e, + 0xb5, 0xdd, 0xda, 0xd4, 0xbe, 0xdb, 0x56, 0x09, 0xcb, 0x28, 0xbe, 0xf5, 0xa5, 0x58, 0x78, 0xbe, + 0x02, 0xb8, 0x5d, 0x1c, 0x3f, 0x87, 0x27, 0x59, 0x92, 0x5e, 0xe6, 0x69, 0x96, 0x64, 0xcb, 0x34, + 0x5f, 0x2e, 0x2e, 0x17, 0x57, 0xab, 0xc5, 0xf8, 0xc1, 0xa1, 0xf0, 0x95, 0xce, 0x93, 0x6c, 0xfe, + 0x6d, 0x8c, 0x0e, 0x85, 0x34, 0x4b, 0xa8, 0x15, 0x06, 0xc5, 0xfe, 0x37, 0x7c, 0xff, 0x37, 0x00, + 0x00, 0xff, 0xff, 0xfa, 0x0a, 0x66, 0x8f, 0x9c, 0x02, 0x00, 0x00, } diff --git a/cmd/relui/protos/relui.proto b/cmd/relui/protos/relui.proto index fa1be06aed..6060dfadc4 100644 --- a/cmd/relui/protos/relui.proto +++ b/cmd/relui/protos/relui.proto @@ -41,6 +41,12 @@ message BuildableTask { string task_type = 6; } +// LocalStorage is the persisted data of relui. It is used in development mode for saving application state. +message LocalStorage { + // workflows are a list of user-created workflows. + repeated Workflow workflows = 1; +} + message GitSource { string url = 1; string ref = 2; diff --git a/cmd/relui/store.go b/cmd/relui/store.go index 09fd362428..a861058690 100644 --- a/cmd/relui/store.go +++ b/cmd/relui/store.go @@ -5,38 +5,81 @@ package main import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" "sync" + "github.com/golang/protobuf/proto" reluipb "golang.org/x/build/cmd/relui/protos" ) // store is a persistence adapter for saving data. type store interface { - GetWorkflows() []*reluipb.Workflow + Workflows() []*reluipb.Workflow AddWorkflow(workflow *reluipb.Workflow) error } -var _ store = (*memoryStore)(nil) +var _ store = (*fileStore)(nil) -// memoryStore is a non-durable implementation of store that keeps everything in memory. -type memoryStore struct { - mut sync.Mutex - workflows []*reluipb.Workflow +// newFileStore initializes a fileStore ready for use. +// +// If dir is set to an empty string (""), no data will be saved to disk. +func newFileStore(dir string) *fileStore { + return &fileStore{ + persistDir: dir, + ls: new(reluipb.LocalStorage), + } +} + +// fileStoreName is the name of the data file used by fileStore for persistence. +const fileStoreName = "local_storage.textpb" + +// fileStore is a non-durable implementation of store that keeps everything in memory. +type fileStore struct { + mu sync.Mutex + ls *reluipb.LocalStorage + + // persistDir is a path to a directory for saving application data in textproto format. + persistDir string } -// AddWorkflow adds a workflow to the store. -func (m *memoryStore) AddWorkflow(w *reluipb.Workflow) error { - m.mut.Lock() - defer m.mut.Unlock() - m.workflows = append(m.workflows, w) +// AddWorkflow adds a workflow to the store, persisting changes to disk. +func (f *fileStore) AddWorkflow(w *reluipb.Workflow) error { + f.mu.Lock() + f.ls.Workflows = append(f.ls.Workflows, w) + f.mu.Unlock() + if err := f.persist(); err != nil { + return err + } return nil } -// GetWorkflows returns all workflows stored. -// -// TODO(golang.org/issue/40279) - clone workflows if they're ever mutated. -func (m *memoryStore) GetWorkflows() []*reluipb.Workflow { - m.mut.Lock() - defer m.mut.Unlock() - return m.workflows +// Workflows returns all workflows stored. +func (f *fileStore) Workflows() []*reluipb.Workflow { + return f.localStorage().GetWorkflows() +} + +// localStorage returns a deep copy of data stored in fileStore. +func (f *fileStore) localStorage() *reluipb.LocalStorage { + f.mu.Lock() + defer f.mu.Unlock() + return proto.Clone(f.ls).(*reluipb.LocalStorage) +} + +// persist saves fileStore state to persistDir/fileStoreName. +func (f *fileStore) persist() error { + if f.persistDir == "" { + return nil + } + if err := os.MkdirAll(f.persistDir, 0755); err != nil { + return fmt.Errorf("os.MkDirAll(%q, %v) = %w", f.persistDir, 0755, err) + } + dst := filepath.Join(f.persistDir, fileStoreName) + data := []byte(proto.MarshalTextString(f.localStorage())) + if err := ioutil.WriteFile(dst, data, 0644); err != nil { + return fmt.Errorf("ioutil.WriteFile(%q, _, %v) = %w", dst, 0644, err) + } + return nil } diff --git a/cmd/relui/store_test.go b/cmd/relui/store_test.go new file mode 100644 index 0000000000..79843db6d7 --- /dev/null +++ b/cmd/relui/store_test.go @@ -0,0 +1,52 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" + + "github.com/golang/protobuf/proto" + "github.com/google/go-cmp/cmp" + reluipb "golang.org/x/build/cmd/relui/protos" +) + +func TestFileStorePersist(t *testing.T) { + dir, err := ioutil.TempDir("", "memory-store-test") + if err != nil { + t.Fatalf("ioutil.TempDir(%q, %q) = _, %v", "", "memory-store-test", err) + } + defer os.RemoveAll(dir) + want := &reluipb.LocalStorage{ + Workflows: []*reluipb.Workflow{ + { + Name: "Persist Test", + BuildableTasks: []*reluipb.BuildableTask{{Name: "Persist Test Task"}}, + }, + }, + } + fs := newFileStore(filepath.Join(dir, "relui")) + fs.ls = want + + err = fs.persist() + if err != nil { + t.Fatalf("fs.Persist() = %v, wanted no error", err) + } + + b, err := ioutil.ReadFile(filepath.Join(dir, "relui", fileStoreName)) + if err != nil { + t.Fatalf("ioutil.ReadFile(%q) = _, %v, wanted no error", filepath.Join(dir, "relui", fileStoreName), err) + } + got := new(reluipb.LocalStorage) + err = proto.UnmarshalText(string(b), got) + if err != nil { + t.Fatalf("proto.UnmarshalText(_) = %v, wanted no error", err) + } + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("reluipb.LocalStorage mismatch (-want, +got):\n%s", diff) + } +} diff --git a/cmd/relui/web.go b/cmd/relui/web.go index fddde4cdec..a20d2fdefa 100644 --- a/cmd/relui/web.go +++ b/cmd/relui/web.go @@ -64,7 +64,7 @@ type homeResponse struct { // homeHandler renders the homepage. func (s *server) homeHandler(w http.ResponseWriter, _ *http.Request) { out := bytes.Buffer{} - if err := homeTmpl.Execute(&out, homeResponse{Workflows: s.store.GetWorkflows()}); err != nil { + if err := homeTmpl.Execute(&out, homeResponse{Workflows: s.store.Workflows()}); err != nil { log.Printf("homeHandler: %v", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return @@ -106,6 +106,7 @@ func (s *server) createWorkflowHandler(w http.ResponseWriter, r *http.Request) { } wf.Params["GitObject"] = ref if err := s.store.AddWorkflow(wf); err != nil { + log.Printf("Error adding workflow: s.store.AddWorkflow(%v) = %v", wf, err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } diff --git a/cmd/relui/web_test.go b/cmd/relui/web_test.go index 311a30b7b4..ab1ae59597 100644 --- a/cmd/relui/web_test.go +++ b/cmd/relui/web_test.go @@ -83,7 +83,7 @@ func TestServerHomeHandler(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/", nil) w := httptest.NewRecorder() - s := &server{store: &memoryStore{}} + s := &server{store: newFileStore("")} s.homeHandler(w, req) resp := w.Result() @@ -96,7 +96,7 @@ func TestServerNewWorkflowHandler(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/new", nil) w := httptest.NewRecorder() - s := &server{store: &memoryStore{}} + s := &server{store: newFileStore("")} s.newWorkflowHandler(w, req) resp := w.Result() @@ -134,7 +134,7 @@ func TestServerCreateWorkflowHandler(t *testing.T) { req.Header.Set("Content-Type", "application/x-www-form-urlencoded") w := httptest.NewRecorder() - s := &server{store: &memoryStore{}, configs: config} + s := &server{store: newFileStore(""), configs: config} s.createWorkflowHandler(w, req) resp := w.Result() @@ -146,16 +146,16 @@ func TestServerCreateWorkflowHandler(t *testing.T) { t.Errorf("resp.Header.Get(%q) = %q, wanted %q", k, resp.Header.Get(k), v) } } - if len(s.store.GetWorkflows()) != 1 && c.wantParams != nil { - t.Fatalf("len(s.store.GetWorkflows()) = %d, wanted %d", len(s.store.GetWorkflows()), 1) - } else if len(s.store.GetWorkflows()) != 0 && c.wantParams == nil { - t.Fatalf("len(s.store.GetWorkflows()) = %d, wanted %d", len(s.store.GetWorkflows()), 0) + if len(s.store.Workflows()) != 1 && c.wantParams != nil { + t.Fatalf("len(s.store.Workflows()) = %d, wanted %d", len(s.store.Workflows()), 1) + } else if len(s.store.Workflows()) != 0 && c.wantParams == nil { + t.Fatalf("len(s.store.Workflows()) = %d, wanted %d", len(s.store.Workflows()), 0) } if c.wantParams == nil { return } - if diff := cmp.Diff(c.wantParams, s.store.GetWorkflows()[0].GetParams()); diff != "" { - t.Errorf("s.Store.GetWorkflows()[0].Params() mismatch (-want, +got):\n%s", diff) + if diff := cmp.Diff(c.wantParams, s.store.Workflows()[0].GetParams()); diff != "" { + t.Errorf("s.Store.Workflows()[0].Params() mismatch (-want, +got):\n%s", diff) } }) }