Skip to content

Commit

Permalink
Add testing framework and a implement tests for syn-teams.libsonnet
Browse files Browse the repository at this point in the history
  • Loading branch information
simu committed Dec 20, 2024
1 parent 02da80b commit 4b80387
Show file tree
Hide file tree
Showing 7 changed files with 340 additions and 0 deletions.
37 changes: 37 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
name: Lint & Test

"on":
pull_request: {}

jobs:
jsonnetfmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
make jsonnetfmt_check
test_libraries_discover_cases:
name: Discover golden test cases
runs-on: ubuntu-latest
outputs:
instances: ${{ steps.instances.outputs.instances }}
steps:
- uses: actions/checkout@v4
- name: Find test cases
id: instances
run: |
echo "instances=$(make -s list_test_instances)" >> "$GITHUB_OUTPUT"
test_libraries:
needs: test_libraries_discover_cases
strategy:
matrix:
instance: ${{ fromJSON(needs.test_libraries_discover_cases.outputs.instances) }}
runs-on: ubuntu-latest
name: 'Golden test: ${{ matrix.instance }}'
steps:
- uses: actions/checkout@v4
- run: |
make golden-diff -e instance=${{ matrix.instance }}
45 changes: 45 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
MAKEFLAGS += --warn-undefined-variables
SHELL := bash
.SHELLFLAGS := -eu -o pipefail -c

include Makefile.vars.mk

.PHONY: jsonnetfmt_check jsonnetfmt
jsonnetfmt_check: JSONNET_ENTRYPOINT=jsonnetfmt
jsonnetfmt_check:
$(JSONNET_DOCKER) --test --pad-arrays -- *.libsonnet

jsonnetfmt: JSONNET_ENTRYPOINT=jsonnetfmt
jsonnetfmt:
$(JSONNET_DOCKER) --in-place --pad-arrays -- *.libsonnet

tests/lib/commodore-real.libjsonnet:
@mkdir -p "tests/lib"
curl -fsSLo "tests/lib/commodore-real.libjsonnet" https://raw.githubusercontent.com/projectsyn/commodore/refs/heads/master/commodore/lib/commodore.libjsonnet

.PHONY: gen-golden
gen-golden: tests/lib/commodore-real.libjsonnet
$(JSONNET_DOCKER) tests/run-instance.sh $(instance) > tests/golden/$(instance).yml

.PHONY: golden-diff
golden-diff: tests/lib/commodore-real.libjsonnet
@mkdir -p /tmp/golden
$(JSONNET_DOCKER) tests/run-instance.sh $(instance) > /tmp/golden/$(instance).yml
@git diff --exit-code --minimal --no-index -- tests/golden/$(instance).yml /tmp/golden/$(instance).yml

.PHONY: golden-diff-all
golden-diff-all: recursive_target=golden-diff
golden-diff-all: $(test_instances)

.PHONY: gen-golden-all
gen-golden-all: recursive_target=gen-golden
gen-golden-all: $(test_instances)

.PHONY: $(test_instances)
$(test_instances):
$(MAKE) $(recursive_target) -e instance=$(basename $(@F))

.PHONY: list_test_instances
list_test_instances: JSONNET_ENTRYPOINT=jsonnet
list_test_instances:
$(JSONNET_DOCKER) -J . -J tests --ext-str instances="$(basename $(notdir $(test_instances)))" -e 'std.split(std.extVar("instances"), " ")' | jq -c
15 changes: 15 additions & 0 deletions Makefile.vars.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
ifneq "$(shell which docker 2>/dev/null)" ""
DOCKER_CMD ?= $(shell which docker)
DOCKER_USERNS ?= ""
else
DOCKER_CMD ?= podman
DOCKER_USERNS ?= keep-id
endif
DOCKER_ARGS ?= run --rm -u "$$(id -u):$$(id -g)" --userns=$(DOCKER_USERNS) -w /work -e HOME="/work"

JSONNET_IMAGE ?= docker.io/bitnami/jsonnet:latest
JSONNET_ENTRYPOINT ?= bash
JSONNET_DOCKER ?= $(DOCKER_CMD) $(DOCKER_ARGS) -v "$${PWD}:/work" --entrypoint=$(JSONNET_ENTRYPOINT) $(JSONNET_IMAGE)

test_instances=$(shell find tests/ -maxdepth 1 -name '*.jsonnet')
instance=syn-teams
61 changes: 61 additions & 0 deletions tests/golden/syn-teams.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"all_teams": [
"fragrant-flower",
"solitary-wood",
"sparkling-sound"
],
"appKeys": {
"foo": [
"foo"
],
"foo-bar": [
"foo_bar"
],
"foo-bar as bar": [
"bar",
"foo_bar"
],
"foo-bar as bar-qux": [
"bar_qux",
"foo_bar"
]
},
"appKeysRaw": {
"foo": [
"foo"
],
"foo-bar": [
"foo-bar"
],
"foo-bar as bar": [
"bar",
"foo-bar"
],
"foo-bar as bar-qux": [
"bar-qux",
"foo-bar"
]
},
"appsForTeam": {
"fragrant-flower": [
"red-flower"
],
"solitary-wood": [
"small-sun"
],
"sparkling-sound": [
"cool-breeze",
"fragrant-smoke"
]
},
"teamForApp": {
"cool-breeze": "sparkling-sound",
"fragrant-smoke": "sparkling-sound",
"red-flower": "fragrant-flower",
"small-sun": "solitary-wood"
},
"teams": [
"fragrant-flower",
"solitary-wood"
]
}
15 changes: 15 additions & 0 deletions tests/run-instance.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash

set -e -u -x

testdir=$(dirname "$0")
instance="${testdir}/${1}"

cat > "${testdir}/lib/commodore.libjsonnet" <<EOF
local com = import 'lib/commodore-real.libjsonnet';
com {
inventory(): std.parseYaml(importstr '${1}.yaml'),
}
EOF

jsonnet -J . -J "${testdir}" "${instance}".jsonnet
124 changes: 124 additions & 0 deletions tests/syn-teams.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
local com = import 'lib/commodore.libjsonnet';
local syn_teams = import 'syn-teams.libsonnet';

local expected = com.inventory().expected;

local teams =
local t = std.set(syn_teams.teams());
local expected_teams = std.set(expected.teams);
if t != expected_teams then
error 'Expected teams: %s, got teams: %s' % [
std.join(', ', teams),
std.join(', ', expected_teams),
]
else
t;

local all_teams =
local t = std.set(syn_teams.teams(true));
local expected_teams = std.set(expected.all_teams);
if t != expected_teams then
error 'Expected teams: %s, got teams: %s' % [
std.join(', ', teams),
std.join(', ', expected_teams),
]
else
t;

local appsForTeam =
local aft = {
[t]: syn_teams.applicationsForTeam(t)
for t in all_teams
};
if aft != expected.appsForTeam then
error 'Mismatch in appsForTeam: got %s, expected %s' % [
aft,
expected.appsForTeam,
]
else
aft;

local teamForApp =
local inv = com.inventory();
local applications = std.map(function(app) syn_teams.appKeys(app, true)[0], inv.applications);
local tfa = {
[a]: syn_teams.teamForApplication(a)
for a in applications
};
if tfa != expected.teamForApp then
error 'Mismatch in teamForApp: got %s, expected %s' % [
tfa,
expected.teamForApp,
]
else
tfa;

local appKeys =
local expected = {
foo: [ 'foo' ],
'foo-bar': [ 'foo_bar' ],
'foo-bar as bar': [ 'bar', 'foo_bar' ],
'foo-bar as bar-qux': [ 'bar_qux', 'foo_bar' ],
};
std.foldl(
function(prev, a)
local ks = syn_teams.appKeys(a);
if ks != expected[a] then
error 'Expected %s for appKeys(%s), got %s' % [
expected[a],
a,
ks,
]
else
prev {
[a]: ks,
},
std.objectFields(expected),
{}
);

local appKeysRaw =
local expected = {
foo: [ 'foo' ],
'foo-bar': [ 'foo-bar' ],
'foo-bar as bar': [ 'bar', 'foo-bar' ],
'foo-bar as bar-qux': [ 'bar-qux', 'foo-bar' ],
};
std.foldl(
function(prev, a)
local ks = syn_teams.appKeys(a, true);
if ks != expected[a] then
error 'Expected %s for appKeys(%s), got %s' % [
expected[a],
a,
ks,
]
else
prev {
[a]: ks,
},
std.objectFields(expected),
{}
);


/*
local ks2 = syn_teams.appKeys('foo-bar');
assert std.length(ks2) == 1 && ks2[0] == 'foo_bar' : 'appKeys should transform - to _';
local ks3 = syn_teams.appKeys('foo-bar as bar');
assert std.length(ks3) == 2 && ks3[0] == 'bar' && ks3[1] == 'foo_bar' : 'appKeys parses and transforms x-z as y';
local ks4 = syn_teams.appKeys('foo-bar as bar-qux');
assert std.length(ks4) == 2 && ks4[0] == 'bar_qux' && ks4[1] == 'foo_bar' : 'appKeys parses and transforms x-zl as y-w';
local ks5 = syn_teams.appKeys('foo-bar as bar-qux', raw=true);
assert std.length(ks5) == 2 && ks5[0] == 'bar-qux' && ks5[1] == 'foo-bar' : "appKeys(raw=true) doesn't transform - to _";
};
*/

{
teams: teams,
all_teams: all_teams,
appKeys: appKeys,
appKeysRaw: appKeysRaw,
appsForTeam: appsForTeam,
teamForApp: teamForApp,
}
43 changes: 43 additions & 0 deletions tests/syn-teams.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
applications:
- small-sun
- cool-breeze
- cool-breeze as red-flower
- fragrant-smoke

parameters:
syn:
owner: sparkling-sound
teams:
solitary-wood:
instances:
- small-sun
lingering-fog:
instances:
- morning-thunder
fragrant-flower:
instances:
- ~small-sun
- red-flower


expected:
teams:
- solitary-wood
- fragrant-flower
all_teams:
- sparkling-sound
- solitary-wood
- fragrant-flower
appsForTeam:
fragrant-flower:
- red-flower
sparkling-sound:
- cool-breeze
- fragrant-smoke
solitary-wood:
- small-sun
teamForApp:
cool-breeze: sparkling-sound
fragrant-smoke: sparkling-sound
red-flower: fragrant-flower
small-sun: solitary-wood

0 comments on commit 4b80387

Please sign in to comment.