package paypal import ( "context" "fmt" "math/rand" "net/http" "strings" "testing" "time" "github.com/stretchr/testify/assert" ) const alphabet = "abcedfghijklmnopqrstuvwxyz" var testClientID = "AXy9orp-CDaHhBZ9C78QHW2BKZpACgroqo85_NIOa9mIfJ9QnSVKzY-X_rivR_fTUUr6aLjcJsj6sDur" var testSecret = "EBoIiUSkCKeSk49hHSgTem1qnjzzJgRQHDEHvGpzlLEf_nIoJd91xu8rPOBDCdR_UYNKVxJE-UgS2iCw" func RandomString(n int) string { var sb strings.Builder k := len(alphabet) for i := 0; i < n; i++ { c := alphabet[rand.Intn(k)] sb.WriteByte(c) } return sb.String() } func createRandomProduct(t *testing.T) Product { //create a product productData := Product{ Name: RandomString(10), Description: RandomString(100), Category: ProductCategorySoftware, Type: ProductTypeService, ImageUrl: "https://example.com/image.png", HomeUrl: "https://example.com", } return productData } // this is a simple copy of the SendWithAuth method, used to // test the Lock and Unlock methods of the private mutex field // of Client structure. func (c *Client) sendWithAuth(req *http.Request, v interface{}) error { c.mu.Lock() defer c.mu.Unlock() if c.Token == nil || (!c.tokenExpiresAt.IsZero() && time.Until(c.tokenExpiresAt) < RequestNewTokenBeforeExpiresIn) { if _, err := c.GetAccessToken(req.Context()); err != nil { return err } } req.Header.Set("Authorization", "Bearer "+c.Token.Token) return c.Send(req, v) } // this method is used to invoke the sendWithAuth method, which will then check // operationally the privated mutex field of Client structure. func (c *Client) createProduct(ctx context.Context, product Product) (*CreateProductResponse, error) { req, err := c.NewRequest(ctx, http.MethodPost, fmt.Sprintf("%s%s", c.APIBase, "/v1/catalogs/products"), product) response := &CreateProductResponse{} if err != nil { return response, err } err = c.sendWithAuth(req, response) return response, err } func TestClientMutex(t *testing.T) { c, _ := NewClient(testClientID, testSecret, APIBaseSandBox) c.GetAccessToken(context.Background()) // Operational testing of the private mutex field n_iter := 2 errs := make(chan error) for i := 0; i < n_iter; i++ { go func() { _, err := c.createProduct(context.Background(), createRandomProduct(t)) errs <- err }() } for i := 0; i < n_iter; i++ { err := <-errs assert.Equal(t, nil, err) } }