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 invitations API #164

Closed
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
171 changes: 171 additions & 0 deletions .github/workflows/api-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
# 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

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" && sleep 10

- 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: 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
30 changes: 29 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,32 @@ 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):
$(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
4 changes: 2 additions & 2 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
15 changes: 15 additions & 0 deletions api/openapi/invitations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ tags:
paths:
/invitations:
post:
operationId: sendInvitation
tags:
- Invitations
summary: Send invitation
Expand All @@ -45,6 +46,8 @@ paths:
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"404":
description: A non-existent entity request.
"409":
description: Failed due to using an existing identity.
"415":
Expand All @@ -53,6 +56,7 @@ paths:
$ref: "#/components/responses/ServiceError"

get:
operationId: listInvitations
tags:
- Invitations
summary: List invitations
Expand Down Expand Up @@ -89,6 +93,7 @@ paths:

/invitations/accept:
post:
operationId: acceptInvitation
summary: Accept invitation
description: |
Current logged in user accepts invitation to join domain.
Expand All @@ -105,11 +110,14 @@ 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"

/invitations/{user_id}/{domain_id}:
get:
operationId: getInvitation
summary: Retrieves a specific invitation
description: |
Retrieves a specific invitation that is identifier by the user ID and domain ID.
Expand All @@ -135,6 +143,7 @@ paths:
$ref: "#/components/responses/ServiceError"

delete:
operationId: deleteInvitation
summary: Deletes a specific invitation
description: |
Deletes a specific invitation that is identifier by the user ID and domain ID.
Expand Down Expand Up @@ -452,6 +461,12 @@ components:
application/json:
schema:
$ref: "#/components/schemas/Invitation"
links:
delete:
operationId: deleteInvitation
parameters:
user_id: $response.body#/user_id
domain_id: $response.body#/domain_id

InvitationPageRes:
description: Data retrieved.
Expand Down
Loading
Loading