Skip to content
This repository has been archived by the owner on Oct 14, 2024. It is now read-only.

NOISSUE - Add property based testing to bootstrap API #167

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
193 changes: 193 additions & 0 deletions .github/workflows/api-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0

name: Property Based Tests

on:
push:
branches:
- main
paths:
- ".github/workflows/api-tests.yml"
- "api/**"
- "auth/api/http/**"
- "bootstrap/api**"
- "certs/api/**"
- "consumers/notifiers/api/**"
- "http/api/**"
- "invitations/api/**"
- "provision/api/**"
- "readers/api/**"
- "things/api/**"
- "twins/api/**"
- "users/api/**"

pull_request:
branches:
- main
paths:
- ".github/workflows/api-tests.yml"
- "api/**"
- "auth/api/http/**"
- "bootstrap/api**"
- "certs/api/**"
- "consumers/notifiers/api/**"
- "http/api/**"
- "invitations/api/**"
- "provision/api/**"
- "readers/api/**"
- "things/api/**"
- "twins/api/**"
- "users/api/**"

env:
TOKENS_URL: http://localhost:9002/users/tokens/issue
DOMAINS_URL: http://localhost:8189/domains
USER_IDENTITY: [email protected]
USER_SECRET: 12345678
DOMAIN_NAME: demo-test
USERS_URL: http://localhost:9002
THINGS_URL: http://localhost:9000
INVITATIONS_URL: http://localhost:9020
AUTH_URL: http://localhost:8189
BOOTSTRAP_URL: http://localhost:9013

jobs:
api-test:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Install Go
uses: actions/setup-go@v4
with:
go-version: 1.21.x
cache-dependency-path: "go.sum"

- name: Build images
run: make all -j $(nproc) && make dockers_dev -j $(nproc)

- name: Start containers
run: make run up args="-d" && make run_addons up args="-d"

- name: Set access token
run: |
export USER_TOKEN=$(curl -sSX POST $TOKENS_URL -H "Content-Type: application/json" -d "{\"identity\": \"$USER_IDENTITY\",\"secret\": \"$USER_SECRET\"}" | jq -r .access_token)
export DOMAIN_ID=$(curl -sSX POST $DOMAINS_URL -H "Content-Type: application/json" -H "Authorization: Bearer $USER_TOKEN" -d "{\"name\":\"$DOMAIN_NAME\",\"alias\":\"$DOMAIN_NAME\"}" | jq -r .id)
export USER_TOKEN=$(curl -sSX POST $TOKENS_URL -H "Content-Type: application/json" -d "{\"identity\": \"$USER_IDENTITY\",\"secret\": \"$USER_SECRET\",\"domain_id\": \"$DOMAIN_ID\"}" | jq -r .access_token)
echo "USER_TOKEN=$USER_TOKEN" >> $GITHUB_ENV

- name: Check for changes in specific paths
uses: dorny/paths-filter@v2
id: changes
with:
filters: |
auth:
- ".github/workflows/api-tests.yml"
- "api/openapi/auth.yml"
- "auth/api/http/**"

bootstrap:
- ".github/workflows/api-tests.yml"
- "api/openapi/bootstrap.yml"
- "bootstrap/api/**"

certs:
- ".github/workflows/api-tests.yml"
- "api/openapi/certs.yml"
- "certs/api/**"

notifiers:
- ".github/workflows/api-tests.yml"
- "api/openapi/notifiers.yml"
- "consumers/notifiers/api/**"

http:
- ".github/workflows/api-tests.yml"
- "api/openapi/http.yml"
- "http/api/**"

invitations:
- ".github/workflows/api-tests.yml"
- "api/openapi/invitations.yml"
- "invitations/api/**"

provision:
- ".github/workflows/api-tests.yml"
- "api/openapi/provision.yml"
- "provision/api/**"

readers:
- ".github/workflows/api-tests.yml"
- "api/openapi/readers.yml"
- "readers/api/**"

things:
- ".github/workflows/api-tests.yml"
- "api/openapi/things.yml"
- "things/api/**"

twins:
- ".github/workflows/api-tests.yml"
- "api/openapi/twins.yml"
- "twins/api/**"

users:
- ".github/workflows/api-tests.yml"
- "api/openapi/users.yml"
- "users/api/**"

- name: Run Users API tests
if: steps.changes.outputs.users == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/users.yml
base-url: ${{ env.USERS_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-unique-data --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'

- name: Run Things API tests
if: steps.changes.outputs.things == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/things.yml
base-url: ${{ env.THINGS_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-unique-data --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'

- name: Run Invitations API tests
if: steps.changes.outputs.invitations == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/invitations.yml
base-url: ${{ env.INVITATIONS_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-unique-data --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'

- name: Run Auth API tests
if: steps.changes.outputs.auth == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/auth.yml
base-url: ${{ env.AUTH_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-unique-data --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'

- name: Run Bootstrap API tests
if: steps.changes.outputs.bootstrap == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/bootstrap.yml
base-url: ${{ env.BOOTSTRAP_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-unique-data --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'

- name: Stop containers
if: always()
run: make run down args="-v"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ tools/provision/mgconn.toml

# coverage files
coverage

# Schemathesis
.hypothesis
32 changes: 31 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ BUILD_DIR = build
SERVICES = auth users things http coap ws lora influxdb-writer influxdb-reader mongodb-writer \
mongodb-reader cassandra-writer cassandra-reader postgres-writer postgres-reader timescale-writer timescale-reader cli \
bootstrap opcua twins mqtt provision certs smtp-notifier smpp-notifier invitations
TEST_API_SERVICES = auth bootstrap certs http invitations notifiers provision readers things twins users
TEST_API = $(addprefix test_api_,$(TEST_API_SERVICES))
DOCKERS = $(addprefix docker_,$(SERVICES))
DOCKERS_DEV = $(addprefix docker_dev_,$(SERVICES))
CGO_ENABLED ?= 0
Expand Down Expand Up @@ -97,7 +99,7 @@ FILTERED_SERVICES = $(filter-out $(RUN_ADDON_ARGS), $(SERVICES))

all: $(SERVICES)

.PHONY: all $(SERVICES) dockers dockers_dev latest release run run_addons grpc_mtls_certs check_mtls check_certs
.PHONY: all $(SERVICES) dockers dockers_dev latest release run run_addons grpc_mtls_certs check_mtls check_certs test_api

clean:
rm -rf ${BUILD_DIR}
Expand Down Expand Up @@ -129,6 +131,34 @@ test: mocks
done
go test -v --race -count 1 -tags test -coverprofile=coverage/coverage.out $$(go list ./... | grep -v 'consumers\|readers\|postgres\|internal\|opcua\|cmd')

define test_api_service
$(eval svc=$(subst test_api_,,$(1)))
@which st > /dev/null || (echo "schemathesis not found, please install it from https://github.com/schemathesis/schemathesis#getting-started" && exit 1)

@if [ -z "$(USER_TOKEN)" ]; then \
echo "USER_TOKEN is not set"; \
echo "Please set it to a valid token"; \
exit 1; \
fi

st run api/openapi/$(svc).yml \
--checks all \
--base-url $(2) \
--header "Authorization: Bearer $(USER_TOKEN)" \
--contrib-unique-data --contrib-openapi-formats-uuid \
--hypothesis-suppress-health-check=filter_too_much \
--stateful=links
endef

test_api_users: TEST_API_URL := http://localhost:9002
test_api_things: TEST_API_URL := http://localhost:9000
test_api_invitations: TEST_API_URL := http://localhost:9020
test_api_auth: TEST_API_URL := http://localhost:8189
test_api_bootstrap: TEST_API_URL := http://localhost:9013

$(TEST_API):
$(call test_api_service,$(@),$(TEST_API_URL))

proto:
protoc -I. --go_out=. --go_opt=paths=source_relative pkg/messaging/*.proto
protoc -I. --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./*.proto
Expand Down
24 changes: 21 additions & 3 deletions api/openapi/auth.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ info:
version: 0.14.0

servers:
- url: http://localhost:8180
- url: https://localhost:8180
- url: http://localhost:8189
- url: https://localhost:8189

tags:
- name: Auth
Expand Down Expand Up @@ -319,6 +319,7 @@ paths:
$ref: "#/components/responses/ServiceError"
/keys:
post:
operationId: issueKey
tags:
- Keys
summary: Issue API key
Expand All @@ -341,6 +342,7 @@ paths:

/keys/{keyID}:
get:
operationId: getKey
summary: Gets API key details.
description: |
Gets API key details for the given key.
Expand All @@ -355,10 +357,13 @@ paths:
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"404":
description: A non-existent entity request.
"500":
$ref: "#/components/responses/ServiceError"

delete:
operationId: revokeKey
summary: Revoke API key
description: |
Revoke API key identified by the given ID.
Expand All @@ -371,11 +376,14 @@ paths:
description: Key revoked.
"401":
description: Missing or invalid access token provided.
"404":
description: A non-existent entity request.
"500":
$ref: "#/components/responses/ServiceError"

/policies:
post:
operationId: addPolicies
summary: Creates new policies.
description: |
Creates new policies. Only admin can use this endpoint. Therefore, you need an authentication token for the admin.
Expand All @@ -393,6 +401,8 @@ paths:
description: Missing or invalid access token provided.
"403":
description: Unauthorized access token provided.
"404":
description: A non-existent entity request.
"409":
description: Failed due to using an existing email address.
"415":
Expand All @@ -402,6 +412,7 @@ paths:

/policies/delete:
post:
operationId: deletePolicies
summary: Deletes policies.
description: |
Deletes policies. Only admin can use this endpoint. Therefore, you need an authentication token for the admin.
Expand All @@ -415,6 +426,8 @@ paths:
description: Policies deleted.
"400":
description: Failed due to malformed JSON.
"404":
description: A non-existent entity request.
"409":
description: Failed due to using an existing email address.
"415":
Expand Down Expand Up @@ -867,11 +880,16 @@ components:
application/json:
schema:
$ref: "#/components/schemas/Key"
links:
revoke:
operationId: revokeKey
parameters:
keyID: $response.body#/id

HealthRes:
description: Service Health Check.
content:
application/json:
application/health+json:
schema:
$ref: "./schemas/HealthInfo.yml"

Expand Down
Loading
Loading