Skip to content

Commit

Permalink
Added unused stubs handle. Added removal of stubs by ID.
Browse files Browse the repository at this point in the history
  • Loading branch information
rez1dent3 committed Sep 8, 2023
1 parent fbfa812 commit d14586b
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 10 deletions.
2 changes: 2 additions & 0 deletions api/openapi/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ components:
- method
- data
properties:
id:
$ref: '#/components/schemas/ID'
service:
type: string
example: Gripmock
Expand Down
10 changes: 8 additions & 2 deletions internal/app/rest_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func NewRestServer(path string) (*StubsServer, error) {

// deprecated code
type findStubPayload struct {
ID *uuid.UUID `json:"id,omitempty"`
Service string `json:"service"`
Method string `json:"method"`
Data map[string]interface{} `json:"data"`
Expand Down Expand Up @@ -128,9 +129,14 @@ func (h *StubsServer) BatchStubsDelete(w http.ResponseWriter, r *http.Request) {
}
}

func (h *StubsServer) ListUnusedStubs(w http.ResponseWriter, r *http.Request) {
func (h *StubsServer) ListUnusedStubs(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
panic("ListUnusedStubs")
err := json.NewEncoder(w).Encode(h.stubs.Unused())
if err != nil {
h.responseError(err, w)

return
}
}

func (h *StubsServer) ListStubs(w http.ResponseWriter, _ *http.Request) {
Expand Down
6 changes: 5 additions & 1 deletion internal/app/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type closeMatch struct {
}

func findStub(stubStorage *storage.StubStorage, stub *findStubPayload) (*storage.Output, error) {
stubs, err := stubStorage.ItemsBy(stub.Service, stub.Method)
stubs, err := stubStorage.ItemsBy(stub.Service, stub.Method, stub.ID)
if errors.Is(err, storage.ErrServiceNotFound) {
//fixme
//nolint:goerr113
Expand All @@ -40,6 +40,10 @@ func findStub(stubStorage *storage.StubStorage, stub *findStubPayload) (*storage
return nil, fmt.Errorf("stub for Service:%s and Method:%s is empty", stub.Service, stub.Method)
}

if stub.ID != nil {
return &stubs[0].Output, nil
}

var closestMatch []closeMatch
for _, strange := range stubs {
if expect := strange.Input.Equals; expect != nil {
Expand Down
1 change: 1 addition & 0 deletions internal/domain/rest/api.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pkg/sdk/api.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 49 additions & 7 deletions pkg/storage/stubs.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type storage struct {
}

type StubStorage struct {
used map[uuid.UUID]struct{}
db *memdb.MemDB
total int64
}
Expand All @@ -58,7 +59,7 @@ func New() (*StubStorage, error) {
return nil, err
}

return &StubStorage{db: db}, nil
return &StubStorage{db: db, used: map[uuid.UUID]struct{}{}}, nil
}

func (r *StubStorage) Add(stubs ...*Stub) []uuid.UUID {
Expand Down Expand Up @@ -93,8 +94,9 @@ func (r *StubStorage) Delete(args ...uuid.UUID) {
var total int64
for _, arg := range args {
n, _ := txn.DeleteAll(TableName, IDField, arg)

total += int64(n)

delete(r.used, arg)
}

atomic.AddInt64(&r.total, -total)
Expand All @@ -105,13 +107,14 @@ func (r *StubStorage) Purge() {
defer txn.Commit()

n, _ := txn.DeleteAll(TableName, IDField)
r.used = map[uuid.UUID]struct{}{}

atomic.AddInt64(&r.total, -int64(n))
}

func (r *StubStorage) ItemsBy(service, method string) ([]storage, error) {
txn := r.db.Txn(false)
defer txn.Abort()
func (r *StubStorage) ItemsBy(service, method string, ID *uuid.UUID) ([]storage, error) {
txn := r.db.Txn(true)
defer txn.Commit()

// Support for backward compatibility. Someday it will be redone...
first, err := txn.First(TableName, ServiceField, service)
Expand All @@ -125,7 +128,14 @@ func (r *StubStorage) ItemsBy(service, method string) ([]storage, error) {
return nil, ErrMethodNotFound
}

it, err := txn.Get(TableName, ServiceMethodField, service, method)
var it memdb.ResultIterator

if ID == nil {
it, err = txn.Get(TableName, ServiceMethodField, service, method)
} else {
it, err = txn.Get(TableName, IDField, ID)
}

if err != nil {
return nil, err
}
Expand All @@ -135,6 +145,7 @@ func (r *StubStorage) ItemsBy(service, method string) ([]storage, error) {
for obj := it.Next(); obj != nil; obj = it.Next() {
stub := obj.(*Stub)

r.used[stub.GetID()] = struct{}{}
result = append(result, storage{
ID: stub.GetID(),
Input: stub.Input,
Expand All @@ -145,17 +156,48 @@ func (r *StubStorage) ItemsBy(service, method string) ([]storage, error) {
return result, nil
}

func (r *StubStorage) Stubs() []Stub {
func (r *StubStorage) Unused() []Stub {
txn := r.db.Txn(false)
defer txn.Abort()

iter, err := txn.Get(TableName, IDField)
if err != nil {
return nil
}

it := memdb.NewFilterIterator(iter, func(raw interface{}) bool {
obj, ok := raw.(*Stub)
if !ok {
return true
}

_, ok = r.used[obj.GetID()]

return ok
})

result := make([]Stub, 0, atomic.LoadInt64(&r.total))

for obj := it.Next(); obj != nil; obj = it.Next() {
stub := obj.(*Stub)

result = append(result, *stub)
}

return result
}

func (r *StubStorage) Stubs() []Stub {
txn := r.db.Txn(false)
defer txn.Abort()

it, err := txn.Get(TableName, IDField)
if err != nil {
return nil
}

result := make([]Stub, 0, atomic.LoadInt64(&r.total))

for obj := it.Next(); obj != nil; obj = it.Next() {
stub := obj.(*Stub)

Expand Down
26 changes: 26 additions & 0 deletions stub/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ func TestStub(t *testing.T) {
handler: api.ListStubs,
expect: "[{\"id\":\"43739ed8-2810-4f57-889b-4d3ff5795bce\",\"service\":\"Testing\",\"method\":\"TestMethod\",\"input\":{\"equals\":{\"Hola\":\"Mundo\"},\"contains\":null,\"matches\":null},\"output\":{\"data\":{\"Hello\":\"World\"},\"error\":\"\"}}]",
},
{
name: "unused stubs (all stubs)",
mock: func() *http.Request {
return httptest.NewRequest(http.MethodGet, "/api/stubs/unused", nil)
},
handler: api.ListUnusedStubs,
expect: "[{\"id\":\"43739ed8-2810-4f57-889b-4d3ff5795bce\",\"service\":\"Testing\",\"method\":\"TestMethod\",\"input\":{\"equals\":{\"Hola\":\"Mundo\"},\"contains\":null,\"matches\":null},\"output\":{\"data\":{\"Hello\":\"World\"},\"error\":\"\"}}]",
},
{
name: "find stub equals",
mock: func() *http.Request {
Expand All @@ -67,6 +75,24 @@ func TestStub(t *testing.T) {
handler: api.SearchStubs,
expect: "{\"data\":{\"Hello\":\"World\"},\"error\":\"\"}\n",
},
{
name: "unused stubs (zero)",
mock: func() *http.Request {
return httptest.NewRequest(http.MethodGet, "/api/stubs/unused", nil)
},
handler: api.ListUnusedStubs,
expect: "[]",
},
{
name: "find stub by ID",
mock: func() *http.Request {
payload := `{"id": "43739ed8-2810-4f57-889b-4d3ff5795bce", "service":"Testing","method":"TestMethod","data":{}}`

return httptest.NewRequest(http.MethodPost, "/api/stubs/search", bytes.NewReader([]byte(payload)))
},
handler: api.SearchStubs,
expect: "{\"data\":{\"Hello\":\"World\"},\"error\":\"\"}\n",
},
{
name: "add nested stub equals",
mock: func() *http.Request {
Expand Down

0 comments on commit d14586b

Please sign in to comment.