Skip to content

Commit

Permalink
Fix imposters search (#173)
Browse files Browse the repository at this point in the history
* Fix imposters search
  • Loading branch information
joanlopez authored Nov 10, 2024
1 parent bca67fd commit 8c64611
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 19 deletions.
13 changes: 7 additions & 6 deletions internal/server/http/imposter.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ func NewImposterFS(path string) (ImposterFs, error) {
}, nil
}

func (i ImposterFs) FindImposters(impostersCh chan []Imposter) error {
err := fs.WalkDir(i.fs, ".", func(path string, info fs.DirEntry, err error) error {
func (ifs ImposterFs) FindImposters(impostersCh chan []Imposter) error {
err := fs.WalkDir(ifs.fs, ".", func(path string, info fs.DirEntry, err error) error {
if err != nil {
return fmt.Errorf("%w: error finding imposters", err)
}
Expand All @@ -168,19 +168,20 @@ func (i ImposterFs) FindImposters(impostersCh chan []Imposter) error {
default:
return nil
}
imposters, err := i.unmarshalImposters(cfg)
imposters, err := ifs.unmarshalImposters(cfg)
if err != nil {
return err
}
impostersCh <- imposters
}
return nil
})
close(impostersCh)
return err
}

func (i ImposterFs) unmarshalImposters(imposterConfig ImposterConfig) ([]Imposter, error) {
imposterFile, _ := i.fs.Open(imposterConfig.FilePath)
func (ifs ImposterFs) unmarshalImposters(imposterConfig ImposterConfig) ([]Imposter, error) {
imposterFile, _ := ifs.fs.Open(imposterConfig.FilePath)
defer imposterFile.Close()

bytes, _ := io.ReadAll(imposterFile)
Expand All @@ -202,7 +203,7 @@ func (i ImposterFs) unmarshalImposters(imposterConfig ImposterConfig) ([]Imposte
}

for i := range imposters {
imposters[i].BasePath = filepath.Dir(imposterConfig.FilePath)
imposters[i].BasePath = filepath.Dir(filepath.Join(ifs.path, imposterConfig.FilePath))
imposters[i].Path = imposterConfig.FilePath
}

Expand Down
134 changes: 133 additions & 1 deletion internal/server/http/imposter_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package http

import (
"encoding/json"
"testing"

"encoding/json"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v2"
Expand All @@ -22,6 +22,138 @@ func TestNewImposterFS(t *testing.T) {
})
}

func TestImposterFS_FindImposters(t *testing.T) {
// Set up
const expected = 7
ifs, err := NewImposterFS("test/testdata/imposters")
require.NoError(t, err)

// We trigger the imposters search.
// We expect exactly [expected] imposters.
ch := make(chan []Imposter, expected)
err = ifs.FindImposters(ch)
require.NoError(t, err)

// We collect all the imposters.
received := make([]Imposter, 0, expected)
for ii := range ch {
received = append(received, ii...)
}
require.Len(t, received, expected)

// Imposter 1
schemaFile := "schemas/create_gopher_request.json"
bodyFile := "responses/create_gopher_response.json"
assert.EqualValues(t, Imposter{
BasePath: "test/testdata/imposters",
Path: "create_gopher.imp.json",
Request: Request{
Method: "POST",
Endpoint: "/gophers",
SchemaFile: &schemaFile,
Params: &map[string]string{
"gopherColor": "{v:[a-z]+}",
},
Headers: &map[string]string{
"Content-Type": "application/json",
},
},
Response: Responses{{
Status: 200,
Headers: &map[string]string{
"Content-Type": "application/json",
},
BodyFile: &bodyFile,
}},
}, received[0])

// Imposter 2
assert.EqualValues(t, Imposter{
BasePath: "test/testdata/imposters",
Path: "create_gopher.imp.json",
Request: Request{},
}, received[1])

// Imposter 3
assert.EqualValues(t, Imposter{
BasePath: "test/testdata/imposters",
Path: "test_request.imp.json",
Request: Request{
Method: "GET",
Endpoint: "/testRequest",
},
Response: Responses{{
Status: 200,
Body: "Handled",
}},
}, received[2])

// Imposter 4
assert.EqualValues(t, Imposter{
BasePath: "test/testdata/imposters",
Path: "test_request.imp.yaml",
Request: Request{
Method: "GET",
Endpoint: "/yamlTestRequest",
},
Response: Responses{{
Status: 200,
Body: "Yaml Handled",
}},
}, received[3])

// Imposter 5
assert.EqualValues(t, Imposter{
BasePath: "test/testdata/imposters",
Path: "test_request.imp.yml",
Request: Request{
Method: "GET",
Endpoint: "/ymlTestRequest",
},
Response: Responses{{
Status: 200,
Body: "Yml Handled",
Delay: ResponseDelay{
delay: 1000000000,
offset: 4000000000,
},
}},
}, received[4])

// Imposter 6
assert.EqualValues(t, Imposter{
BasePath: "test/testdata/imposters",
Path: "test_request.imp.yml",
Request: Request{
Method: "POST",
Endpoint: "/yamlGophers",
Headers: &map[string]string{
"Content-Type": "application/json",
},
},
Response: Responses{{
Status: 201,
Headers: &map[string]string{
"Content-Type": "application/json",
"X-Source": "YAML",
},
BodyFile: &bodyFile,
}},
}, received[5])

// Imposter 7
assert.EqualValues(t, Imposter{
BasePath: "test/testdata/imposters",
Path: "test_request.imp.yml",
Request: Request{},
}, received[6])

// Finally, once the search is done,
// the channel must be closed.
_, open := <-ch
require.False(t, open)
}

func TestResponses_MarshalJSON(t *testing.T) {
tcs := map[string]struct {
rr *Responses
Expand Down
2 changes: 1 addition & 1 deletion internal/server/http/route_matchers.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func validateSchema(imposter Imposter, req *http.Request) error {
return fmt.Errorf("unexpected empty body request")
}

schemaFilePath, _ := filepath.Abs(schemaFile)
schemaFilePath, err := filepath.Abs(schemaFile)
if err != nil {
return fmt.Errorf("%w: impossible find the schema", err)
}
Expand Down
19 changes: 8 additions & 11 deletions internal/server/http/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"crypto/tls"
_ "embed"
"errors"
"log"
"net/http"

Expand Down Expand Up @@ -86,23 +87,19 @@ func (s *Server) Build() error {
}

var impostersCh = make(chan []Imposter)
var done = make(chan struct{})

go func() {
s.imposterFs.FindImposters(impostersCh)
done <- struct{}{}
}()
loop:
for {
select {
case imposters := <-impostersCh:
s.addImposterHandler(imposters)
log.Printf("imposter %s loaded\n", imposters[0].Path)
case <-done:
close(impostersCh)
close(done)
imposters, ok := <-impostersCh
if !ok {
break loop
}

s.addImposterHandler(imposters)
log.Printf("imposter %s loaded\n", imposters[0].Path)
}
if s.proxy.mode == killgrave.ProxyMissing {
s.router.NotFoundHandler = s.proxy.Handler()
Expand All @@ -120,7 +117,7 @@ func (s *Server) Run() {
}
log.Printf("The fake server is on tap now: %s%s\n", s.httpServer.Addr, tlsString)
err := s.run(s.secure)
if err != http.ErrServerClosed {
if !errors.Is(err, http.ErrServerClosed) {
log.Fatal(err)
}
}()
Expand All @@ -143,7 +140,7 @@ func (s *Server) run(secure bool) error {
return s.httpServer.ListenAndServeTLS("", "")
}

// Shutdown shutdown the current http server
// Shutdown shutdowns the current http server
func (s *Server) Shutdown() error {
log.Println("stopping server...")
if err := s.httpServer.Shutdown(context.TODO()); err != nil {
Expand Down

0 comments on commit 8c64611

Please sign in to comment.