Skip to content

Commit

Permalink
feat(go): add client tests (#2552)
Browse files Browse the repository at this point in the history
  • Loading branch information
millotp authored Jan 18, 2024
1 parent 02a40de commit 30a1f27
Show file tree
Hide file tree
Showing 55 changed files with 396 additions and 643 deletions.
2 changes: 1 addition & 1 deletion .github/.cache_version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.7
1.0.8
2 changes: 1 addition & 1 deletion clients/algoliasearch-client-go/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<a href="https://pkg.go.dev/github.com/algolia/algoliasearch-client-go/v4"><img src="https://pkg.go.dev/badge/github.com/algolia/algoliasearch-client-go/v4" alt="GoDoc"></img></a>
<a href="https://goreportcard.com/report/github.com/algolia/algoliasearch-client-go"><img src="https://goreportcard.com/badge/github.com/algolia/algoliasearch-client-go" alt="Go Report Card"></img></a>
<a href="https://github.com/algolia/algoliasearch-client-go/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"></img></a>
<img src="https://img.shields.io/badge/Go-%3E=1.19-green.svg" alt="Supported version"></img></a>
<img src="https://img.shields.io/badge/Go-%3E=1.21-green.svg" alt="Supported version"></img></a>
</p>
</p>

Expand Down
22 changes: 22 additions & 0 deletions clients/algoliasearch-client-go/algolia/transport/configuration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package transport

import (
"time"

"github.com/algolia/algoliasearch-client-go/v4/algolia/compression"
)

type Configuration struct {
AppID string
ApiKey string

Hosts []string
DefaultHeader map[string]string
UserAgent string
Debug bool
Requester Requester
ReadTimeout time.Duration
WriteTimeout time.Duration
ConnectTimeout time.Duration
Compression compression.Compression
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,37 +22,40 @@ const (
// the Algolia API client (by wrapping it in a user-defined instance of
// transport.Requester) but would like to wrap it into a middleware layer or
// pass it to an HTTP interceptor.
func DefaultHTTPClient() *http.Client {
return &http.Client{
Transport: defaultTransport,
func DefaultHTTPClient(connectTimeout *time.Duration) *http.Client {
connectTimeoutValue := DefaultConnectTimeout
if connectTimeout != nil {
connectTimeoutValue = *connectTimeout
}
}

var defaultTransport = &http.Transport{
DialContext: (&net.Dialer{
KeepAlive: DefaultKeepAliveDuration,
Timeout: DefaultConnectTimeout,
}).DialContext,
DisableKeepAlives: false,
MaxIdleConnsPerHost: DefaultMaxIdleConnsPerHost,
Proxy: http.ProxyFromEnvironment,
TLSHandshakeTimeout: DefaultTLSHandshakeTimeout,
return &http.Client{
Transport: &http.Transport{
DialContext: (&net.Dialer{
KeepAlive: DefaultKeepAliveDuration,
Timeout: connectTimeoutValue,
}).DialContext,
DisableKeepAlives: false,
MaxIdleConnsPerHost: DefaultMaxIdleConnsPerHost,
Proxy: http.ProxyFromEnvironment,
TLSHandshakeTimeout: DefaultTLSHandshakeTimeout,
},
}
}

type Requester interface {
Request(req *http.Request) (*http.Response, error)
Request(req *http.Request, timeout time.Duration, connectTimeout time.Duration) (*http.Response, error)
}

type defaultRequester struct {
client *http.Client
}

func newDefaultRequester() *defaultRequester {
func NewDefaultRequester(connectTimeout *time.Duration) *defaultRequester {
return &defaultRequester{
client: DefaultHTTPClient(),
client: DefaultHTTPClient(connectTimeout),
}
}

func (r *defaultRequester) Request(req *http.Request) (*http.Response, error) {
func (r *defaultRequester) Request(req *http.Request, _, _ time.Duration) (*http.Response, error) {
return r.client.Do(req)
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,37 @@ import (
"github.com/algolia/algoliasearch-client-go/v4/algolia/call"
"github.com/algolia/algoliasearch-client-go/v4/algolia/compression"
"github.com/algolia/algoliasearch-client-go/v4/algolia/debug"
"github.com/algolia/algoliasearch-client-go/v4/algolia/internal/errs"
"github.com/algolia/algoliasearch-client-go/v4/algolia/errs"
)

type Transport struct {
requester Requester
retryStrategy *RetryStrategy
compression compression.Compression
requester Requester
retryStrategy *RetryStrategy
compression compression.Compression
connectTimeout time.Duration
}

func New(
hosts []*StatefulHost,
requester Requester,
readTimeout time.Duration,
writeTimeout time.Duration,
connectTimeout time.Duration,
compression compression.Compression,
) *Transport {
if connectTimeout == 0 {
connectTimeout = DefaultConnectTimeout
}

if requester == nil {
requester = newDefaultRequester()
requester = NewDefaultRequester(&connectTimeout)
}

return &Transport{
requester: requester,
retryStrategy: newRetryStrategy(hosts, readTimeout, writeTimeout),
compression: compression,
requester: requester,
retryStrategy: newRetryStrategy(hosts, readTimeout, writeTimeout),
compression: compression,
connectTimeout: connectTimeout,
}
}

Expand All @@ -56,7 +63,7 @@ func (t *Transport) Request(ctx context.Context, req *http.Request, k call.Kind)
// cancelled` error may happen when the body is read.
perRequestCtx, cancel := context.WithTimeout(ctx, h.timeout)
req = req.WithContext(perRequestCtx)
res, err := t.request(req, h.host)
res, err := t.request(req, h.host, h.timeout, t.connectTimeout)

code := 0
if res != nil {
Expand Down Expand Up @@ -98,12 +105,12 @@ func (t *Transport) Request(ctx context.Context, req *http.Request, k call.Kind)
return nil, errs.ErrNoMoreHostToTry
}

func (t *Transport) request(req *http.Request, host string) (*http.Response, error) {
func (t *Transport) request(req *http.Request, host string, timeout time.Duration, connectTimeout time.Duration) (*http.Response, error) {
req.URL.Scheme = "https"
req.URL.Host = host

debug.Display(req)
res, err := t.requester.Request(req)
res, err := t.requester.Request(req, timeout, connectTimeout)
debug.Display(res)

if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,8 @@ package transport

import (
"math/rand"
"time"
)

func init() {
rand.Seed(int64(time.Now().Nanosecond()))
}

func Shuffle(hosts []*StatefulHost) []*StatefulHost {
if hosts == nil {
return nil
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,11 @@
/*
A/B Testing API
API powering the A/B Testing feature of Algolia.
API version: 1.0.0
*/

// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.

package abtesting
package utils

import (
"encoding/json"
"reflect"
"time"

"github.com/algolia/algoliasearch-client-go/v4/algolia/internal/errs"
"github.com/algolia/algoliasearch-client-go/v4/algolia/errs"
)

// PtrBool is a helper routine that returns a pointer to given boolean value.
Expand Down Expand Up @@ -330,8 +320,8 @@ func (v *NullableTime) UnmarshalJSON(src []byte) error {
return json.Unmarshal(src, &v.value)
}

// isNilorEmpty checks if an input is nil or empty
func isNilorEmpty(i any) bool {
// IsNilOrEmpty checks if an input is nil or empty.
func IsNilOrEmpty(i any) bool {
if i == nil {
return true
}
Expand Down
2 changes: 1 addition & 1 deletion clients/algoliasearch-client-go/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/algolia/algoliasearch-client-go/v4

go 1.19
go 1.21

require github.com/go-playground/validator/v10 v10.17.0

Expand Down
4 changes: 3 additions & 1 deletion config/generation.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,12 @@ export const patterns = [
'clients/algoliasearch-client-go/algolia/**',
'!clients/algoliasearch-client-go/.github/**',
'!clients/algoliasearch-client-go/*',
'!clients/algoliasearch-client-go/algolia/internal/**',
'!clients/algoliasearch-client-go/algolia/transport/**',
'!clients/algoliasearch-client-go/algolia/errs/**',
'!clients/algoliasearch-client-go/algolia/call/*',
'!clients/algoliasearch-client-go/algolia/compression/*',
'!clients/algoliasearch-client-go/algolia/debug/*',
'!clients/algoliasearch-client-go/algolia/utils/*',

'tests/output/go/go.sum',

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ public void processOpts() {
supportingFiles.clear();
supportingFiles.add(new SupportingFile("configuration.mustache", "", "configuration.go"));
supportingFiles.add(new SupportingFile("client.mustache", "", "client.go"));
supportingFiles.add(new SupportingFile("response.mustache", "", "response.go"));
supportingFiles.add(new SupportingFile("utils.mustache", "", "utils.go"));

try {
Helpers.generateServer(client, additionalProperties);
Expand All @@ -76,11 +74,11 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs)

for (Map.Entry<String, ModelsMap> entry : models.entrySet()) {
String modelName = entry.getKey();
ModelsMap model = entry.getValue();
CodegenModel model = entry.getValue().getModels().get(0).getModel();

// for some reason the property additionalPropertiesIsAnyType is not propagated to the
// property
for (CodegenProperty prop : model.getModels().get(0).getModel().getVars()) {
for (CodegenProperty prop : model.getVars()) {
ModelsMap propertyModel = models.get(prop.datatypeWithEnum);
if (propertyModel != null && propertyModel.getModels().get(0).getModel().getAdditionalPropertiesIsAnyType()) {
// consider it the same as model for our purpose
Expand All @@ -92,6 +90,8 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs)
prop.dataType = prop.dataType.replace("[]*[]", "[][]");
prop.vendorExtensions.put("x-go-base-type", prop.dataType);
}

prop.dataType = prop.dataType.replace("NullableBool", "utils.NullableBool");
}
}
return models;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,9 @@

import com.algolia.codegen.exceptions.GeneratorException;
import java.util.*;
import org.openapitools.codegen.SupportingFile;

public class GoCTSManager implements CTSManager {

@Override
public void addTestsSupportingFiles(List<SupportingFile> supportingFiles) {
supportingFiles.add(new SupportingFile("tests/common.mustache", "tests/output/go/tests/requests", "common.go"));
}

@Override
public void addDataToBundle(Map<String, Object> bundle) throws GeneratorException {
Object clientPrefix = bundle.get("clientPrefix");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ class Step {
class Expected {

public String type;
public Object error;
public String error;
public Object match;
}
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ private Map<String, Object> traverseParams(
testOutput.put("isParentFreeFormObject", isParentFreeFormObject);

if (param == null) {
handleNull(testOutput);
handleNull(spec, testOutput);
} else if (spec.getIsArray()) {
handleArray(paramName, param, testOutput, spec, suffix);
} else if (spec.getIsEnum()) {
Expand All @@ -155,7 +155,7 @@ private Map<String, Object> traverseParams(
handleModel(paramName, param, testOutput, spec, baseType, parent, suffix);
} else if (baseType.equals("Object")) {
// not var, no item, pure free form
handleObject(paramName, param, testOutput, suffix);
handleObject(paramName, param, testOutput, true, suffix);
} else if (spec.getIsMap()) {
// free key but only one type
handleMap(paramName, param, testOutput, spec, suffix);
Expand Down Expand Up @@ -188,11 +188,11 @@ private Map<String, Object> traverseParamsWithoutSpec(String paramName, Object p
}

if (param == null) {
handleNull(testOutput);
handleNull(null, testOutput);
} else if (param instanceof List) {
handleArray(paramName, param, testOutput, null, suffix);
} else if (param instanceof Map) {
handleObject(paramName, param, testOutput, suffix);
handleObject(paramName, param, testOutput, false, suffix);
} else {
handlePrimitive(param, testOutput, null);
}
Expand All @@ -205,6 +205,7 @@ private Map<String, Object> createDefaultOutput() {
// we need to set all types to false otherwise mustache will read the one from the parent
// context and run into a infinite loop
testOutput.put("isObject", false);
testOutput.put("isNullObject", false);
testOutput.put("isArray", false);
testOutput.put("isNull", false);
testOutput.put("isFreeFormObject", false);
Expand All @@ -224,8 +225,11 @@ private Map<String, Object> createDefaultOutput() {
return testOutput;
}

private void handleNull(Map<String, Object> testOutput) {
private void handleNull(IJsonSchemaValidationProperties spec, Map<String, Object> testOutput) {
testOutput.put("isNull", true);
if (spec.getIsModel() || spec instanceof CodegenModel) {
testOutput.put("isNullObject", true);
}
}

private void handleArray(
Expand Down Expand Up @@ -385,7 +389,8 @@ private void handleModel(
testOutput.put("optionalValue", optionalValues);
}

private void handleObject(String paramName, Object param, Map<String, Object> testOutput, int suffix) throws CTSException {
private void handleObject(String paramName, Object param, Map<String, Object> testOutput, boolean isSimpleObject, int suffix)
throws CTSException {
Map<String, Object> vars = (Map<String, Object>) param;

List<Object> values = new ArrayList<>();
Expand All @@ -394,11 +399,8 @@ private void handleObject(String paramName, Object param, Map<String, Object> te
objSpec.dataType = inferDataType(entry.getValue(), objSpec, null);
values.add(traverseParams(entry.getKey(), entry.getValue(), objSpec, paramName, suffix + 1, true));
}
// sometimes it's really just an object
if (testOutput.getOrDefault("objectName", "").equals("Object")) {
testOutput.put("isSimpleObject", true);
}

testOutput.put("isSimpleObject", isSimpleObject);
testOutput.put("isFreeFormObject", true);
testOutput.put("value", values);
}
Expand Down Expand Up @@ -493,6 +495,8 @@ private String getObjectNameForLanguage(String objectName) {
return "bool";
case "List":
return "Array";
case "Object":
return "map[string]any";
}
}
return Helpers.capitalize(objectName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public void run(Map<String, CodegenModel> models, Map<String, CodegenOperation>
try {
Map<String, Object> testOut = new HashMap<>();
List<Object> steps = new ArrayList<>();
testOut.put("inClientTest", true);
testOut.put("testName", test.testName);
testOut.put("testIndex", testIndex++);
testOut.put("autoCreateClient", test.autoCreateClient);
Expand Down Expand Up @@ -101,6 +102,10 @@ public void run(Map<String, CodegenModel> models, Map<String, CodegenOperation>
if (step.expected.error != null) {
stepOut.put("isError", true);
stepOut.put("expectedError", step.expected.error);
if (language.equals("go") && step.path != null) {
// hack for go that use PascalCase, but just in the operationID
stepOut.put("expectedError", step.expected.error.replace(step.path, Helpers.toPascalCase(step.path)));
}
} else if (step.expected.match != null) {
if (step.expected.match instanceof Map) {
Map<String, Object> match = new HashMap<>();
Expand Down
Loading

0 comments on commit 30a1f27

Please sign in to comment.