diff --git a/cmd/mmock/main.go b/cmd/mmock/main.go index 7ef7c60..77295a5 100644 --- a/cmd/mmock/main.go +++ b/cmd/mmock/main.go @@ -10,16 +10,16 @@ import ( "path/filepath" "strings" - "github.com/jmartin82/mmock/internal/console" "github.com/jmartin82/mmock/internal/config" "github.com/jmartin82/mmock/internal/config/parser" - "github.com/jmartin82/mmock/pkg/match" - "github.com/jmartin82/mmock/pkg/match/payload" + "github.com/jmartin82/mmock/internal/console" "github.com/jmartin82/mmock/internal/server" "github.com/jmartin82/mmock/internal/statistics" - "github.com/jmartin82/mmock/pkg/mock" "github.com/jmartin82/mmock/internal/vars" - "github.com/jmartin82/mmock/internal/vars/fakedata" + "github.com/jmartin82/mmock/internal/vars/fake" + "github.com/jmartin82/mmock/pkg/match" + "github.com/jmartin82/mmock/pkg/match/payload" + "github.com/jmartin82/mmock/pkg/mock" ) //VERSION of the application @@ -74,7 +74,7 @@ func getOutboundIP() string { return localAddr[0:idx] } -func getMatchSpier(checker match.Matcher, matchStore match.Storer) match.Spier { +func getTransactionSpy(checker match.Matcher, matchStore match.TransactionStorer) *match.Spy { return match.NewSpy(checker, matchStore) } @@ -112,12 +112,14 @@ func getRouter(mapping config.Mapping, checker match.Matcher) *server.Router { return router } -func getVarsProcessor() vars.Evaluator { - - return vars.Evaluator{FillerFactory: vars.MockFillerFactory{FakeAdapter: fakedata.FakeAdapter{}}} +func getVarsProcessor() *vars.ResponseMessageEvaluator { + ccg := fake.NewCreditCardGenerator() + fp := fake.NewFakeDataProvider(ccg) + ff := vars.NewFillerFactory(fp) + return vars.NewResponseMessageEvaluator(ff) } -func startServer(ip string, port, portTLS int, configTLS string, done chan bool, router server.Resolver, mLog chan match.Log, scenario match.ScenearioStorer, varsProcessor vars.Evaluator, spier match.Spier) { +func startServer(ip string, port, portTLS int, configTLS string, done chan struct{}, router server.RequestResolver, mLog chan match.Log, scenario match.ScenearioStorer, varsProcessor vars.Evaluator, spier match.TransactionSpier) { dispatcher := server.Dispatcher{ IP: ip, Port: port, @@ -125,15 +127,15 @@ func startServer(ip string, port, portTLS int, configTLS string, done chan bool, ConfigTLS: configTLS, Resolver: router, Translator: mock.HTTP{}, - Processor: varsProcessor, + Evaluator: varsProcessor, Scenario: scenario, Spier: spier, Mlog: mLog, } dispatcher.Start() - done <- true + done <- struct{}{} } -func startConsole(ip string, port int, resultsPerPage uint, spy match.Spier, scenario match.ScenearioStorer, mapping config.Mapping, done chan bool, mLog chan match.Log) { +func startConsole(ip string, port int, resultsPerPage uint, spy match.TransactionSpier, scenario match.ScenearioStorer, mapping config.Mapping, done chan struct{}, mLog chan match.Log) { dispatcher := console.Dispatcher{ IP: ip, Port: port, @@ -144,7 +146,7 @@ func startConsole(ip string, port int, resultsPerPage uint, spy match.Spier, sce ResultsPerPage: resultsPerPage, } dispatcher.Start() - done <- true + done <- struct{}{} } func main() { @@ -171,15 +173,15 @@ func main() { //chanels mLog := make(chan match.Log) - done := make(chan bool) + done := make(chan struct{}) //shared structs - scenario := match.NewScenarioStore() + scenario := match.NewInMemoryScenarioStore() comparator := payload.NewDefaultComparator() tester := match.NewTester(comparator, scenario) - matchStore := match.NewStore(tester) + matchStore := match.NewInMemoryTransactionStore(tester) mapping := getMapping(*cPath) - spy := getMatchSpier(tester, matchStore) + spy := getTransactionSpy(tester, matchStore) router := getRouter(mapping, tester) varsProcessor := getVarsProcessor() diff --git a/go.mod b/go.mod index 8671cc2..a3a4116 100644 --- a/go.mod +++ b/go.mod @@ -7,8 +7,10 @@ require ( github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/corpix/uarand v0.0.0 // indirect github.com/elazarl/go-bindata-assetfs v1.0.0 + github.com/fatih/color v1.7.0 // indirect github.com/ghodss/yaml v1.0.0 github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428 + github.com/joeljunstrom/go-luhn v0.0.0-20190413165225-1e071b33b576 github.com/kr/pretty v0.1.0 // indirect github.com/labstack/echo v3.3.10+incompatible github.com/labstack/gommon v0.2.8 // indirect @@ -16,6 +18,7 @@ require ( github.com/mattn/go-isatty v0.0.7 // indirect github.com/myesui/uuid v1.0.0 // indirect github.com/radovskyb/watcher v1.0.6 + github.com/rakyll/gotest v0.0.0-20180125184505-86f0749cd8cc // indirect github.com/ryanuber/go-glob v1.0.0 github.com/stathat/go v1.0.0 github.com/stretchr/testify v1.3.0 // indirect diff --git a/go.sum b/go.sum index b1eac17..8c11322 100644 --- a/go.sum +++ b/go.sum @@ -12,10 +12,14 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk= github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= +github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428 h1:Mo9W14pwbO9VfRe+ygqZ8dFbPpoIK1HFrG/zjTuQ+nc= github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428/go.mod h1:uhpZMVGznybq1itEKXj6RYw9I71qK4kH+OGMjRC4KEo= +github.com/joeljunstrom/go-luhn v0.0.0-20190413165225-1e071b33b576 h1:k82KNEG8vk59eHv/8xwBUh4dSR/t1wPiht4aDJm0SOY= +github.com/joeljunstrom/go-luhn v0.0.0-20190413165225-1e071b33b576/go.mod h1:pE5zuSeg07RZZfWS158WpV7oUWb1++8T2jZ/UklLM3E= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -36,6 +40,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/radovskyb/watcher v1.0.6 h1:8WIQ9UxEYMZjem1OwU7dVH94DXXk9mAIE1i8eqHD+IY= github.com/radovskyb/watcher v1.0.6/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg= +github.com/rakyll/gotest v0.0.0-20180125184505-86f0749cd8cc h1:hrzpgS8mnUi65ieVrD3TKJMxHP84bzmybMTQIdK/XhM= +github.com/rakyll/gotest v0.0.0-20180125184505-86f0749cd8cc/go.mod h1:iln+RRtJaJ52lKwqrSmNgQYw32Fk16CgChX85eFqBgI= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/stathat/go v1.0.0 h1:HFIS5YkyaI6tXu7JXIRRZBLRvYstdNZm034zcCeaybI= diff --git a/internal/console/dispatcher.go b/internal/console/dispatcher.go index ca3b01a..31bf276 100644 --- a/internal/console/dispatcher.go +++ b/internal/console/dispatcher.go @@ -33,7 +33,7 @@ type Dispatcher struct { IP string Port int ResultsPerPage uint - MatchSpy match.Spier + MatchSpy match.TransactionSpier Scenario match.ScenearioStorer Mapping config.Mapping Mlog chan match.Log diff --git a/internal/proxy/proxy_test.go b/internal/proxy/proxy_test.go index 779b50c..3a71ed3 100644 --- a/internal/proxy/proxy_test.go +++ b/internal/proxy/proxy_test.go @@ -4,10 +4,11 @@ import ( "bytes" "errors" "fmt" - "github.com/jmartin82/mmock/pkg/mock" "io" "net/http" "testing" + + "github.com/jmartin82/mmock/pkg/mock" ) type MockClient struct { @@ -47,7 +48,7 @@ func TestMakeValidRequest(t *testing.T) { request.Host = "http://mock_host.com" request.Method = "GET" request.Path = "/home" - url := "http://example.com" + url := "http://jordi.io" proxy := Proxy{URL: url, Client: client} response := proxy.MakeRequest(request) @@ -81,8 +82,8 @@ func TestMakeInvalidRequest(t *testing.T) { request := &mock.Request{} request.Host = "http://mock_host.com" request.Method = "GET" - request.Path = "/home" - url := "http://example.com" + request.Path = "/home/OriolMG" + url := "http://jordi.io" proxy := Proxy{URL: url, Client: client} response := proxy.MakeRequest(request) if response.StatusCode != http.StatusInternalServerError { diff --git a/internal/server/dispatcher.go b/internal/server/dispatcher.go index d99ac73..31d55fd 100644 --- a/internal/server/dispatcher.go +++ b/internal/server/dispatcher.go @@ -14,15 +14,16 @@ import ( "strconv" "time" - "github.com/jmartin82/mmock/pkg/match" "github.com/jmartin82/mmock/internal/proxy" + "github.com/jmartin82/mmock/pkg/match" - "github.com/jmartin82/mmock/internal/statistics" - "github.com/jmartin82/mmock/pkg/mock" - "github.com/jmartin82/mmock/internal/vars" "net/url" "regexp" "strings" + + "github.com/jmartin82/mmock/internal/statistics" + "github.com/jmartin82/mmock/internal/vars" + "github.com/jmartin82/mmock/pkg/mock" ) //Dispatcher is the mock http server @@ -31,11 +32,11 @@ type Dispatcher struct { Port int PortTLS int ConfigTLS string - Resolver Resolver + Resolver RequestResolver Translator mock.MessageTranslator - Processor vars.Evaluator + Evaluator vars.Evaluator Scenario match.ScenearioStorer - Spier match.Spier + Spier match.TransactionSpier Mlog chan match.Log } @@ -137,7 +138,7 @@ func (di *Dispatcher) getMatchingResult(request *mock.Request) (*mock.Definition response = getProxyResponse(request, mock) } else { - di.Processor.Eval(request, mock) + di.Evaluator.Eval(request, mock) if mock.Control.Crazy { log.Println("Running crazy mode") mock.Response.StatusCode = di.randomStatusCode(mock.Response.StatusCode) @@ -183,7 +184,7 @@ func (di Dispatcher) Start() { err := <-errCh if err != nil { - log.Fatalf("ListenAndServe: %s" , err.Error()) + log.Fatalf("ListenAndServe: %s", err.Error()) } } diff --git a/internal/server/router.go b/internal/server/router.go index f5d7083..7482b1e 100644 --- a/internal/server/router.go +++ b/internal/server/router.go @@ -10,8 +10,8 @@ import ( "github.com/jmartin82/mmock/pkg/match" ) -//Resolver contains the functions to check the http request and return the matching mock. -type Resolver interface { +//RequestResolver contains the functions to check the http request and return the matching mock. +type RequestResolver interface { Resolve(req *mock.Request) (*mock.Definition, *match.Result) } diff --git a/internal/vars/evaluator.go b/internal/vars/evaluator.go index 92fe869..183272b 100644 --- a/internal/vars/evaluator.go +++ b/internal/vars/evaluator.go @@ -1,20 +1,27 @@ package vars import ( - "github.com/jmartin82/mmock/pkg/mock" "regexp" "strings" - + "github.com/jmartin82/mmock/pkg/mock" ) var varsRegex = regexp.MustCompile(`\{\{\s*(.+?)\s*\}\}`) -type Evaluator struct { +type Evaluator interface { + Eval(req *mock.Request, m *mock.Definition) +} + +type ResponseMessageEvaluator struct { FillerFactory FillerFactory } -func (fp Evaluator) Eval(req *mock.Request, m *mock.Definition) { +func NewResponseMessageEvaluator(fp FillerFactory) *ResponseMessageEvaluator { + return &ResponseMessageEvaluator{FillerFactory: fp} +} + +func (fp ResponseMessageEvaluator) Eval(req *mock.Request, m *mock.Definition) { requestFiller := fp.FillerFactory.CreateRequestFiller(req, m) fakeFiller := fp.FillerFactory.CreateFakeFiller() streamFiller := fp.FillerFactory.CreateStreamFiller() @@ -26,7 +33,7 @@ func (fp Evaluator) Eval(req *mock.Request, m *mock.Definition) { fp.walkAndFill(m, vars) } -func (fp Evaluator) walkAndGet(res mock.Response) []string { +func (fp ResponseMessageEvaluator) walkAndGet(res mock.Response) []string { vars := []string{} for _, header := range res.Headers { @@ -43,7 +50,7 @@ func (fp Evaluator) walkAndGet(res mock.Response) []string { return vars } -func (fp Evaluator) walkAndFill(m *mock.Definition, vars map[string][]string) { +func (fp ResponseMessageEvaluator) walkAndFill(m *mock.Definition, vars map[string][]string) { res := &m.Response for header, values := range res.Headers { for i, value := range values { @@ -58,7 +65,7 @@ func (fp Evaluator) walkAndFill(m *mock.Definition, vars map[string][]string) { res.Body = fp.replaceVars(res.Body, vars) } -func (fp Evaluator) replaceVars(input string, vars map[string][]string) string { +func (fp ResponseMessageEvaluator) replaceVars(input string, vars map[string][]string) string { return varsRegex.ReplaceAllStringFunc(input, func(value string) string { varName := strings.Trim(value, "{} ") // replace the strings @@ -72,7 +79,7 @@ func (fp Evaluator) replaceVars(input string, vars map[string][]string) string { }) } -func (fp Evaluator) extractVars(input string, vars *[]string) { +func (fp ResponseMessageEvaluator) extractVars(input string, vars *[]string) { if m := varsRegex.FindAllString(input, -1); m != nil { for _, v := range m { varName := strings.Trim(v, "{} ") @@ -81,7 +88,7 @@ func (fp Evaluator) extractVars(input string, vars *[]string) { } } -func (fp Evaluator) mergeVars(org map[string][]string, vals map[string][]string) { +func (fp ResponseMessageEvaluator) mergeVars(org map[string][]string, vals map[string][]string) { for k, v := range vals { org[k] = v } diff --git a/internal/vars/evaluator_test.go b/internal/vars/evaluator_test.go index 26e70b7..8f50ecf 100644 --- a/internal/vars/evaluator_test.go +++ b/internal/vars/evaluator_test.go @@ -1,14 +1,13 @@ package vars import ( - "github.com/jmartin82/mmock/pkg/mock" "testing" + "github.com/jmartin82/mmock/pkg/mock" + "strconv" "strings" - - ) //DummyDataFaker is used in tests @@ -178,8 +177,10 @@ func (ddf DummyDataFaker) Hex(n int) string { return strings.Repeat("0", n) } -func getProcessor() Evaluator { - return Evaluator{FillerFactory: MockFillerFactory{FakeAdapter: NewDummyDataFaker("AleixMG")}} +func getProcessor() ResponseMessageEvaluator { + dfp := NewDummyDataFaker("AleixMG") + ff := NewFillerFactory(dfp) + return ResponseMessageEvaluator{FillerFactory: ff} } func TestReplaceTags(t *testing.T) { diff --git a/internal/vars/fake.go b/internal/vars/fake.go index 4bde76d..4485101 100644 --- a/internal/vars/fake.go +++ b/internal/vars/fake.go @@ -2,7 +2,7 @@ package vars import ( "errors" - "github.com/jmartin82/mmock/internal/vars/fakedata" + "github.com/jmartin82/mmock/internal/vars/fake" "log" "reflect" "regexp" @@ -11,11 +11,14 @@ import ( ) + var errMissingParameterValue = errors.New("The requested method needs input parameters which are not supplied!") + + //Fake parses the data looking for fake data tags or request data tags type Fake struct { - Fake fakedata.DataFaker + Fake fake.Generator } func (fv Fake) call(data reflect.Value, name string) (string, error) { diff --git a/internal/vars/fake/credit_card.go b/internal/vars/fake/credit_card.go new file mode 100644 index 0000000..407c4da --- /dev/null +++ b/internal/vars/fake/credit_card.go @@ -0,0 +1,59 @@ +package fake + +import ( + "math/rand" + "time" + + luhn "github.com/joeljunstrom/go-luhn" +) + +type creditCard struct { + length int + prefixes []string +} + +var creditCards = map[string]creditCard{ + "visa": {16, []string{"4"}}, + "visaelectron": {16, []string{"4539", "4556", "4916", "4532", "4929", "40240071", "4485", "4716"}}, + "mastercard": {16, []string{"51", "52", "53", "54", "55"}}, + "amex": {15, []string{"34", "37"}}, + "discover": {16, []string{"6011"}}, +} + +var r = rand.New(rand.NewSource(time.Now().UnixNano())) + +type CreditCardGenerator struct { +} + +func NewCreditCardGenerator() *CreditCardGenerator { + return &CreditCardGenerator{} +} + +func (c *CreditCardGenerator) getRndPrefix(prefixes []string) string { + return prefixes[r.Intn(len(prefixes))] +} + +func (c *CreditCardGenerator) getNumber(name string) string { + cardInfo := creditCards[name] + prefix := c.getRndPrefix(cardInfo.prefixes) + return luhn.GenerateWithPrefix(cardInfo.length, prefix) +} + +func (c *CreditCardGenerator) CreditCardVisa() string { + return c.getNumber("visa") +} +func (c *CreditCardGenerator) CreditCardVisaElectron() string { + return c.getNumber("visaelectron") +} + +func (c *CreditCardGenerator) CreditCardMasterCard() string { + return c.getNumber("mastercard") +} + +func (c *CreditCardGenerator) CreditCardAmericanExpress() string { + return c.getNumber("amex") +} + +func (c *CreditCardGenerator) CreditCardDiscover() string { + return c.getNumber("discover") +} diff --git a/internal/vars/fakedata/data_faker.go b/internal/vars/fake/generator.go similarity index 90% rename from internal/vars/fakedata/data_faker.go rename to internal/vars/fake/generator.go index dde40ff..2d4f1a0 100644 --- a/internal/vars/fakedata/data_faker.go +++ b/internal/vars/fake/generator.go @@ -1,7 +1,7 @@ -package fakedata +package fake -//DataFaker interface contains the funtions to obtain the fake data to fill the response. -type DataFaker interface { +//Generator interface contains the funtions to obtain the fake data to fill the response. +type Generator interface { Brand() string Character() string Characters() string diff --git a/internal/vars/fakedata/fake_adapter.go b/internal/vars/fake/provider.go similarity index 60% rename from internal/vars/fakedata/fake_adapter.go rename to internal/vars/fake/provider.go index 40cbf92..edf6d30 100644 --- a/internal/vars/fakedata/fake_adapter.go +++ b/internal/vars/fake/provider.go @@ -1,4 +1,4 @@ -package fakedata +package fake import ( "encoding/hex" @@ -10,117 +10,127 @@ import ( "github.com/twinj/uuid" ) -//FakeAdapter contains all available functions to create random data in the mock response. -type FakeAdapter struct { +//Provider contains all available functions to create random data in the mock response. +type Provider struct { + ccg *CreditCardGenerator +} + +func NewFakeDataProvider(ccg *CreditCardGenerator) *Provider { + return &Provider{ccg: ccg} } //Brand returns a random Brand -func (fa FakeAdapter) Brand() string { +func (p Provider) Brand() string { return fake.Brand() } //Character returns a random Character -func (fa FakeAdapter) Character() string { +func (p Provider) Character() string { return fake.Character() } //Characters returns from 1 to 5 random Characters -func (fa FakeAdapter) Characters() string { +func (p Provider) Characters() string { return fake.Characters() } //CharactersN returns n random Characters -func (fa FakeAdapter) CharactersN(n int) string { +func (p Provider) CharactersN(n int) string { return fake.CharactersN(n) } //City returns a random City -func (fa FakeAdapter) City() string { +func (p Provider) City() string { return fake.City() } //Color returns a random Color -func (fa FakeAdapter) Color() string { +func (p Provider) Color() string { return fake.Color() } //Company returns a random Company -func (fa FakeAdapter) Company() string { +func (p Provider) Company() string { return fake.Company() } //Continent returns a random Continent -func (fa FakeAdapter) Continent() string { +func (p Provider) Continent() string { return fake.Continent() } //Country returns a random Country -func (fa FakeAdapter) Country() string { +func (p Provider) Country() string { return fake.Country() } //CreditCardVisa returns a random CreditCardVisa -func (fa FakeAdapter) CreditCardVisa() string { - return fake.CreditCardNum("Visa") +func (p Provider) CreditCardVisa() string { + return p.ccg.CreditCardVisa() +} + +//CreditCardVisaElectron returns a random CreditCardVisaElectron +func (p Provider) CreditCardVisaElectron() string { + return p.ccg.CreditCardVisaElectron() } //CreditCardMasterCard returns a random CreditCardMasterCard -func (fa FakeAdapter) CreditCardMasterCard() string { - return fake.CreditCardNum("MasterCard") +func (p Provider) CreditCardMasterCard() string { + return p.ccg.CreditCardMasterCard() } //CreditCardAmericanExpress returns a random CreditCardAmericanExpress -func (fa FakeAdapter) CreditCardAmericanExpress() string { - return fake.CreditCardNum("American Express") +func (p Provider) CreditCardAmericanExpress() string { + return p.ccg.CreditCardAmericanExpress() } //Currency returns a random Currency -func (fa FakeAdapter) Currency() string { +func (p Provider) Currency() string { return fake.Currency() } //CurrencyCode returns a random CurrencyCode -func (fa FakeAdapter) CurrencyCode() string { +func (p Provider) CurrencyCode() string { return fake.CurrencyCode() } //Digits returns from 1 to 5 random Digits -func (fa FakeAdapter) Digits() string { +func (p Provider) Digits() string { return fake.Digits() } //DigitsN returns n random Digits -func (fa FakeAdapter) DigitsN(n int) string { +func (p Provider) DigitsN(n int) string { return fake.DigitsN(n) } //EmailAddress returns a random EmailAddress -func (fa FakeAdapter) EmailAddress() string { +func (p Provider) EmailAddress() string { return fake.EmailAddress() } //FirstName returns a random FirstName -func (fa FakeAdapter) FirstName() string { +func (p Provider) FirstName() string { return fake.FirstName() } //FullName returns a random FullName -func (fa FakeAdapter) FullName() string { +func (p Provider) FullName() string { return fake.FullName() } //LastName returns a random LastName -func (fa FakeAdapter) LastName() string { +func (p Provider) LastName() string { return fake.LastName() } //Gender returns a random Gender -func (fa FakeAdapter) Gender() string { +func (p Provider) Gender() string { return fake.Gender() } //Hex returns a random hexidecimal string of length n -func (fa FakeAdapter) Hex(n int) string { +func (p Provider) Hex(n int) string { bytes := make([]byte, n) rand.Read(bytes) @@ -128,154 +138,154 @@ func (fa FakeAdapter) Hex(n int) string { } //IPv4 returns a random IPv4 -func (fa FakeAdapter) IPv4() string { +func (p Provider) IPv4() string { return fake.IPv4() } //Language returns a random Language -func (fa FakeAdapter) Language() string { +func (p Provider) Language() string { return fake.Language() } //Model returns a random Model -func (fa FakeAdapter) Model() string { +func (p Provider) Model() string { return fake.Model() } //Paragraph returns a random Paragraph -func (fa FakeAdapter) Paragraph() string { +func (p Provider) Paragraph() string { return fake.Paragraph() } //Paragraphs returns from 1 to 5 random Paragraphs -func (fa FakeAdapter) Paragraphs() string { +func (p Provider) Paragraphs() string { return fake.Paragraphs() } //ParagraphsN returns n random Paragraphs -func (fa FakeAdapter) ParagraphsN(n int) string { +func (p Provider) ParagraphsN(n int) string { return fake.ParagraphsN(n) } //Phone returns a random Phone -func (fa FakeAdapter) Phone() string { +func (p Provider) Phone() string { return fake.Phone() } //Product returns a random Product -func (fa FakeAdapter) Product() string { +func (p Provider) Product() string { return fake.Product() } //Sentence returns a random sentence -func (fa FakeAdapter) Sentence() string { +func (p Provider) Sentence() string { return fake.Sentence() } //Sentences returns from 1 to 5 random sentences -func (fa FakeAdapter) Sentences() string { +func (p Provider) Sentences() string { return fake.Sentences() } //SentencesN returns n random sentences -func (fa FakeAdapter) SentencesN(n int) string { +func (p Provider) SentencesN(n int) string { return fake.SentencesN(n) } //SimplePassword returns a random simple password -func (fa FakeAdapter) SimplePassword() string { +func (p Provider) SimplePassword() string { return fake.SimplePassword() } //State returns a random state -func (fa FakeAdapter) State() string { +func (p Provider) State() string { return fake.State() } //StateAbbrev returns a random state abbrev -func (fa FakeAdapter) StateAbbrev() string { +func (p Provider) StateAbbrev() string { return fake.StateAbbrev() } //Street returns a random street -func (fa FakeAdapter) Street() string { +func (p Provider) Street() string { return fake.Street() } //StreetAddress returns a random street address -func (fa FakeAdapter) StreetAddress() string { +func (p Provider) StreetAddress() string { return fake.StreetAddress() } //UserName returns a random username -func (fa FakeAdapter) UserName() string { +func (p Provider) UserName() string { return fake.UserName() } //Day returns a random day -func (fa FakeAdapter) Day() string { +func (p Provider) Day() string { return strconv.Itoa(fake.Day()) } //Month returns a random month -func (fa FakeAdapter) Month() string { +func (p Provider) Month() string { return fake.Month() } //Year returns a random year between (1980,2020) -func (fa FakeAdapter) Year() string { +func (p Provider) Year() string { return strconv.Itoa(fake.Year(1980, 2020)) } //MonthShort returns a random month (Short Version) -func (fa FakeAdapter) MonthShort() string { +func (p Provider) MonthShort() string { return fake.MonthShort() } //WeekDay returns a random day of week -func (fa FakeAdapter) WeekDay() string { +func (p Provider) WeekDay() string { return fake.WeekDay() } //Word returns a random word -func (fa FakeAdapter) Word() string { +func (p Provider) Word() string { return fake.Word() } //Words returns from 1 to 5 random words -func (fa FakeAdapter) Words() string { +func (p Provider) Words() string { return fake.Words() } //WordsN returns n random words -func (fa FakeAdapter) WordsN(n int) string { +func (p Provider) WordsN(n int) string { return fake.WordsN(n) } //Zip returns a random zip -func (fa FakeAdapter) Zip() string { +func (p Provider) Zip() string { return fake.Zip() } //Int returns a random positive number less than or equal to n -func (fa FakeAdapter) Int(n int) string { +func (p Provider) Int(n int) string { return strconv.Itoa(rand.Intn(n + 1)) } //IntMinMax returns a random positive number greater than min and lower than max -func (fa FakeAdapter) IntMinMax(values ...int) string { +func (p Provider) IntMinMax(values ...int) string { return strconv.Itoa(rand.Intn(values[1]-values[0]) + values[0]) } //Float returns a random positive floating point number less than n -func (fa FakeAdapter) Float(n int) string { +func (p Provider) Float(n int) string { f := float64(n) value := rand.Float64() * f return strconv.FormatFloat(value, 'f', 4, 64) } //UUID generates a unique id -func (fa FakeAdapter) UUID() string { +func (p Provider) UUID() string { u := uuid.NewV4() return u.String() } diff --git a/internal/vars/fakedata/fake_adapter_test.go b/internal/vars/fake/provider_test.go similarity index 92% rename from internal/vars/fakedata/fake_adapter_test.go rename to internal/vars/fake/provider_test.go index e825110..4521ba3 100644 --- a/internal/vars/fakedata/fake_adapter_test.go +++ b/internal/vars/fake/provider_test.go @@ -1,4 +1,4 @@ -package fakedata +package fake import ( "fmt" @@ -10,7 +10,7 @@ import ( ) func TestInt(t *testing.T) { - faker := FakeAdapter{} + faker := Provider{} for i := 0; i < 10000; i++ { result := faker.Int(1000) @@ -25,7 +25,7 @@ func TestInt(t *testing.T) { } func TestIntMinMax(t *testing.T) { - faker := FakeAdapter{} + faker := Provider{} rand.Seed(time.Now().Unix()) min := 0 @@ -46,7 +46,7 @@ func TestIntMinMax(t *testing.T) { } func TestFloat(t *testing.T) { - faker := FakeAdapter{} + faker := Provider{} for i := 0; i < 10000; i++ { result := faker.Float(1000) @@ -61,7 +61,7 @@ func TestFloat(t *testing.T) { } func TestUUID(t *testing.T) { - faker := FakeAdapter{} + faker := Provider{} r := regexp.MustCompile(`[0-9A-Fa-f]{32}|[0-9A-Fa-f\\-]{36}`) for i := 0; i < 10000; i++ { @@ -73,7 +73,7 @@ func TestUUID(t *testing.T) { } func TestBasicFakeVars(t *testing.T) { - faker := FakeAdapter{} + faker := Provider{} if faker.Brand() == "" { t.Error("Brand fake doesn't work") } @@ -87,7 +87,7 @@ func TestBasicFakeVars(t *testing.T) { } func TestHex(t *testing.T) { - faker := FakeAdapter{} + faker := Provider{} for i := 1; i < 65; i++ { r := regexp.MustCompile(fmt.Sprintf("[0-9a-f]{%d}", i)) diff --git a/internal/vars/filler.go b/internal/vars/filler.go index 7827525..dbcb51c 100644 --- a/internal/vars/filler.go +++ b/internal/vars/filler.go @@ -1,5 +1,37 @@ package vars +import ( + "github.com/jmartin82/mmock/internal/vars/fake" + "github.com/jmartin82/mmock/pkg/mock" +) + type Filler interface { Fill(holders []string) map[string][]string } + +type FillerFactory interface { + CreateRequestFiller(req *mock.Request, mock *mock.Definition) Filler + CreateFakeFiller() Filler + CreateStreamFiller() Filler +} + +type MockFillerFactory struct { + FakeDataProvider fake.Generator +} + +func NewFillerFactory(fdp fake.Generator) *MockFillerFactory { + return &MockFillerFactory{FakeDataProvider: fdp} +} + +func (mff MockFillerFactory) CreateRequestFiller(req *mock.Request, mock *mock.Definition) Filler { + return Request{Mock: mock, Request: req} +} + +func (mff MockFillerFactory) CreateFakeFiller() Filler { + + return Fake{Fake: mff.FakeDataProvider} +} + +func (mff MockFillerFactory) CreateStreamFiller() Filler { + return Stream{} +} diff --git a/internal/vars/filler_factory.go b/internal/vars/filler_factory.go deleted file mode 100644 index 04cbe2e..0000000 --- a/internal/vars/filler_factory.go +++ /dev/null @@ -1,29 +0,0 @@ -package vars - -import ( - "github.com/jmartin82/mmock/pkg/mock" - "github.com/jmartin82/mmock/internal/vars/fakedata" -) - -type FillerFactory interface { - CreateRequestFiller(req *mock.Request, mock *mock.Definition) Filler - CreateFakeFiller() Filler - CreateStreamFiller() Filler -} - -type MockFillerFactory struct { - FakeAdapter fakedata.DataFaker -} - -func (mff MockFillerFactory) CreateRequestFiller(req *mock.Request, mock *mock.Definition) Filler { - return Request{Mock: mock, Request: req} -} - -func (mff MockFillerFactory) CreateFakeFiller() Filler { - - return Fake{Fake: mff.FakeAdapter} -} - -func (mff MockFillerFactory) CreateStreamFiller() Filler { - return Stream{} -} diff --git a/internal/vars/stream_test.go b/internal/vars/stream_test.go index 127213b..16428fb 100644 --- a/internal/vars/stream_test.go +++ b/internal/vars/stream_test.go @@ -44,7 +44,7 @@ func TestReadFile(t *testing.T) { func TestHTTPContent(t *testing.T) { st := Stream{} - k := "http.contents(http://example.com/)" + k := "http.contents(http://jordi.io/)" holders := []string{k} result := st.Fill(holders) @@ -53,7 +53,7 @@ func TestHTTPContent(t *testing.T) { t.Errorf("Stream key not found") } - if !strings.Contains(v[0], "Example Domain") { + if !strings.Contains(v[0], "Software Engineer") { t.Errorf("Couldn't get the content. Value: %s", v) } } diff --git a/pkg/match/request_test.go b/pkg/match/request_test.go index 70a864e..8366a59 100644 --- a/pkg/match/request_test.go +++ b/pkg/match/request_test.go @@ -491,7 +491,7 @@ func TestSceneMatchingDefinition(t *testing.T) { m := mock.Definition{} m.Control.Scenario.Name = "uSEr" m.Control.Scenario.RequiredState = []string{"created"} - s := NewScenarioStore() + s := NewInMemoryScenarioStore() mm := Request{scenario: s} if b, _ := mm.Match(&req, &m, true); b { t.Error("Scenario doesn't match") @@ -508,7 +508,7 @@ func TestSceneMatchingIgnoreStateCase(t *testing.T) { m := mock.Definition{} m.Control.Scenario.Name = "uSEr" m.Control.Scenario.RequiredState = []string{"CreAted"} - s := NewScenarioStore() + s := NewInMemoryScenarioStore() mm := Request{scenario: s} if b, _ := mm.Match(&req, &m, true); b { t.Error("Scenario doesn't match") @@ -525,7 +525,7 @@ func TestSceneMatchingDefinitionDisabled(t *testing.T) { m := mock.Definition{} m.Control.Scenario.Name = "uSEr" m.Control.Scenario.RequiredState = []string{"created"} - s := NewScenarioStore() + s := NewInMemoryScenarioStore() mm := Request{scenario: s} if b, _ := mm.Match(&req, &m, false); !b { t.Error("Scenario not skiped") diff --git a/pkg/match/scenario_store.go b/pkg/match/scenario_store.go index 12e301c..c61fe8a 100644 --- a/pkg/match/scenario_store.go +++ b/pkg/match/scenario_store.go @@ -15,17 +15,17 @@ type ScenearioStorer interface { } -func NewScenarioStore() *ScenarioStore { +func NewInMemoryScenarioStore() *InMemoryScenarioStore { status := make(map[string]string) - return &ScenarioStore{status: status} + return &InMemoryScenarioStore{status: status} } -type ScenarioStore struct { +type InMemoryScenarioStore struct { status map[string]string paused bool } -func (sm *ScenarioStore) Reset(name string) bool { +func (sm *InMemoryScenarioStore) Reset(name string) bool { if _, f := sm.status[strings.ToLower(name)]; f { sm.status[strings.ToLower(name)] = "not_started" return true @@ -33,29 +33,29 @@ func (sm *ScenarioStore) Reset(name string) bool { return false } -func (sm *ScenarioStore) ResetAll() { +func (sm *InMemoryScenarioStore) ResetAll() { sm.status = make(map[string]string) sm.paused = false } -func (sm *ScenarioStore) SetState(name, status string) { +func (sm *InMemoryScenarioStore) SetState(name, status string) { if sm.paused { return } sm.status[strings.ToLower(name)] = strings.ToLower(status) } -func (sm *ScenarioStore) GetState(name string) string { +func (sm *InMemoryScenarioStore) GetState(name string) string { if v, f := sm.status[strings.ToLower(name)]; f { return v } return "not_started" } -func (sm *ScenarioStore) GetPaused() bool { +func (sm *InMemoryScenarioStore) GetPaused() bool { return sm.paused } -func (sm *ScenarioStore) SetPaused(newstate bool) { +func (sm *InMemoryScenarioStore) SetPaused(newstate bool) { sm.paused = newstate } diff --git a/pkg/match/scenario_store_test.go b/pkg/match/scenario_store_test.go index 1f00fd0..45df062 100644 --- a/pkg/match/scenario_store_test.go +++ b/pkg/match/scenario_store_test.go @@ -3,7 +3,7 @@ package match import "testing" func TestBasicScenarioManage(t *testing.T) { - ms := NewScenarioStore() + ms := NewInMemoryScenarioStore() state := ms.GetState("scene1") if state != "not_started" { @@ -36,7 +36,7 @@ func TestBasicScenarioManage(t *testing.T) { } func TestScenarioManagePause(t *testing.T) { - ms := NewScenarioStore() + ms := NewInMemoryScenarioStore() ms.SetPaused(true) ms.SetState("Scene1", "some_state") diff --git a/pkg/match/spy.go b/pkg/match/spy.go index dcf80d0..80ca89b 100644 --- a/pkg/match/spy.go +++ b/pkg/match/spy.go @@ -27,20 +27,20 @@ type Log struct { } -type Spier interface { +type TransactionSpier interface { Find(mock.Request) []Log GetMatched() []Log GetUnMatched() []Log - Storer + TransactionStorer } type Spy struct { - store Storer + store TransactionStorer checker Matcher } -func NewSpy(checker Matcher, matchStore Storer) *Spy { - return &Spy{store: matchStore, checker: checker} +func NewSpy(checker Matcher, transactionStore TransactionStorer) *Spy { + return &Spy{store: transactionStore, checker: checker} } func (mc Spy) Find(r mock.Request) []Log { diff --git a/pkg/match/spy_test.go b/pkg/match/spy_test.go index 067563e..6f6def0 100644 --- a/pkg/match/spy_test.go +++ b/pkg/match/spy_test.go @@ -32,7 +32,7 @@ func (dsm DummyScenarioManager) SetPaused(_ bool) { } func TestFindMatches(t *testing.T) { - spy := NewSpy(NewTester(payload.NewComparator(), DummyScenarioManager{}), NewStore(DummyMatcher{})) + spy := NewSpy(NewTester(payload.NewComparator(), DummyScenarioManager{}), NewInMemoryTransactionStore(DummyMatcher{})) m1 := Log{Request: &mock.Request{Host: "TEST1"}} spy.Save(m1) @@ -56,7 +56,7 @@ func TestFindMatches(t *testing.T) { } func TestMatchByResult(t *testing.T) { - spy := NewSpy(NewTester(payload.NewComparator(), DummyScenarioManager{}), NewStore(DummyMatcher{})) + spy := NewSpy(NewTester(payload.NewComparator(), DummyScenarioManager{}), NewInMemoryTransactionStore(DummyMatcher{})) m1 := Log{Result: &Result{Found: true}} spy.Save(m1) diff --git a/pkg/match/store.go b/pkg/match/transaction_store.go similarity index 64% rename from pkg/match/store.go rename to pkg/match/transaction_store.go index 1705442..82b2a0f 100644 --- a/pkg/match/store.go +++ b/pkg/match/transaction_store.go @@ -6,7 +6,7 @@ import ( "github.com/jmartin82/mmock/pkg/mock" ) -type Storer interface { +type TransactionStorer interface { Save(Log) Reset() ResetMatch(mock.Request) @@ -15,29 +15,29 @@ type Storer interface { } -//Store stores all received request and their matches in memory until the last reset -type Store struct { +//InMemoryTransactionStore stores all received request and their matches in memory until the last reset +type InMemoryTransactionStore struct { matches []Log sync.Mutex checker Matcher } //Save store a match information -func (mrs *Store) Save(req Log) { +func (mrs *InMemoryTransactionStore) Save(req Log) { mrs.Lock() mrs.matches = append(mrs.matches, req) mrs.Unlock() } //Reset clean the request stored in memory -func (mrs *Store) Reset() { +func (mrs *InMemoryTransactionStore) Reset() { mrs.Lock() mrs.matches = make([]Log, 0, 100) mrs.Unlock() } //ResetMatch clean the request stored in memory that matches a particular criteria -func (mrs *Store) ResetMatch(req mock.Request) { +func (mrs *InMemoryTransactionStore) ResetMatch(req mock.Request) { matches := mrs.GetAll() mrs.Lock() var r = []Log{} @@ -52,7 +52,7 @@ func (mrs *Store) ResetMatch(req mock.Request) { } //GetAll return current matches (positive and negative) in memory -func (mrs *Store) GetAll() []Log { +func (mrs *InMemoryTransactionStore) GetAll() []Log { mrs.Lock() r := make([]Log, len(mrs.matches)) copy(r, mrs.matches) @@ -61,7 +61,7 @@ func (mrs *Store) GetAll() []Log { } //Get return an subset of current matches (positive and negative) in memory -func (mrs *Store) Get(limit uint, offset uint) []Log { +func (mrs *InMemoryTransactionStore) Get(limit uint, offset uint) []Log { mrs.Lock() defer mrs.Unlock() @@ -80,9 +80,9 @@ func (mrs *Store) Get(limit uint, offset uint) []Log { return r } -//NewScenarioStore is the Store constructor -func NewStore(checker Matcher) *Store { +//NewInMemoryScenarioStore is the InMemoryTransactionStore constructor +func NewInMemoryTransactionStore(checker Matcher) *InMemoryTransactionStore { reqs := make([]Log, 0, 100) - return &Store{matches: reqs, checker: checker} + return &InMemoryTransactionStore{matches: reqs, checker: checker} } diff --git a/pkg/match/store_test.go b/pkg/match/transaction_store_test.go similarity index 92% rename from pkg/match/store_test.go rename to pkg/match/transaction_store_test.go index 6f6fafb..32754a2 100644 --- a/pkg/match/store_test.go +++ b/pkg/match/transaction_store_test.go @@ -24,7 +24,7 @@ func (dm DummyMatcher) Match(req *mock.Request, mock *mock.Definition, scenarioA func TestStoreRequest(t *testing.T) { - msr := NewStore(DummyMatcher{}) + msr := NewInMemoryTransactionStore(DummyMatcher{}) m1 := Log{Request: &mock.Request{Host: "TEST1"}} msr.Save(m1) m2 := Log{Request: &mock.Request{Host: "TEST2"}} @@ -46,7 +46,7 @@ func TestStoreRequest(t *testing.T) { func TestGetAll(t *testing.T) { - msr := NewStore(DummyMatcher{}) + msr := NewInMemoryTransactionStore(DummyMatcher{}) m1 := Log{Request: &mock.Request{Host: "TEST1"}} msr.Save(m1) m2 := Log{Request: &mock.Request{Host: "TEST2"}} @@ -67,7 +67,7 @@ func TestGetAll(t *testing.T) { func TestGet(t *testing.T) { - msr := NewStore(DummyMatcher{}) + msr := NewInMemoryTransactionStore(DummyMatcher{}) matches := []Log{ {Time: 1}, @@ -110,7 +110,7 @@ func TestGet(t *testing.T) { func TestGetOnEmptyStore(t *testing.T) { - msr := NewStore(DummyMatcher{}) + msr := NewInMemoryTransactionStore(DummyMatcher{}) tests := []struct { msg string @@ -137,7 +137,7 @@ func TestGetOnEmptyStore(t *testing.T) { func TestReset(t *testing.T) { - msr := NewStore(DummyMatcher{}) + msr := NewInMemoryTransactionStore(DummyMatcher{}) m1 := Log{Request: &mock.Request{Host: "TEST1"}} msr.Save(m1) m2 := Log{Request: &mock.Request{Host: "TEST2"}} @@ -165,11 +165,11 @@ func TestReset(t *testing.T) { func TestResetMatch(t *testing.T) { - scenario := NewScenarioStore() + scenario := NewInMemoryScenarioStore() comparator := payload.NewDefaultComparator() tester := NewTester(comparator, scenario) - msr := NewStore(tester) + msr := NewInMemoryTransactionStore(tester) m1 := Log{Request: &mock.Request{Host: "TEST1"}} msr.Save(m1) m2 := Log{Request: &mock.Request{Host: "TEST2"}}