Skip to content

Commit e1576dc

Browse files
Thomas StrombergThomas Stromberg
authored andcommitted
add integration tests
1 parent 0493e48 commit e1576dc

File tree

13 files changed

+4612
-0
lines changed

13 files changed

+4612
-0
lines changed

.github/workflows/test.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Test
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
matrix:
14+
go-version: [ '1.22', '1.23' ]
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- name: Set up Go
20+
uses: actions/setup-go@v5
21+
with:
22+
go-version: ${{ matrix.go-version }}
23+
24+
- name: Run tests
25+
run: make test
26+
27+
- name: Run linter
28+
run: make lint

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,6 @@ go.work.sum
3030
# Editor/IDE
3131
# .idea/
3232
# .vscode/
33+
34+
out/
35+

.golangci.yml

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
## Golden config for golangci-lint - strict, but within the realm of what Go authors might use.
2+
#
3+
# This is tied to the version of golangci-lint listed in the Makefile, usage with other
4+
# versions of golangci-lint will yield errors and/or false positives.
5+
#
6+
# Docs: https://github.com/golangci/golangci-lint/blob/HEAD/.golangci.reference.yml
7+
# Based heavily on https://gist.github.com/maratori/47a4d00457a92aa426dbd48a18776322
8+
9+
version: "2"
10+
11+
issues:
12+
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
13+
max-issues-per-linter: 0
14+
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
15+
max-same-issues: 0
16+
17+
formatters:
18+
enable:
19+
# - gci
20+
# - gofmt
21+
- gofumpt
22+
# - goimports
23+
# - golines
24+
- swaggo
25+
26+
settings:
27+
golines:
28+
# Default: 100
29+
max-len: 120
30+
31+
linters:
32+
default: all
33+
disable:
34+
# linters that give advice contrary to what the Go authors advise
35+
- decorder # checks declaration order and count of types, constants, variables and functions
36+
- dupword # [useless without config] checks for duplicate words in the source code
37+
- exhaustruct # [highly recommend to enable] checks if all structure fields are initialized
38+
- forcetypeassert # [replaced by errcheck] finds forced type assertions
39+
- ginkgolinter # [if you use ginkgo/gomega] enforces standards of using ginkgo and gomega
40+
- gochecknoglobals # checks that no global variables exist
41+
- cyclop # replaced by revive
42+
- gocyclo # replaced by revive
43+
- forbidigo # needs configuration to be useful
44+
- funlen # replaced by revive
45+
- godox # TODO's are OK
46+
- ireturn # It's OK
47+
- musttag
48+
- nonamedreturns
49+
- goconst # finds repeated strings that could be replaced by a constant
50+
- goheader # checks is file header matches to pattern
51+
- gomodguard # [use more powerful depguard] allow and block lists linter for direct Go module dependencies
52+
- gomoddirectives
53+
- err113 # bad advice about dynamic errors
54+
- lll # [replaced by golines] reports long lines
55+
- mnd # detects magic numbers, duplicated by revive
56+
- nlreturn # [too strict and mostly code is not more readable] checks for a new line before return and branch statements to increase code clarity
57+
- noinlineerr # disallows inline error handling `if err := ...; err != nil {`
58+
- prealloc # [premature optimization, but can be used in some cases] finds slice declarations that could potentially be preallocated
59+
- tagliatelle # needs configuration
60+
- testableexamples # checks if examples are testable (have an expected output)
61+
- testpackage # makes you use a separate _test package
62+
- paralleltest # not every test should be in parallel
63+
- wrapcheck # not required
64+
- wsl # [too strict and mostly code is not more readable] whitespace linter forces you to use empty lines
65+
- wsl_v5 # [too strict and mostly code is not more readable] add or remove empty lines
66+
- zerologlint # detects the wrong usage of zerolog that a user forgets to dispatch zerolog.Event
67+
68+
# All settings can be found here https://github.com/golangci/golangci-lint/blob/HEAD/.golangci.reference.yml
69+
settings:
70+
depguard:
71+
rules:
72+
"deprecated":
73+
files:
74+
- "$all"
75+
deny:
76+
- pkg: github.com/golang/protobuf
77+
desc: Use google.golang.org/protobuf instead, see https://developers.google.com/protocol-buffers/docs/reference/go/faq#modules
78+
- pkg: github.com/satori/go.uuid
79+
desc: Use github.com/google/uuid instead, satori's package is not maintained
80+
- pkg: github.com/gofrs/uuid$
81+
desc: Use github.com/gofrs/uuid/v5 or later, it was not a go module before v5
82+
"non-test files":
83+
files:
84+
- "!$test"
85+
deny:
86+
- pkg: math/rand$
87+
desc: Use math/rand/v2 instead, see https://go.dev/blog/randv2
88+
- pkg: "github.com/sirupsen/logrus"
89+
desc: not allowed
90+
- pkg: "github.com/pkg/errors"
91+
desc: Should be replaced by standard lib errors package
92+
93+
dupl:
94+
# token count (default: 150)
95+
threshold: 300
96+
97+
embeddedstructfieldcheck:
98+
# Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.
99+
forbid-mutex: true
100+
101+
errcheck:
102+
# Report about not checking of errors in type assertions: `a := b.(MyStruct)`.
103+
check-type-assertions: true
104+
check-blank: true
105+
106+
exhaustive:
107+
# Program elements to check for exhaustiveness.
108+
# Default: [ switch ]
109+
check:
110+
- switch
111+
- map
112+
default-signifies-exhaustive: true
113+
114+
fatcontext:
115+
# Check for potential fat contexts in struct pointers.
116+
# May generate false positives.
117+
# Default: false
118+
check-struct-pointers: true
119+
120+
funcorder:
121+
# Checks if the exported methods of a structure are placed before the non-exported ones.
122+
struct-method: false
123+
124+
gocognit:
125+
min-complexity: 55
126+
127+
gocritic:
128+
enable-all: true
129+
disabled-checks:
130+
- paramTypeCombine
131+
# The list of supported checkers can be found at https://go-critic.com/overview.
132+
settings:
133+
captLocal:
134+
# Whether to restrict checker to params only.
135+
paramsOnly: false
136+
underef:
137+
# Whether to skip (*x).method() calls where x is a pointer receiver.
138+
skipRecvDeref: false
139+
hugeParam:
140+
# Default: 80
141+
sizeThreshold: 200
142+
143+
govet:
144+
enable-all: true
145+
146+
godot:
147+
scope: toplevel
148+
149+
inamedparam:
150+
# Skips check for interface methods with only a single parameter.
151+
skip-single-param: true
152+
153+
nakedret:
154+
# Default: 30
155+
max-func-lines: 7
156+
157+
nestif:
158+
min-complexity: 15
159+
160+
nolintlint:
161+
# Exclude following linters from requiring an explanation.
162+
# Default: []
163+
allow-no-explanation: [funlen, gocognit, golines]
164+
# Enable to require an explanation of nonzero length after each nolint directive.
165+
require-explanation: true
166+
# Enable to require nolint directives to mention the specific linter being suppressed.
167+
require-specific: true
168+
169+
revive:
170+
enable-all-rules: true
171+
rules:
172+
- name: add-constant
173+
severity: warning
174+
disabled: true
175+
- name: cognitive-complexity
176+
disabled: true # prefer maintidx
177+
- name: cyclomatic
178+
disabled: true # prefer maintidx
179+
- name: function-length
180+
arguments: [150, 225]
181+
- name: line-length-limit
182+
arguments: [150]
183+
- name: nested-structs
184+
disabled: true
185+
- name: max-public-structs
186+
arguments: [10]
187+
- name: flag-parameter # fixes are difficult
188+
disabled: true
189+
190+
rowserrcheck:
191+
# database/sql is always checked.
192+
# Default: []
193+
packages:
194+
- github.com/jmoiron/sqlx
195+
196+
perfsprint:
197+
# optimize fmt.Sprintf("x: %s", y) into "x: " + y
198+
strconcat: false
199+
200+
staticcheck:
201+
checks:
202+
- all
203+
204+
usetesting:
205+
# Enable/disable `os.TempDir()` detections.
206+
# Default: false
207+
os-temp-dir: true
208+
209+
varnamelen:
210+
max-distance: 75
211+
min-name-length: 2
212+
check-receivers: false
213+
ignore-names:
214+
- r
215+
- w
216+
- f
217+
- err
218+
219+
exclusions:
220+
# Default: []
221+
presets:
222+
- common-false-positives
223+
rules:
224+
# Allow "err" and "ok" vars to shadow existing declarations, otherwise we get too many false positives.
225+
- text: '^shadow: declaration of "(err|ok)" shadows declaration'
226+
linters:
227+
- govet
228+
- text: "parameter 'ctx' seems to be unused, consider removing or renaming it as _"
229+
linters:
230+
- revive
231+
- path: _test\.go
232+
linters:
233+
- dupl
234+
- gosec
235+
- godot
236+
- govet # alignment
237+
- noctx
238+
- perfsprint
239+
- revive
240+
- varnamelen

Makefile

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
.PHONY: test integration lint build clean
2+
3+
test:
4+
go test -v -race -cover ./...
5+
6+
DS9_TEST_PROJECT ?= integration-testing-476513
7+
DS9_TEST_DATABASE ?= ds9-test
8+
DS9_TEST_LOCATION ?= us-central1
9+
10+
integration:
11+
@echo "==> Setting up integration test environment"
12+
@echo " Project: $(DS9_TEST_PROJECT)"
13+
@echo " Database: $(DS9_TEST_DATABASE)"
14+
@echo " Location: $(DS9_TEST_LOCATION)"
15+
@echo ""
16+
@echo "==> Checking if test database exists..."
17+
@if gcloud firestore databases describe --database=$(DS9_TEST_DATABASE) --project=$(DS9_TEST_PROJECT) >/dev/null 2>&1; then \
18+
echo " Database already exists, skipping creation"; \
19+
else \
20+
echo " Database does not exist, creating..."; \
21+
if ! gcloud firestore databases create --database=$(DS9_TEST_DATABASE) \
22+
--location=$(DS9_TEST_LOCATION) \
23+
--type=datastore-mode \
24+
--project=$(DS9_TEST_PROJECT); then \
25+
echo ""; \
26+
echo "ERROR: Failed to create database $(DS9_TEST_DATABASE)"; \
27+
echo "Please check:"; \
28+
echo " 1. Project exists: $(DS9_TEST_PROJECT)"; \
29+
echo " 2. You have permission: datastore.databases.create"; \
30+
echo " 3. Cloud Firestore API is enabled"; \
31+
exit 1; \
32+
fi; \
33+
echo " Database created successfully"; \
34+
fi
35+
@echo ""
36+
@echo "==> Running integration tests..."
37+
@DS9_TEST_PROJECT=$(DS9_TEST_PROJECT) go test -v -race -tags=integration -timeout=5m ./... || \
38+
(echo ""; echo "==> Tests failed, cleaning up..."; \
39+
gcloud firestore databases delete --database=$(DS9_TEST_DATABASE) --project=$(DS9_TEST_PROJECT) --quiet 2>/dev/null; \
40+
exit 1)
41+
@echo ""
42+
@echo "==> Cleaning up test database..."
43+
@gcloud firestore databases delete --database=$(DS9_TEST_DATABASE) --project=$(DS9_TEST_PROJECT) --quiet
44+
@echo "==> Integration tests complete!"
45+
46+
lint:
47+
go vet ./...
48+
gofmt -s -w .
49+
test -z "$$(gofmt -s -l .)"
50+
51+
build:
52+
go build ./...
53+
54+
clean:
55+
go clean -cache -testcache
56+
57+
all: lint test build
58+
59+
# BEGIN: lint-install .
60+
# http://github.com/codeGROOVE-dev/lint-install
61+
62+
.PHONY: lint
63+
lint: _lint
64+
65+
LINT_ARCH := $(shell uname -m)
66+
LINT_OS := $(shell uname)
67+
LINT_OS_LOWER := $(shell echo $(LINT_OS) | tr '[:upper:]' '[:lower:]')
68+
LINT_ROOT := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
69+
70+
# shellcheck and hadolint lack arm64 native binaries: rely on x86-64 emulation
71+
ifeq ($(LINT_OS),Darwin)
72+
ifeq ($(LINT_ARCH),arm64)
73+
LINT_ARCH=x86_64
74+
endif
75+
endif
76+
77+
LINTERS :=
78+
FIXERS :=
79+
80+
GOLANGCI_LINT_CONFIG := $(LINT_ROOT)/.golangci.yml
81+
GOLANGCI_LINT_VERSION ?= v2.5.0
82+
GOLANGCI_LINT_BIN := $(LINT_ROOT)/out/linters/golangci-lint-$(GOLANGCI_LINT_VERSION)-$(LINT_ARCH)
83+
$(GOLANGCI_LINT_BIN):
84+
mkdir -p $(LINT_ROOT)/out/linters
85+
rm -rf $(LINT_ROOT)/out/linters/golangci-lint-*
86+
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(LINT_ROOT)/out/linters $(GOLANGCI_LINT_VERSION)
87+
mv $(LINT_ROOT)/out/linters/golangci-lint $@
88+
89+
LINTERS += golangci-lint-lint
90+
golangci-lint-lint: $(GOLANGCI_LINT_BIN)
91+
find . -name go.mod -execdir "$(GOLANGCI_LINT_BIN)" run -c "$(GOLANGCI_LINT_CONFIG)" \;
92+
93+
FIXERS += golangci-lint-fix
94+
golangci-lint-fix: $(GOLANGCI_LINT_BIN)
95+
find . -name go.mod -execdir "$(GOLANGCI_LINT_BIN)" run -c "$(GOLANGCI_LINT_CONFIG)" --fix \;
96+
97+
.PHONY: _lint $(LINTERS)
98+
_lint:
99+
@exit_code=0; \
100+
for target in $(LINTERS); do \
101+
$(MAKE) $$target || exit_code=1; \
102+
done; \
103+
exit $$exit_code
104+
105+
.PHONY: fix $(FIXERS)
106+
fix:
107+
@exit_code=0; \
108+
for target in $(FIXERS); do \
109+
$(MAKE) $$target || exit_code=1; \
110+
done; \
111+
exit $$exit_code
112+
113+
# END: lint-install .

0 commit comments

Comments
 (0)