From 141203449c57faf3dbbfc596e210130945fd69fe Mon Sep 17 00:00:00 2001 From: wregulski Date: Tue, 6 Jun 2023 15:44:06 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20tests=20adjustment=C2=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client.go | 142 ++++++-- client_test.go | 897 +++++++++++++++++++++++++------------------------ interface.go | 2 +- 3 files changed, 574 insertions(+), 467 deletions(-) diff --git a/client.go b/client.go index f691d29..286637d 100644 --- a/client.go +++ b/client.go @@ -2,6 +2,9 @@ package minercraft import ( "encoding/json" + "errors" + "fmt" + "math/rand" "net" "net/http" "strings" @@ -26,42 +29,66 @@ type Client struct { } // AddMiner will add a new miner to the list of miners -func (c *Client) AddMiner(miner Miner) error { - // TODO: Align with new structure - // Make sure we have the basic requirements - // if len(miner.Name) == 0 { - // return errors.New("missing miner name") - // } else if len(miner.URL) == 0 { - // return errors.New("missing miner url") - // } - - // // Check if a miner with that name already exists - // existingMiner := c.MinerByName(miner.Name) - // if existingMiner != nil { - // return fmt.Errorf("miner %s already exists", miner.Name) - // } - - // // Check if a miner with the minerID already exists - // if len(miner.MinerID) > 0 { - // if existingMiner = c.MinerByID(miner.MinerID); existingMiner != nil { - // return fmt.Errorf("miner %s already exists", miner.MinerID) - // } - // } - - // // Ensure that we have a protocol - // if !strings.Contains(miner.URL, "http") { - // return fmt.Errorf("miner %s is missing http from url", miner.Name) - // } - - // // Test parsing the url - // parsedURL, err := url.Parse(miner.URL) - // if err != nil { - // return err - // } - // // miner.URL = parsedURL.String() - - // // Append the new miner - // c.miners = append(c.miners, &miner) +func (c *Client) AddMiner(miner Miner, apis []API) error { + // Check if miner name is empty + if len(miner.Name) == 0 { + return errors.New("missing miner name") + } + + // Check if apis is empty or nil + if len(apis) == 0 || apis == nil { + return errors.New("at least one API must be provided") + } + + // Check if a miner with that name already exists + existingMiner := c.MinerByName(miner.Name) + if existingMiner != nil { + return fmt.Errorf("miner %s already exists", miner.Name) + } + + // Check if a miner with the minerID already exists + if len(miner.MinerID) > 0 { + if existingMiner = c.MinerByID(miner.MinerID); existingMiner != nil { + return fmt.Errorf("miner %s already exists", miner.MinerID) + } + } + + // Check if the MinerAPIs already exist for the given MinerID + existingMinerAPIs := c.MinerAPIsByMinerID(miner.MinerID) + if existingMinerAPIs != nil { + return fmt.Errorf("miner APIs for MinerID %s already exist", miner.MinerID) + } + + // Check if the API types are valid + for _, api := range apis { + if !isValidAPIType(api.Type) { + return fmt.Errorf("invalid API type: %s", api.Type) + } + } + + // Check if the API types are unique within the provided APIs + apiTypes := make(map[APIType]bool) + for _, api := range apis { + if apiTypes[api.Type] { + return fmt.Errorf("duplicate API type found: %s", api.Type) + } + apiTypes[api.Type] = true + } + + // Check if the MinerID is unique or generate a new one + if len(miner.MinerID) == 0 || !c.isUniqueMinerID(miner.MinerID) { + miner.MinerID = generateUniqueMinerID() + } + + // Append the new miner + c.miners = append(c.miners, &miner) + + // Append the new miner APIs + c.minerAPIs = append(c.minerAPIs, &MinerAPIs{ + MinerID: miner.MinerID, + APIs: apis, + }) + return nil } @@ -304,3 +331,46 @@ func DefaultMinersAPIs() (minerAPIs []*MinerAPIs, err error) { err = json.Unmarshal([]byte(KnownMinersAPIs), &minerAPIs) return } + +func (c *Client) MinerAPIsByMinerID(minerID string) *MinerAPIs { + for _, minerAPIs := range c.minerAPIs { + if minerAPIs.MinerID == minerID { + return minerAPIs + } + } + return nil +} + +func isValidAPIType(apiType APIType) bool { + switch apiType { + case MAPI, Arc: + return true + default: + return false + } +} + +func (c *Client) isUniqueMinerID(minerID string) bool { + for _, miner := range c.miners { + if miner.MinerID == minerID { + return false + } + } + return true +} + +func generateUniqueMinerID() string { + // Implement your logic to generate a unique miner ID + // Here's a simple example that generates a random ID + const idLength = 8 + const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + + rand.Seed(time.Now().UnixNano()) + + id := make([]byte, idLength) + for i := range id { + id[i] = letters[rand.Intn(len(letters))] + } + + return string(id) +} diff --git a/client_test.go b/client_test.go index 81cb684..e797680 100644 --- a/client_test.go +++ b/client_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const ( @@ -46,7 +47,7 @@ func (m *mockHTTPDefaultClient) Do(req *http.Request) (*http.Response, error) { // newTestClient returns a client for mocking (using a custom HTTP interface) func newTestClient(httpClient HTTPInterface) ClientInterface { - client, _ := NewClient(nil, httpClient, nil) + client, _ := NewClient(nil, httpClient, "", nil, nil) // client.httpClient = httpClient return client } @@ -56,7 +57,7 @@ func TestNewClient(t *testing.T) { t.Parallel() t.Run("valid new client", func(t *testing.T) { - client, err := NewClient(nil, nil, nil) + client, err := NewClient(nil, nil, "", nil, nil) assert.NotNil(t, client) assert.NoError(t, err) @@ -65,13 +66,13 @@ func TestNewClient(t *testing.T) { }) t.Run("custom http client", func(t *testing.T) { - client, err := NewClient(nil, http.DefaultClient, nil) + client, err := NewClient(nil, http.DefaultClient, "", nil, nil) assert.NotNil(t, client) assert.NoError(t, err) }) t.Run("default miners", func(t *testing.T) { - client, err := NewClient(nil, nil, nil) + client, err := NewClient(nil, nil, "", nil, nil) assert.NotNil(t, client) assert.NoError(t, err) @@ -101,7 +102,7 @@ func TestNewClient(t *testing.T) { // URL: testMinerURL, }} - client, err := NewClient(nil, nil, miners) + client, err := NewClient(nil, nil, "", miners) assert.NotNil(t, client) assert.NoError(t, err) @@ -115,7 +116,7 @@ func TestNewClient(t *testing.T) { // ExampleNewClient example using NewClient() func ExampleNewClient() { - client, err := NewClient(nil, nil, nil) + client, err := NewClient(nil, nil, "", nil, nil) if err != nil { fmt.Printf("error occurred: %s", err.Error()) return @@ -128,7 +129,7 @@ func ExampleNewClient() { // BenchmarkNewClient benchmarks the method NewClient() func BenchmarkNewClient(b *testing.B) { for i := 0; i < b.N; i++ { - _, _ = NewClient(nil, nil, nil) + _, _ = NewClient(nil, nil, "", nil, nil) } } @@ -157,7 +158,7 @@ func TestDefaultClientOptions(t *testing.T) { t.Run("no retry", func(t *testing.T) { options := DefaultClientOptions() options.RequestRetryCount = 0 - client, err := NewClient(options, nil, nil) + client, err := NewClient(options, nil, "", nil, nil) assert.NotNil(t, client) assert.NoError(t, err) }) @@ -167,7 +168,7 @@ func TestDefaultClientOptions(t *testing.T) { func ExampleDefaultClientOptions() { options := DefaultClientOptions() options.UserAgent = "Custom UserAgent v1.0" - client, err := NewClient(options, nil, nil) + client, err := NewClient(options, nil, "", nil, nil) if err != nil { fmt.Printf("error occurred: %s", err.Error()) return @@ -186,427 +187,463 @@ func BenchmarkDefaultClientOptions(b *testing.B) { // TODO: Align with new structure // TestClient_AddMiner tests the method AddMiner() -// func TestClient_AddMiner(t *testing.T) { -// t.Parallel() - -// t.Run("valid cases", func(t *testing.T) { - -// // Create the list of tests -// var tests = []struct { -// testCase string -// inputMiner Miner -// expectedName string -// expectedURL string -// }{ -// { -// "valid miner", -// Miner{ -// MinerID: testMinerID, -// Name: "Test", -// Token: testMinerToken, -// URL: "https://testminer.com", -// }, -// "Test", -// "https://testminer.com", -// }, -// } - -// // Run tests -// client := newTestClient(&mockHTTPDefaultClient{}) -// for _, test := range tests { -// t.Run(test.testCase, func(t *testing.T) { -// err := client.AddMiner(test.inputMiner) -// assert.NoError(t, err) - -// // Get the miner -// miner := client.MinerByName(test.inputMiner.Name) -// assert.Equal(t, test.expectedName, miner.Name) -// assert.Equal(t, test.expectedURL, miner.URL) -// }) -// } -// }) - -// t.Run("invalid cases", func(t *testing.T) { - -// // Create the list of tests -// var tests = []struct { -// testCase string -// inputMiner Miner -// }{ -// { -// "duplicate miner - by name", -// Miner{ -// MinerID: testMinerID + "123", -// Name: "Test", -// Token: testMinerToken, -// URL: testMinerURL, -// }, -// }, -// { -// "duplicate miner - by id", -// Miner{ -// MinerID: testMinerID, -// Name: "Test123", -// Token: testMinerToken, -// URL: testMinerURL, -// }, -// }, -// { -// "missing miner name", -// Miner{ -// MinerID: testMinerID, -// Name: "", -// Token: testMinerToken, -// URL: testMinerURL, -// }, -// }, -// { -// "missing miner url", -// Miner{ -// MinerID: testMinerID, -// Name: "TestURL", -// Token: testMinerToken, -// URL: "", -// }, -// }, -// { -// "invalid miner url - http", -// Miner{ -// MinerID: testMinerID, -// Name: "TestURL", -// Token: testMinerToken, -// URL: "www.domain.com", -// }, -// }, -// { -// "invalid miner url - trigger parse error", -// Miner{ -// MinerID: testMinerID, -// Name: "TestURL", -// Token: testMinerToken, -// URL: "postgres://user:abc{DEf1=ghi@example.com:5432/db?sslmode=require", -// }, -// }, -// } - -// // Run tests -// client := newTestClient(&mockHTTPDefaultClient{}) - -// // Add a miner to start -// err := client.AddMiner(Miner{MinerID: testMinerID, Name: "Test", URL: testMinerURL}) -// assert.NoError(t, err) - -// for _, test := range tests { -// t.Run(test.testCase, func(t *testing.T) { -// err = client.AddMiner(test.inputMiner) -// assert.Error(t, err) -// }) -// } -// }) -// } - -// // ExampleClient_AddMiner example using AddMiner() -// func ExampleClient_AddMiner() { -// client, err := NewClient(nil, nil, nil) -// if err != nil { -// fmt.Printf("error occurred: %s", err.Error()) -// return -// } - -// // Add a miner -// if err = client.AddMiner(Miner{Name: testMinerName, URL: testMinerURL}); err != nil { -// fmt.Printf("error occurred: %s", err.Error()) -// return -// } - -// // Get miner by name -// fmt.Printf("created new miner named: %s", client.MinerByName(testMinerName).Name) -// // Output:created new miner named: TestMiner -// } - -// // BenchmarkClient_AddMiner benchmarks the method AddMiner() -// func BenchmarkClient_AddMiner(b *testing.B) { -// client, _ := NewClient(nil, nil, nil) -// for i := 0; i < b.N; i++ { -// _ = client.AddMiner(Miner{Name: testMinerName, URL: testMinerURL}) -// } -// } - -// // TestClient_MinerByName tests the method MinerByName() -// func TestClient_MinerByName(t *testing.T) { -// t.Parallel() - -// t.Run("get valid miner", func(t *testing.T) { -// client := newTestClient(&mockHTTPDefaultClient{}) - -// // Add a valid miner -// err := client.AddMiner(Miner{ -// Name: testMinerName, -// URL: testMinerURL, -// }) -// assert.NoError(t, err) - -// // Get valid miner -// miner := client.MinerByName(testMinerName) -// assert.NotNil(t, miner) -// }) - -// t.Run("get invalid miner", func(t *testing.T) { -// client := newTestClient(&mockHTTPDefaultClient{}) - -// // Add a valid miner -// err := client.AddMiner(Miner{ -// Name: testMinerName, -// URL: testMinerURL, -// }) -// assert.NoError(t, err) - -// // Get invalid miner -// miner := client.MinerByName("Unknown") -// assert.Nil(t, miner) -// }) -// } - -// // ExampleClient_MinerByName example using MinerByName() -// func ExampleClient_MinerByName() { -// client, err := NewClient(nil, nil, nil) -// if err != nil { -// fmt.Printf("error occurred: %s", err.Error()) -// return -// } - -// // Add a miner -// if err = client.AddMiner(Miner{Name: testMinerName, URL: testMinerURL}); err != nil { -// fmt.Printf("error occurred: %s", err.Error()) -// return -// } - -// // Get miner by name -// fmt.Printf("created new miner named: %s", client.MinerByName(testMinerName).Name) -// // Output:created new miner named: TestMiner -// } - -// // BenchmarkClient_MinerByName benchmarks the method MinerByName() -// func BenchmarkClient_MinerByName(b *testing.B) { -// client, _ := NewClient(nil, nil, nil) -// _ = client.AddMiner(Miner{Name: testMinerName, URL: testMinerURL}) -// for i := 0; i < b.N; i++ { -// _ = client.MinerByName(testMinerName) -// } -// } - -// // TestClient_MinerByID tests the method MinerByID() -// func TestClient_MinerByID(t *testing.T) { -// t.Parallel() - -// t.Run("get valid miner", func(t *testing.T) { -// client := newTestClient(&mockHTTPDefaultClient{}) - -// // Add a valid miner -// err := client.AddMiner(Miner{ -// Name: testMinerName, -// MinerID: testMinerID, -// URL: testMinerURL, -// }) -// assert.NoError(t, err) - -// // Get valid miner -// miner := client.MinerByID(testMinerID) -// assert.NotNil(t, miner) -// }) - -// t.Run("get invalid miner", func(t *testing.T) { -// client := newTestClient(&mockHTTPDefaultClient{}) - -// // Add a valid miner -// err := client.AddMiner(Miner{ -// Name: testMinerName, -// MinerID: testMinerID, -// URL: testMinerURL, -// }) -// assert.NoError(t, err) - -// // Get invalid miner -// miner := client.MinerByID("00000") -// assert.Nil(t, miner) -// }) -// } - -// // ExampleClient_MinerByID example using MinerByID() -// func ExampleClient_MinerByID() { -// client, err := NewClient(nil, nil, nil) -// if err != nil { -// fmt.Printf("error occurred: %s", err.Error()) -// return -// } - -// // Add a miner -// if err = client.AddMiner(Miner{Name: testMinerName, MinerID: testMinerID, URL: testMinerURL}); err != nil { -// fmt.Printf("error occurred: %s", err.Error()) -// return -// } - -// // Get miner by id -// fmt.Printf("created new miner named: %s", client.MinerByID(testMinerID).Name) -// // Output:created new miner named: TestMiner -// } - -// // BenchmarkClient_MinerByID benchmarks the method MinerByID() -// func BenchmarkClient_MinerByID(b *testing.B) { -// client, _ := NewClient(nil, nil, nil) -// _ = client.AddMiner(Miner{Name: testMinerName, MinerID: testMinerID, URL: testMinerURL}) -// for i := 0; i < b.N; i++ { -// _ = client.MinerByID(testMinerID) -// } -// } - -// // TestClient_MinerUpdateToken tests the method MinerUpdateToken() -// func TestClient_MinerUpdateToken(t *testing.T) { -// t.Parallel() - -// t.Run("update valid miner", func(t *testing.T) { -// client := newTestClient(&mockHTTPDefaultClient{}) - -// // Add a valid miner -// err := client.AddMiner(Miner{ -// Name: testMinerName, -// MinerID: testMinerID, -// Token: testMinerToken, -// URL: testMinerURL, -// }) -// assert.NoError(t, err) - -// // Update a valid miner token -// client.MinerUpdateToken(testMinerName, "99999") - -// // Get valid miner -// miner := client.MinerByID(testMinerID) -// assert.NotNil(t, miner) -// assert.Equal(t, "99999", miner.Token) -// }) - -// t.Run("update unknown miner", func(t *testing.T) { -// client := newTestClient(&mockHTTPDefaultClient{}) - -// // Add a valid miner -// err := client.AddMiner(Miner{ -// Name: testMinerName, -// MinerID: testMinerID, -// Token: testMinerToken, -// URL: testMinerURL, -// }) -// assert.NoError(t, err) - -// // Update a invalid miner token -// client.MinerUpdateToken("Unknown", "99999") -// }) -// } - -// // ExampleClient_MinerUpdateToken example using MinerUpdateToken() -// func ExampleClient_MinerUpdateToken() { -// client, err := NewClient(nil, nil, nil) -// if err != nil { -// fmt.Printf("error occurred: %s", err.Error()) -// return -// } - -// // Update existing miner token -// client.MinerUpdateToken(MinerTaal, "9999") - -// // Get miner by id -// fmt.Printf("miner token found: %s", client.MinerByName(MinerTaal).Token) -// // Output:miner token found: 9999 -// } - -// // BenchmarkClient_MinerUpdateToken benchmarks the method MinerUpdateToken() -// func BenchmarkClient_MinerUpdateToken(b *testing.B) { -// client, _ := NewClient(nil, nil, nil) -// for i := 0; i < b.N; i++ { -// _ = client.MinerByName(MinerTaal) -// } -// } - -// // TestClient_RemoveMiner will remove a miner by name or ID -// func TestClient_RemoveMiner(t *testing.T) { -// t.Parallel() - -// t.Run("remove a valid miner", func(t *testing.T) { -// client := newTestClient(&mockHTTPDefaultClient{}) - -// // Remove miner -// removed := client.RemoveMiner(client.MinerByName(MinerTaal)) -// assert.Equal(t, true, removed) - -// // Try to get the miner -// miner := client.MinerByName(MinerTaal) -// assert.Nil(t, miner) -// }) - -// t.Run("remove an invalid miner", func(t *testing.T) { -// client := newTestClient(&mockHTTPDefaultClient{}) - -// // Unknown miner -// dummyMiner := &Miner{ -// MinerID: "dummy", -// Name: "dummy", -// Token: "dummy", -// URL: "https://dummy.com", -// } - -// // Remove miner -// removed := client.RemoveMiner(dummyMiner) -// assert.Equal(t, false, removed) -// }) - -// t.Run("remove a nil miner", func(t *testing.T) { -// client := newTestClient(&mockHTTPDefaultClient{}) - -// // Remove miner -// assert.Panics(t, func() { -// removed := client.RemoveMiner(nil) -// assert.Equal(t, false, removed) -// }) -// }) -// } - -// // ExampleClient_MinerUpdateToken example using RemoveMiner() -// func ExampleClient_RemoveMiner() { -// client, err := NewClient(nil, nil, nil) -// if err != nil { -// fmt.Printf("error occurred: %s", err.Error()) -// return -// } - -// // Update existing miner token -// client.RemoveMiner(client.MinerByName(MinerTaal)) - -// // Show response -// fmt.Printf("total miners: %d", len(client.Miners())) -// // Output:total miners: 3 -// } - -// // BenchmarkClient_RemoveMiner benchmarks the method RemoveMiner() -// func BenchmarkClient_RemoveMiner(b *testing.B) { -// client, _ := NewClient(nil, nil, nil) -// miner := client.MinerByName(MinerTaal) -// for i := 0; i < b.N; i++ { -// _ = client.RemoveMiner(miner) -// } -// } - -// // TestDefaultMiners will test the method DefaultMiners() -// func TestDefaultMiners(t *testing.T) { -// t.Run("default json", func(t *testing.T) { -// miners, err := DefaultMiners() -// require.NoError(t, err) -// require.NotNil(t, miners) -// assert.Equal(t, 4, len(miners)) -// assert.Equal(t, MinerTaal, miners[0].Name) -// assert.Equal(t, MinerMempool, miners[1].Name) -// assert.Equal(t, MinerGorillaPool, miners[3].Name) -// assert.Equal(t, MinerMatterpool, miners[2].Name) -// }) -// } +func TestClient_AddMiner(t *testing.T) { + t.Parallel() + + t.Run("valid cases", func(t *testing.T) { + + // Create the list of tests + var tests = []struct { + testCase string + inputMiner Miner + inputAPIs []API + expectedName string + expectedURL string + }{ + { + "valid miner", + Miner{ + MinerID: testMinerID, + Name: "Test", + }, + []API{ + API{ + Token: testMinerToken, + URL: "https://testminer.com", + Type: MAPI, + }, + }, + "Test", + "https://testminer.com", + }, + } + + // Run tests + client := newTestClient(&mockHTTPDefaultClient{}) + for _, test := range tests { + t.Run(test.testCase, func(t *testing.T) { + err := client.AddMiner(test.inputMiner, test.inputAPIs) + assert.NoError(t, err) + + // Get the miner + miner := client.MinerByName(test.inputMiner.Name) + assert.Equal(t, test.expectedName, miner.Name) + assert.Equal(t, test.expectedURL, test.inputAPIs[0].URL) + }) + } + }) + + t.Run("invalid cases", func(t *testing.T) { + + // Create the list of tests + var tests = []struct { + testCase string + inputMiner Miner + inputAPIs []API + }{ + { + "duplicate miner - by name", + Miner{ + MinerID: testMinerID + "123", + Name: "Test", + }, + []API{ + API{ + Token: testMinerToken, + URL: testMinerURL, + Type: MAPI, + }, + }, + }, + { + "duplicate miner - by id", + Miner{ + MinerID: testMinerID, + Name: "Test123", + }, + []API{ + API{ + Token: testMinerToken, + URL: testMinerURL, + Type: MAPI, + }, + }, + }, + { + "missing miner name", + Miner{ + MinerID: testMinerID, + Name: "", + }, + []API{ + API{ + Token: testMinerToken, + URL: testMinerURL, + Type: MAPI, + }, + }, + }, + { + "missing miner url", + Miner{ + MinerID: testMinerID, + Name: "TestURL", + }, + []API{ + API{ + Token: testMinerToken, + URL: testMinerURL, + Type: MAPI, + }, + }, + }, + { + "invalid miner url - http", + Miner{ + MinerID: testMinerID, + Name: "TestURL", + }, + []API{ + API{ + Token: testMinerToken, + URL: "www.domain.com", + Type: MAPI, + }, + }, + }, + { + "invalid miner url - trigger parse error", + Miner{ + MinerID: testMinerID, + Name: "TestURL", + }, + []API{ + API{ + Token: testMinerToken, + URL: "postgres://user:abc{DEf1=ghi@example.com:5432/db?sslmode=require", + Type: MAPI, + }, + }, + }, + } + + // Run tests + client := newTestClient(&mockHTTPDefaultClient{}) + + // Add a miner to start + err := client.AddMiner(Miner{MinerID: testMinerID, Name: "Test"}, []API{API{URL: testMinerURL, Type: Arc}}) + assert.NoError(t, err) + + for _, test := range tests { + t.Run(test.testCase, func(t *testing.T) { + err = client.AddMiner(test.inputMiner, test.inputAPIs) + assert.Error(t, err) + }) + } + }) +} + +// ExampleClient_AddMiner example using AddMiner() +func ExampleClient_AddMiner() { + client, err := NewClient(nil, nil, "", nil, nil) + if err != nil { + fmt.Printf("error occurred: %s", err.Error()) + return + } + + // Add a miner + if err = client.AddMiner(Miner{Name: testMinerName}, []API{API{URL: testMinerURL, Type: Arc}}); err != nil { + fmt.Printf("error occurred: %s", err.Error()) + return + } + + // Get miner by name + fmt.Printf("created new miner named: %s", client.MinerByName(testMinerName).Name) + // Output:created new miner named: TestMiner +} + +// BenchmarkClient_AddMiner benchmarks the method AddMiner() +func BenchmarkClient_AddMiner(b *testing.B) { + client, _ := NewClient(nil, nil, "", nil, nil) + for i := 0; i < b.N; i++ { + _ = client.AddMiner(Miner{Name: testMinerName}, []API{API{URL: testMinerURL, Type: Arc}}) + } +} + +// TestClient_MinerByName tests the method MinerByName() +func TestClient_MinerByName(t *testing.T) { + t.Parallel() + + t.Run("get valid miner", func(t *testing.T) { + client := newTestClient(&mockHTTPDefaultClient{}) + + // Add a valid miner + err := client.AddMiner(Miner{ + Name: testMinerName, + }, []API{API{URL: testMinerURL, Type: Arc}}) + assert.NoError(t, err) + + // Get valid miner + miner := client.MinerByName(testMinerName) + assert.NotNil(t, miner) + }) + + t.Run("get invalid miner", func(t *testing.T) { + client := newTestClient(&mockHTTPDefaultClient{}) + + // Add a valid miner + err := client.AddMiner(Miner{ + Name: testMinerName, + }, []API{API{URL: testMinerURL, Type: Arc}}, + ) + assert.NoError(t, err) + + // Get invalid miner + miner := client.MinerByName("Unknown") + assert.Nil(t, miner) + }) +} + +// ExampleClient_MinerByName example using MinerByName() +func ExampleClient_MinerByName() { + client, err := NewClient(nil, nil, "", nil, nil) + if err != nil { + fmt.Printf("error occurred: %s", err.Error()) + return + } + + // Add a miner + if err = client.AddMiner(Miner{Name: testMinerName}, []API{API{URL: testMinerURL, Type: Arc}}); err != nil { + fmt.Printf("error occurred: %s", err.Error()) + return + } + + // Get miner by name + fmt.Printf("created new miner named: %s", client.MinerByName(testMinerName).Name) + // Output:created new miner named: TestMiner +} + +// BenchmarkClient_MinerByName benchmarks the method MinerByName() +func BenchmarkClient_MinerByName(b *testing.B) { + client, _ := NewClient(nil, nil, "", nil, nil) + _ = client.AddMiner(Miner{Name: testMinerName, URL: testMinerURL}) + for i := 0; i < b.N; i++ { + _ = client.MinerByName(testMinerName) + } +} + +// TestClient_MinerByID tests the method MinerByID() +func TestClient_MinerByID(t *testing.T) { + t.Parallel() + + t.Run("get valid miner", func(t *testing.T) { + client := newTestClient(&mockHTTPDefaultClient{}) + + // Add a valid miner + err := client.AddMiner(Miner{ + Name: testMinerName, + MinerID: testMinerID, + URL: testMinerURL, + }) + assert.NoError(t, err) + + // Get valid miner + miner := client.MinerByID(testMinerID) + assert.NotNil(t, miner) + }) + + t.Run("get invalid miner", func(t *testing.T) { + client := newTestClient(&mockHTTPDefaultClient{}) + + // Add a valid miner + err := client.AddMiner(Miner{ + Name: testMinerName, + MinerID: testMinerID, + URL: testMinerURL, + }) + assert.NoError(t, err) + + // Get invalid miner + miner := client.MinerByID("00000") + assert.Nil(t, miner) + }) +} + +// ExampleClient_MinerByID example using MinerByID() +func ExampleClient_MinerByID() { + client, err := NewClient(nil, nil, nil) + if err != nil { + fmt.Printf("error occurred: %s", err.Error()) + return + } + + // Add a miner + if err = client.AddMiner(Miner{Name: testMinerName, MinerID: testMinerID, URL: testMinerURL}); err != nil { + fmt.Printf("error occurred: %s", err.Error()) + return + } + + // Get miner by id + fmt.Printf("created new miner named: %s", client.MinerByID(testMinerID).Name) + // Output:created new miner named: TestMiner +} + +// BenchmarkClient_MinerByID benchmarks the method MinerByID() +func BenchmarkClient_MinerByID(b *testing.B) { + client, _ := NewClient(nil, nil, nil) + _ = client.AddMiner(Miner{Name: testMinerName, MinerID: testMinerID, URL: testMinerURL}) + for i := 0; i < b.N; i++ { + _ = client.MinerByID(testMinerID) + } +} + +// TestClient_MinerUpdateToken tests the method MinerUpdateToken() +func TestClient_MinerUpdateToken(t *testing.T) { + t.Parallel() + + t.Run("update valid miner", func(t *testing.T) { + client := newTestClient(&mockHTTPDefaultClient{}) + + // Add a valid miner + err := client.AddMiner(Miner{ + Name: testMinerName, + MinerID: testMinerID, + Token: testMinerToken, + URL: testMinerURL, + }) + assert.NoError(t, err) + + // Update a valid miner token + client.MinerUpdateToken(testMinerName, "99999") + + // Get valid miner + miner := client.MinerByID(testMinerID) + assert.NotNil(t, miner) + assert.Equal(t, "99999", miner.Token) + }) + + t.Run("update unknown miner", func(t *testing.T) { + client := newTestClient(&mockHTTPDefaultClient{}) + + // Add a valid miner + err := client.AddMiner(Miner{ + Name: testMinerName, + MinerID: testMinerID, + Token: testMinerToken, + URL: testMinerURL, + }) + assert.NoError(t, err) + + // Update a invalid miner token + client.MinerUpdateToken("Unknown", "99999") + }) +} + +// ExampleClient_MinerUpdateToken example using MinerUpdateToken() +func ExampleClient_MinerUpdateToken() { + client, err := NewClient(nil, nil, "", nil, nil) + if err != nil { + fmt.Printf("error occurred: %s", err.Error()) + return + } + + // Update existing miner token + client.MinerUpdateToken(MinerTaal, "9999") + + taal := client.MinerByName(MinerTaal) + + // Get miner by id + fmt.Printf("miner token found: %s", client.MinerByName(MinerTaal).Token) + // Output:miner token found: 9999 +} + +// BenchmarkClient_MinerUpdateToken benchmarks the method MinerUpdateToken() +func BenchmarkClient_MinerUpdateToken(b *testing.B) { + client, _ := NewClient(nil, nil, nil) + for i := 0; i < b.N; i++ { + _ = client.MinerByName(MinerTaal) + } +} + +// TestClient_RemoveMiner will remove a miner by name or ID +func TestClient_RemoveMiner(t *testing.T) { + t.Parallel() + + t.Run("remove a valid miner", func(t *testing.T) { + client := newTestClient(&mockHTTPDefaultClient{}) + + // Remove miner + removed := client.RemoveMiner(client.MinerByName(MinerTaal)) + assert.Equal(t, true, removed) + + // Try to get the miner + miner := client.MinerByName(MinerTaal) + assert.Nil(t, miner) + }) + + t.Run("remove an invalid miner", func(t *testing.T) { + client := newTestClient(&mockHTTPDefaultClient{}) + + // Unknown miner + dummyMiner := &Miner{ + MinerID: "dummy", + Name: "dummy", + } + + // Remove miner + removed := client.RemoveMiner(dummyMiner) + assert.Equal(t, false, removed) + }) + + t.Run("remove a nil miner", func(t *testing.T) { + client := newTestClient(&mockHTTPDefaultClient{}) + + // Remove miner + assert.Panics(t, func() { + removed := client.RemoveMiner(nil) + assert.Equal(t, false, removed) + }) + }) +} + +// ExampleClient_MinerUpdateToken example using RemoveMiner() +func ExampleClient_RemoveMiner() { + client, err := NewClient(nil, nil, "", nil, nil) + if err != nil { + fmt.Printf("error occurred: %s", err.Error()) + return + } + + // Update existing miner token + client.RemoveMiner(client.MinerByName(MinerTaal)) + + // Show response + fmt.Printf("total miners: %d", len(client.Miners())) + // Output:total miners: 3 +} + +// BenchmarkClient_RemoveMiner benchmarks the method RemoveMiner() +func BenchmarkClient_RemoveMiner(b *testing.B) { + client, _ := NewClient(nil, nil, "", nil, nil) + miner := client.MinerByName(MinerTaal) + for i := 0; i < b.N; i++ { + _ = client.RemoveMiner(miner) + } +} + +// TestDefaultMiners will test the method DefaultMiners() +func TestDefaultMiners(t *testing.T) { + t.Run("default json", func(t *testing.T) { + miners, err := DefaultMiners() + require.NoError(t, err) + require.NotNil(t, miners) + assert.Equal(t, 4, len(miners)) + assert.Equal(t, MinerTaal, miners[0].Name) + assert.Equal(t, MinerMempool, miners[1].Name) + assert.Equal(t, MinerGorillaPool, miners[3].Name) + assert.Equal(t, MinerMatterpool, miners[2].Name) + }) +} // ExampleDefaultMiners example using DefaultMiners() func ExampleDefaultMiners() { diff --git a/interface.go b/interface.go index 97dd4bb..f671b63 100644 --- a/interface.go +++ b/interface.go @@ -15,7 +15,7 @@ type QuoteService interface { // MinerService is the MinerCraft miner related methods type MinerService interface { - AddMiner(miner Miner) error + AddMiner(miner Miner, apis []API) error MinerByID(minerID string) *Miner MinerByName(name string) *Miner Miners() []*Miner