File: mock.go

package info (click to toggle)
golang-github-linode-linodego 1.55.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,112 kB
  • sloc: makefile: 96; sh: 52; python: 24
file content (130 lines) | stat: -rw-r--r-- 2,864 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package testutil

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"reflect"
	"regexp"
	"strings"
	"testing"

	"github.com/google/go-cmp/cmp"
	"github.com/jarcoal/httpmock"
	"golang.org/x/oauth2"
)

var validTestAPIKey = "NOTANAPIKEY"

func MockRequestURL(path string) *regexp.Regexp {
	return regexp.MustCompile(fmt.Sprintf("/[a-zA-Z0-9]+/%s", strings.TrimPrefix(path, "/")))
}

func MockRequestBodyValidate(t *testing.T, expected any, response any) httpmock.Responder {
	t.Helper()

	return func(request *http.Request) (*http.Response, error) {
		eType := reflect.TypeOf(expected)
		result := reflect.New(eType)

		i := result.Interface()

		data, err := io.ReadAll(request.Body)
		if err != nil {
			t.Fatal(err)
		}

		if err := json.Unmarshal(data, &i); err != nil {
			t.Fatal(err)
		}

		// Deref the pointer if necessary
		if result.Kind() == reflect.Pointer {
			result = result.Elem()
		}

		resultValue := result.Interface()

		if !reflect.DeepEqual(expected, resultValue) {
			t.Fatalf("request body does not match request options: %s", cmp.Diff(expected, resultValue))
		}

		return httpmock.NewJsonResponse(http.StatusOK, response)
	}
}

func MockRequestBodyValidateNoBody(t *testing.T, response any) httpmock.Responder {
	t.Helper()

	return func(request *http.Request) (*http.Response, error) {
		if request.Body != nil {
			t.Fatal("got request body when no request body was expected")
		}

		return httpmock.NewJsonResponse(http.StatusOK, response)
	}
}

// CreateMockClient is generic because importing the linodego package will result
// in a cyclic dependency. This pattern isn't ideal but works for now.
func CreateMockClient[T any](t *testing.T, createFunc func(*http.Client) T) *T {
	t.Helper()

	tokenSource := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: validTestAPIKey})

	client := &http.Client{
		Transport: &oauth2.Transport{
			Source: tokenSource,
		},
	}
	httpmock.ActivateNonDefault(client)

	t.Cleanup(func() {
		httpmock.DeactivateAndReset()
	})

	result := createFunc(client)

	return &result
}

type Logger interface {
	Errorf(format string, v ...interface{})
	Warnf(format string, v ...interface{})
	Debugf(format string, v ...interface{})
}

func CreateLogger() *TestLogger {
	l := &TestLogger{L: log.New(os.Stderr, "", log.Ldate|log.Lmicroseconds)}
	return l
}

var _ Logger = (*TestLogger)(nil)

type TestLogger struct {
	L *log.Logger
}

func (l *TestLogger) Errorf(format string, v ...interface{}) {
	l.outputf("ERROR RESTY "+format, v...)
}

func (l *TestLogger) Warnf(format string, v ...interface{}) {
	l.outputf("WARN RESTY "+format, v...)
}

func (l *TestLogger) Debugf(format string, v ...interface{}) {
	l.outputf("DEBUG RESTY "+format, v...)
}

func (l *TestLogger) outputf(format string, v ...interface{}) {
	if len(v) == 0 {
		l.L.Print(format)
		return
	}

	l.L.Printf(format, v...)
}