diff --git a/Makefile b/Makefile index da8968b..4c92b97 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ LD_FLAGS := "-s -w" +# TODO: add needed platforms PLATFORMS = linux darwin ARCHITECTURES = amd64 @@ -20,6 +21,10 @@ build-all: clean test: go test ./... +# Run integration tests +test-integration: + go test -tags=integrity ./... + bench: go test -bench=. -benchmem -run=^# ./... diff --git a/integrity_test.go b/integrity_test.go index 77c0657..7ca39f9 100644 --- a/integrity_test.go +++ b/integrity_test.go @@ -1,3 +1,6 @@ +//go:build integrity +// +build integrity + package main_test import ( @@ -16,24 +19,37 @@ func TestRelayIntegration(t *testing.T) { }) } +// setup prepares the test environment by building the relay binary and copying required license files func setup(env *testscript.Env) error { binPath := filepath.Join(env.WorkDir, "relay") - cmd := exec.Command("go", "build", "-o", binPath, "./cmd/relay") - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - return err + buildCmd := exec.Command("go", "build", "-o", binPath, "./cmd/relay") + buildCmd.Stderr = os.Stderr + if err := buildCmd.Run(); err != nil { + return fmt.Errorf("failed to build relay binary: %w", err) } env.Setenv("PATH", env.Getenv("PATH")+string(os.PathListSeparator)+env.WorkDir) - licenseSrc := filepath.Join(env.Getenv("TESTSCRIPT_ROOT"), "testdata", "license.lic") - licenseDst := filepath.Join(env.WorkDir, "license.lic") - input, err := os.ReadFile(licenseSrc) + // copy license files into the working directory tests + testscriptRoot := env.Getenv("TESTSCRIPT_ROOT") + if err := copyFile(filepath.Join(testscriptRoot, "testdata", "license.lic"), filepath.Join(env.WorkDir, "license.lic")); err != nil { + return fmt.Errorf("failed to copy license.lic: %w", err) + } + if err := copyFile(filepath.Join(testscriptRoot, "testdata", "license_2.lic"), filepath.Join(env.WorkDir, "license_2.lic")); err != nil { + return fmt.Errorf("failed to copy license_2.lic: %w", err) + } + + return nil +} + +func copyFile(src, dst string) error { + input, err := os.ReadFile(src) if err != nil { - return fmt.Errorf("failed to read license file: %v", err) + return fmt.Errorf("unable to read file %s: %w", src, err) } - if err := os.WriteFile(licenseDst, input, 0644); err != nil { - return fmt.Errorf("failed to write license file: %v", err) + + if err := os.WriteFile(dst, input, 0644); err != nil { + return fmt.Errorf("unable to write file to %s: %w", dst, err) } return nil diff --git a/testdata/claim_conflict.txt b/testdata/claim_conflict.txt new file mode 100644 index 0000000..7007446 --- /dev/null +++ b/testdata/claim_conflict.txt @@ -0,0 +1,25 @@ +# Remove existing database +rm -f relay.sqlite + +# Add the license +exec relay add --file license.lic --key 9E32DD-D8CC22-771926-C2D834-C506DC-V3 --public-key e8601e48b69383ba520245fd07971e983d06d22c4257cfd82304601479cee788 + +# Set a port as environment variable +env PORT=8082 + +# Start the server with heartbeat disabled +exec relay serve --port $PORT --no-heartbeats &server_process_test& + +# Wait for the server to start +exec sleep 1 + +# Claim the license for the first time and check status code directly +exec curl -s -o /dev/null -w "%{http_code}" -X PUT http://localhost:$PORT/v1/nodes/test_fingerprint +stdout '201' + +# Claim the license again with the same fingerprint and check status code directly +exec curl -s -o /dev/null -w "%{http_code}" -X PUT http://localhost:$PORT/v1/nodes/test_fingerprint +stdout '409' + +# Stop the server +kill server_process_test diff --git a/testdata/claim_license_conflict.txt b/testdata/claim_license_conflict.txt new file mode 100644 index 0000000..cf51960 --- /dev/null +++ b/testdata/claim_license_conflict.txt @@ -0,0 +1,29 @@ +# Remove existing database +rm -f relay.sqlite + +# Add the license +exec relay add --file license.lic --key 9E32DD-D8CC22-771926-C2D834-C506DC-V3 --public-key e8601e48b69383ba520245fd07971e983d06d22c4257cfd82304601479cee788 + +# Set a port as environment variable +env PORT=8083 + +# Start the server with heartbeat disabled +exec relay serve --port $PORT --no-heartbeats &server_process_test& + +# Wait for the server to start +exec sleep 1 + +# Claim the license for the first time +exec curl -s -o /dev/null -w "%{http_code}" -X PUT http://localhost:$PORT/v1/nodes/test_fingerprint +stdout '201' + +# Claim the license again with the same fingerprint +exec curl -s -o response.txt -w "%{http_code}" -X PUT http://localhost:$PORT/v1/nodes/test_fingerprint + +# Expect a conflict response with status code 409 and error message +stdout '409' + +exec grep '{"error":"License claim conflict, heartbeat disabled"}' response.txt + +# Stop the server +kill server_process_test diff --git a/testdata/claim_license_extended.txt b/testdata/claim_license_extended.txt new file mode 100644 index 0000000..22830ba --- /dev/null +++ b/testdata/claim_license_extended.txt @@ -0,0 +1,29 @@ +# Remove existing database +rm -f relay.sqlite + +# Add the license +exec relay add --file license.lic --key 9E32DD-D8CC22-771926-C2D834-C506DC-V3 --public-key e8601e48b69383ba520245fd07971e983d06d22c4257cfd82304601479cee788 + +# Set a port as environment variable +env PORT=8087 + +# Start the server with heartbeat enabled (for extension to work) +exec relay serve --port $PORT &server_process_test& + +# Wait for the server to start +exec sleep 1 + +# Claim a license for the first time +exec curl -s -o /dev/null -w "%{http_code}" -X PUT http://localhost:$PORT/v1/nodes/test_fingerprint +stdout '201' + +# Claim the license again with the same fingerprint to trigger an extension +exec curl -s -o response.txt -w "%{http_code}" -X PUT http://localhost:$PORT/v1/nodes/test_fingerprint +stdout '202' + +# Expect the response to contain "license_file" and "license_key" fields for extended license +exec grep '"license_file":' response.txt +exec grep '"license_key":' response.txt + +# Stop the server +kill server_process_test diff --git a/testdata/claim_license_lifo_strategy.txt b/testdata/claim_license_lifo_strategy.txt new file mode 100644 index 0000000..671bec8 --- /dev/null +++ b/testdata/claim_license_lifo_strategy.txt @@ -0,0 +1,32 @@ +# Remove existing database +rm -f relay.sqlite + +# Add two licenses +exec relay add --file license.lic --key 9E32DD-D8CC22-771926-C2D834-C506DC-V3 --public-key e8601e48b69383ba520245fd07971e983d06d22c4257cfd82304601479cee788 + +# Give a pause between adding licenses +exec sleep 1 + +exec relay add --file license_2.lic --key 9A96B8-FD08CD-8C433B-7657C8-8A8655-V3 --public-key e8601e48b69383ba520245fd07971e983d06d22c4257cfd82304601479cee788 + +# Set a port and strategy as environment variables +env PORT=8089 +env STRATEGY=lifo + +# Start the server with FIFO strategy +exec relay serve --port $PORT --strategy $STRATEGY &server_process_test& + +# Wait for the server to start +exec sleep 1 + +# Claim a license (LIFO: should return the last license) +exec curl -s -o response.txt -w "%{http_code}" -X PUT http://localhost:$PORT/v1/nodes/test_fingerprint + +exec relay ls --plain + +# Expect the first license to be returned +exec grep '"license_file":' response.txt +exec grep '"license_key":"9A96B8-FD08CD-8C433B-7657C8-8A8655-V3"' response.txt + +# Stop the server +kill server_process_test diff --git a/testdata/claim_license_success.txt b/testdata/claim_license_success.txt new file mode 100644 index 0000000..99e9226 --- /dev/null +++ b/testdata/claim_license_success.txt @@ -0,0 +1,27 @@ +# Remove existing database +rm -f relay.sqlite + +# Add the license +exec relay add --file license.lic --key 9E32DD-D8CC22-771926-C2D834-C506DC-V3 --public-key e8601e48b69383ba520245fd07971e983d06d22c4257cfd82304601479cee788 + +# Set a port as environment variable +env PORT=8090 + +# Start the server with heartbeat disabled +exec relay serve --port $PORT &server_process_test& + +# Wait for the server to start +exec sleep 1 + +# Claim a license +exec curl -s -o response.txt -w "%{http_code}" -X PUT http://localhost:$PORT/v1/nodes/test_fingerprint + +# Expect a success response with status code 201 +stdout '201' + +# Check that the response contains license_file and license_key fields (using grep) +exec grep '"license_file":' response.txt +exec grep '"license_key":' response.txt + +# Stop the server +kill server_process_test diff --git a/testdata/claim_no_licenses_available.txt b/testdata/claim_no_licenses_available.txt new file mode 100644 index 0000000..8e104ea --- /dev/null +++ b/testdata/claim_no_licenses_available.txt @@ -0,0 +1,18 @@ +# Remove existing database +rm -f relay.sqlite + +# Start the server without adding any licenses +env PORT=8084 +exec relay serve --port $PORT &server_process_test& + +# Wait for the server to start +exec sleep 1 + +# Attempt to claim a license when none are available +exec curl -s -o response.txt -w "%{http_code}" -X PUT http://localhost:$PORT/v1/nodes/test_fingerprint + +# Expect a gone response with status code 410 and error message +stdout '410' +exec grep 'No licenses available' response.txt + +kill server_process_test diff --git a/testdata/cmd_del.txt b/testdata/cmd_del.txt new file mode 100644 index 0000000..38a932e --- /dev/null +++ b/testdata/cmd_del.txt @@ -0,0 +1,19 @@ +# Remove existing database +rm -f relay.sqlite + +# Add the license +exec relay add --file license.lic --key 9E32DD-D8CC22-771926-C2D834-C506DC-V3 --public-key e8601e48b69383ba520245fd07971e983d06d22c4257cfd82304601479cee788 + +# Confirm the license is added +exec relay ls --plain +stdout 'dcea31a4-1664-4633-9f52-4a1b0b5ea2ef' + +# Delete the license +exec relay del --id dcea31a4-1664-4633-9f52-4a1b0b5ea2ef + +# Expect output indicating success +stdout 'License deleted successfully.' + +# Verify the license is deleted +exec relay ls --plain +stdout 'No licenses found.' diff --git a/testdata/cmd_serve.txt b/testdata/cmd_serve.txt new file mode 100644 index 0000000..d0d6265 --- /dev/null +++ b/testdata/cmd_serve.txt @@ -0,0 +1,32 @@ +# Remove existing database +rm -f relay.sqlite + +# Add the license +exec relay add --file license.lic --key 9E32DD-D8CC22-771926-C2D834-C506DC-V3 --public-key e8601e48b69383ba520245fd07971e983d06d22c4257cfd82304601479cee788 + +# Set a port as environment variable +env PORT=8081 + +# Start the server in the background with the environment variable +exec relay serve --port $PORT &server_process& + +# Wait for the server to start +exec sleep 1 + +# Claim a license using the port from the environment variable +exec curl -s -X PUT http://localhost:$PORT/v1/nodes/test_fingerprint + +# Expect license data in the response +stdout '"license_file":' + +# Release the license +exec curl -s -X DELETE http://localhost:$PORT/v1/nodes/test_fingerprint + +# Expect no content in the response +stdout '' + +# Stop the server +kill server_process + +# Wait for the server to terminate +# wait server_process diff --git a/testdata/cmd_stat.txt b/testdata/cmd_stat.txt new file mode 100644 index 0000000..acce3ec --- /dev/null +++ b/testdata/cmd_stat.txt @@ -0,0 +1,11 @@ +# Remove existing database +rm -f relay.sqlite + +# Add the license +exec relay add --file license.lic --key 9E32DD-D8CC22-771926-C2D834-C506DC-V3 --public-key e8601e48b69383ba520245fd07971e983d06d22c4257cfd82304601479cee788 + +# Get statistics of the license +exec relay stat --id dcea31a4-1664-4633-9f52-4a1b0b5ea2ef --plain + +# Expect output containing the license details +stdout 'dcea31a4-1664-4633-9f52-4a1b0b5ea2ef' diff --git a/testdata/license_2.lic b/testdata/license_2.lic new file mode 100644 index 0000000..97f1e06 --- /dev/null +++ b/testdata/license_2.lic @@ -0,0 +1,201 @@ +-----BEGIN LICENSE FILE----- +eyJlbmMiOiJqNHlIZ3VtczFTTENQVzlBNzJhcTFKVlJIcXc4UXNGWGp3TEpn +NllFNWo5VE5nNzhUV0pJTWZWU09INk83YW5SbnU5MHVyWTVvMmgrM0xJdnNj +K1pmclNSL09vZlpYQkxBSUZhWGloRHluSW9wa1FHcGRjdDFxVzR4UXExcWE3 +UGZja25GWmc1MXJBMzlDWG1oVHM0cjljTHBuaVdlUHpjN3hqdnkzdTduVm1L +UisrTUx2M09RNXI3RTRldWVlYk1JM1hGeE4yVnlONXA2c2NMS05CZUxWdjZM +Zm0yeEVUVEU3SW1rcU5jRU9lcFVwN1QvcmVVVHRDZnNkb0Nja0ZyNzJVQW9a +OW10TlBNMVpGalVIbTBLd01vWS8yZGE1Vmt6WWFtMEFhVG8vM3VBVW9TaWJ1 +aVZRTXgxQlFGQmxEalZwYkQrZG5LSWRQd3pZMjZFd0FxVXY5N2swcjZaUGdO +TzhIQmxvQ0VFQThMbU5lS3RUeXd4UFpKM0hkS2diQWo4SVBLVzdVT09xZlU0 +RmxoNlpqdDg2aWhsa0hhT3hicHo3bDNkT3RUR1hBWXdIL1UrNDc2elBISW5F +Qk1yVUVaZ3ZwRGlEdkpUNjNKS1Y1MFpKTmwrdjBmMlZqZEhLN0xWNEpYSmhU +YXQ4dUdtOFZ6bzB0akw2UVJsSzR6d2pGOWRmYVdlai9mbmV0c3lydWF6c09r +ditqVWRxdGZlVFB2Y1Y4TWpmQkFxTTRsalBVU1J4UjBOeStUbVV3aklOdkJu +NXRMRUsydGRLUktsY1lOVzNqQ3hJSTRLTyt5WVVnQXhSN25SeEdRaUR4RHhS +Q3RsTkFuRzgwN0htdEo4WVlMRGg0cVZCSVlZajQ0ME9INC8vcUdNbW5YMmp5 +eFFpcnRmL1d4bG1aTXhadjc2aDZhVVZmN3NFdmVnREZkYXQyU09MeFlGdTlw +QXJ0dno2K3Z2bHJNWWdoNllzejI3Ymp6MHhFekltNGRETU5zOXBFcjN5YThq +MkgxZWtEVmlnWmU0b3hCQVlYbEgxRjU3K1BHbGNNbUtaREMvMXRRdUJDakxB +aVY3S1JITExxN1R1MjhGb201QWVvTW4vUU81d2NpRldPNlcrQzhFZUtrV3dZ +cFlCNUhLeFJiMVlabUpNZlp1bXdONzFXNzhZdkRFN05XSzd4WnBkdldwZHB0 +NXplbkl3T21qN0pjd09MQkJDb3RuRlBsbVpHam5PWU5hZEpWeG9nQitpWmlW +QVJFZ3k1K0c0QUxHU0o1ejVDM2ppNVZTRzFWV0U0TVZaM1NnT05FSElTUFNX +eTVRUEFKQnlPQldtRjRyczJUcExxVmJFSXYxdG1rNEFTcTV4eGQxVmNXdnF1 +T1B5N2J6YVljVTk0YTZ5WVFSajdkMWRKdHJZMVBNTTJIRWFQNFdSZ3BCSXBi +Z3NucnZpN2R1NEMycjUzaVlPajJKV2FlTTRTUkZjTy9HR3pGSW9BY0NicW1B +N3ZKc054TnBic2lOUWNGWllGb015VHZRUDUvQnhrK2pKSVQxV2FuU1hyNDBP +M2pxZjl3S1p6UStRRUhoZ1pneHorRjVvT1F4SS9tNllpRHVqdnRybDBKVG14 +dzNMdmthWXZVMUNMMXNSNUJidjJtTHFtTmh1Q1VHcGNDU3dBQmlnZjR4b1hu +WWVjREVpZDhJSGZTTXRqTGQyWnI1STE1RHZWUTZjZXI3czcrQkVNakdhZ3pI +dndzVXgwUDUrSU1OL25RMmV6K09TY2UzSG4xajJXdGswUG5VQVdNV2FJWkJ0 +eWJkOFpsQmNRcUJxMGZJVzJIZFZLMkllN3NXeU1mMEpGSkRpRnhwL1pENmRZ +R1luUGtYcVMwNHlDUWdHcVRPUURralZ1c1grVUNCK1RrcllUK1d0VjlkSlNa +VDVzNUJYT2d0dW5TVUdFZit0a1RiSENiNDNTSTduM2NEbllUZU1tRW5ZQ0FI +azQxYk0rWEJIaStKTlFocVhkd2psaGhiZGt4RDFhTSt6SlQ1b3d1Q0R0RWRF +Z2xxbTV5cE9OVkRXNit1RWE3bnVtY2hEa3dqYVZmSEx2anNCRUhlU2FFdnMr +Tm9TSFFheUZDakZVTGpZejZHNndiYmlKT1h4bHI5VkE3S2t0RjBFaWluUzhu +VXZCdTBBZzhkZEVsTjZHeUpVSGJLOXIvVVVKQmpTTDc3VVBwbnlXeEd0TUV5 +a0owZkx4ZXFhZVQvaE9oRkJDbmRUV2duYjJwYWgwdDlNaUFDWDErK0dZcGU1 +bTJWQjYxb3BBcndidzM0UkhjeFlZVFBMSkc0YmtraEg3NkJodGtWS0R6Zmlt +Mi8xNlh4dmpodzQ4cVIzQW1qUDdEV2ZXeHQvZVdFVHdVbHArcmJmOE9WWjhn +aU1jbzAwTmFJQ09DeFlYYVlHTmE5OVpmV2FuUXJ0aUgvLytRQUd0WCtRNzRs +VWo1bS9GcHd1NGU3TWJYc3ExUURQUk9LN2I2NU16cGovZ3VUak00T0lGK1p0 +TlhPMG9hbVlaamwvaU1sRFVJSGEwM3Z6aEdLZUNuL0M4ZFlUSVVQamhZZzRw +TDQrQzRmSCt2SXRoc2FTY04xd1FKQ29UYmd2MzZ1a1MvSG04bVB5YmVGaHpp +Y0haSmJBTHZEMTRnK3M5S3U1bWpNamh1ejc4dWYxdVRldHp6U1V6ZkFxWUFn +RFJieE9Ma2JnUnRsK3pFTWMxK280Q0JNMU13aDFjMEhRUzVvZ0VBd2kxb2hO +ZlgweURHVEZJZ3lCUktBNEtVOWk1T25XcWNxWFdNRURCYjR0UnM3VHY5Z1RG +dHRHQlZvZm1nSUQwZUZ0cDh0V2ZQajRsS2tCQWJrdHRBaW4vMmlGS1Yvd2Y1 +eVR3MXFKemphYllOd21RbXEvNzRDOHU5QjhGc21Bcm52QkF6SmlnT1ZqYTRs +L2hWRVJNZjkweHRWbjI4K00xd3I1cldXZ0xiclh4VS9zR3hoTHg2Sm83aFcv +Mm1uWDMzZlNvYWI3OTRpUmlBMHhBbCt0dGduWDRXaDZsYkV6eXdBbFRWUnV3 +S1hvVWVwekdncDMzQlBtVnRGRktUalB5eWdkSm11MTgvV3ZLZjZoM2dJWGg5 +eHp1eUdySklIOURaUkwvT2owcmE1R0ZDc0ZPMk5kbHNLb2VwVDJoSUJLL1ow +OXhQL2xJZnpkMXB4OGh2S0EyWDJ5ODZZL2V4NWM5QXlnWDlvdzk0S1JIaGlN +MTM5UTVVNFo0QlJ1dFhYQVFpbW9hOXJKWDhpakFEQm1ZaXU2UGxrZFUyZjk0 +OUNNQWcwcVBOQVVpRmZtTGcrNjhWM1JYRkxNaUt6bFJUdHQ3Tm9MLzF3VEpt +ZTJkdlBkWGE1RWp4Wml3YzQyV1BhdFFsamE2U1NGZ0tONTEzZnVMeE5MMTVE +NVZ5eTAxaTA4eW1VRmlDU0E0SGpCMHpIdm4zYTI4Vi9ERzV1UE1RbDAvcHp6 +UnFrMkIvV3g4MlR2TDBIeGQyaVJRcDVIVlpXdVVlOEcxbHRnU0lCZlN4UENW +dTNlWXZEc1cwQmZUY2NaVzFtcUx4NTVXU29JRHF4K200RUlmT0JSTTh4ZUI3 +RzJIekt2YXdrTTBaM044M0cwRHRtbnVtbU85OCswTm9PSmg1eUpnRytDcU5V +WFFpWlYrci9FOEF1Ums2WFdseHlubVdhVnN6L0pwVjcxMVF5cFEyOFlMTllQ +UUpoVHlDOXdSWEtKbjA1eUswbHAvWmMrT0g5SzMvNXVQM3NQeHUyWGFzTWc2 +SEhxdEFrZGRrc1ovTUxGcHZLMkRQWS9lK20ycFJvL2ZJQUhIOGlhUEFiVS9V +bWUxMXlkb2R0ZlNsc0RDUUlpVUF4SHpJZEcyUW9QMFFCdURDaXlnemxkdHRn +d2xxYWZvS0EvVXVmdDNJTVBMd3VzTHUwV2x5MjlCdnRvbEtSS3FWRS9JWHJK +WlNPRC91TlVMZVU4Q2ZyY20yeVkvRTF5TGFscnVLaEVocTFRa3lsdWxtSGps +TEF4OGtqL0gxVE1JNmdEdHl1bnBIa21ZWjV2dkwxeFJWQThwd2RTYk1QTEd4 +MjkzS3FRYmlBUHRKMjRvcFNDc2RCT0xpM2lrUnBubkUwQW52NFA2QkNwcm5z +TnQrcWNPeG1KLzl6U1JoYmkxREpqSXJFajBCNzRwSHZWMFB1QytvVVpjd1Zk +RmkyT2orcEd6STZ2RDBBRUh1YTBxR1NseE05VlNnSi9wb0hlYThTOU1JSkU3 +b0wrY2pzaDFiV21lbjFTMWJYeS9HdTc5YXhRVHlJdGduclZYQU9ja1BtNC8r +ZzV6c1dhWjFma0cvOGFVdHJtc056bkRxREloTHZyL0F4dnFPdkk4RUZHbEhz +WEhmRFlRWmJFV09KRHdzcGpDUmltSVoyVHhpSFdWTE1SSS91eTNoeDUrUUpl +ejNEODRpakxiSDhETkhhTTZlRnlaRWRSRkpta2M3ZUMwWUZ4K1lkVTI5K2cw +bHo2b0I5RGNIc1Y2bjczS1E3ZW9kNTZ2MkFscDlLNVZ2NVVmbUkvUjNGMWZz +M25ONFBXTTlWMlBPblppUjNyUFFPNUVvQ0daNU9BQW8xTTFZa1pTV0gwZE1R +SitBak55NXVOTkg0a1k3SXhneEhYRVAxY3hkSlg4QXdUeGlrS05weU9pcXRt +M1VQQk85YXBybitWYmtpUVhvZ04xTTlRZHFNams0djd0TENQR3ZoLzlvOTk4 +c2ZYb2F0UWpLWjdCb2FXSThVRGJYTDFsQ21TeS9YM2lYcVQ1cWdVdDhBTnRi +N1lnR1M5eUV1WHdSVmp6eVhWbTF5bDFBOWVMcjB1SHlPSXpIODlSZzBkcm5y +Vy96ZFd0YkNPVGZCeFNrQ1JjQ04vSFhLV3N1YmJ6TENhbXB0bEMyMHExbG1o +czVuL1pJc0FUR201MjRScUFxcVI2bFc5WjFWV0NubXRQd2hrYVFFcjV6RFlj +UTFCSm94MFpXK1dHTlJyQkhyTTZEdWREaXZXYmR5UVY0aU9NSUNKQ2JMR25D +UDkxS3ZKOUs3dnNZU2hzeFArMCtac0Z6OHRWa0JhUXoxZGtXUUVROEZFRnNM +WjF0dmFhNmFETHNnWkd4MmxhZDRJUE9XdFFuNENZenFncGtXTlJlK1hPVXhz +YW00RmJ2ZG9OeWJydVRSTUJ3elZ5V0lZemI4Q1p3VVFqWk1jWjg3VlNqa2pQ +SkhLUndNY1d6cXBJeHpNOHpibFhteVlYVjQyOUthQmpYT0JIRExYWStkOFBJ +Si9jZ0VRZWw5aDN3Y3ZXbDlWMDdZR2wxb2N4S3VTNUxEd2QycHR4Y2k0cm5F +QU5odGhIL3pRK0J2dXExOFh0T3BGUzVmV3RoeHRCR2w2d1hNQjljaGN2S2lI +MWF5VDBUb2hPY2pMajhwVnlIalVRSFprWnFFa3BlbjJnSitzcnJuN3gvZnFz +d2dodWU2ZGlqMVYzTHl2eHRSTjlXSVJmS0ZXeXRMdjRnbm1oaVpEM3B0Qkl5 +ditZcVlrMSs1eDRXeVloeXVQYStvaGhoZ1NvdnhweVlmaDRaNklBTGJrOUc1 +cncvSVpxOUtxV0l0VGYrMEE1TGxDamJaVXFwckdNZEVhckhQYytnNmYyOHVG +R0tXZXBZa1ZxRjU4Uzh4OEZPQzV2TmhtSXFLb1NmT29pQTNpbjZiNytFVyt4 +VGdHQSt4QWJ2WklwNjRwZEdmL3NxMGN1VE53L0NDdG13bExOSUZZcldaOGpG +RE80azdXb2NydFV4WjBkMGFNSUR0a1Q4VHNldlNEVThaMmlWOGhWLzlMWmox +c2pHb0diL3dZSkoxRkpDaFdqVjlzM0cvZ0V1MHJGMkI5MEZKN2FhYkN0K2Ez +Qnk4TWhqMDVodlN6TllUbUdUbEdyQS9XdGNlRHFlMHRxeGZHKzNlZjYrYUNa +VndjamlWYk9jVG1WVmNaRTBjeGMvMVR4bDdzTzJvdHdsanFLQjZmbDk0MEcv +RkRnR09adytqenNpYWN6UnhBVnJseGVudG9qaUovNnFWOFlWc0t2RC9ESXNN +dXRNWDNKaU1yaDQvTERDYzIzVlNLVldGVHFzSS9pUWtXK09ZcTMxa1ZJK2d6 +d0xjR2lEd2V4RWhuZHNwS3pMdFVnMnAwZFdwZjR0ZEFqb1dUNC9naXRUNGhC +dHJldFk0OUhXMGJ4WWJjUzRNWk5LaytuTVdoQ1FYVlBGQSt2NXpYWjV4RXRD +ay9SZFZVbHVVQjJHQ1lISnZBc1JVdDRPcDZneG10dmo0YTZ1dzYxMzBtYmRx +djBjaFVVN0toWDZMMjJEeDZTUEVtSFdJSll3WGJFQXI2TWlYNWFXNk96WThN +ZmVsVktObUc4ejVWOWlsT3F4S1E2R2tyZStUYmRHNUZDREZ5TGdrZURqK1R5 +ajlabDRSOTRKZW9vSFpuQTUrSDRpenlvSnVRRnhoc2FPUGd2NTJxTmozSklp +TGc1MlJZN09Ubkhxam54bXAra21IZTFBQzNkWldKeFRtQnVHTThDQjU0bHNy +VmtBQ2l1N0pPaUxtQklsK0w4bEVKYWRtVUNVYlVrbnRlbTdndytkKzV0MEVQ +R1EyamZMYXYyemhMeG9rR05OV2x0NWRSa1lOVEVmZC9PL2JFMVlGQm5PV0VD +bHZ5c2JIMG9WWXAyZ3FnUndtWHZUZHFBeTZ0RzgxWHA2cUN3QUhpOTVZSStE +SmUrNGpYRXY5Ly9YQk9OekpJNzJTcXZCSE5qejVaOVZNbzVUYk5MdlRTd0hw +dnFJS3VrQjB0Q0s0Mml5NWZCcXlUNU1mc0RkV28zTVlDSWNtMEJPeUxxbVY5 +RStZeUlaYWI1bVN4aU41WTBpSEJqTkJJRWxldHRyQ3ZKckZJcGw5R2Q1YWQw +WkwzR3Nxa0FhdmtycHlyNXpHME9FWlp4R21WOVdJUERyTmNHRDdQejRGVE13 +blRsQVBnbmJHYXBuUjFiZFZ0SzdpTHRWbHRtU0RtYlhHZFY3ZDZ2ZWUrdG50 +SUZRNWZZcFhPMHJ3dStrZDZBY2ZtMGgrM0hiMWwxK0JCRi85SEEvakdqTnNW +amRpamZ0S0hhY0Z1WHNYVlBJODgrWGdDRitRTEtCSzVRQU1IbGVhUmdiT0c1 +a0s2YkhPVVN5cHltenNxSzZSRWRtMlhxN3lSa1RXZm82c1BidGpGWlhzbS9C +TjF1ZWtRY2tVcUdWTmxFRm83M1VjQkpqTVBmUjgvNTZWTFQ3UEU1eGFmZUxn +cXZyNWVVK2pVa1craWMvdWVwV0Q1SG0vbjl3TVhVMnp1MS9iN2dWSG5kQXNp +Y3d6OWtBYXA5ZGc2UGlhQS9Hc0R4YzUwcG53cmFXcHFUbnFlRHZraUlCdGRK +bWozanU3bWR2K3ZmRzNUT1hDeDc0aWxXOTlhR3BtaXk3cS9JVFIwc1F0aXQw +clNsYm81Z3BZZXpobFVSL2hNMktraWhuK091a2srdWN5b1h1S2JjNnZIL1J6 +enZlOWtaWS9QMXowOWhTTWt3M3BtbUpITXJ2TW5KTzM0U2JzcmRGSjBKb2FE +ZzBpSmttNlU0OFlGRkJGTUdoaUowcUdyaEJEMGNDTHdVNEI2dkczL21oekJQ +RjZheXRZTTNsY3RaT1pxc1BqUWFvSHc0WElLSUcyNGdWSG1BeWpKd3lwRjVH +SDlhOFI0SHNVTTVydm50MHBtak1vWmhzeVJpNFdVUnZIVVIwZG1Rc0tHV1By +dDA4cExEaXBEM0IzTVEzNENpL2FMVHVPajNIMzNNeC9LQm8wckxTWWxjR2Nv +Y0dVZU1YY0U3U2NJZnUyQWN5K0doSFlwV2htMllWSU43YjVkZlNoczhzSDNu +WlNjMlNWWW5IMVVrc09IcHR4YlV4YnRONFNKTVhXRjdzZFdOZ2cvTkpVSVUw +QUlDNWlLUUxpUTUyK2NuY1RCYVJvd0ZzZVB0OE4rS2lwcTdpWDNYZmpNNFU3 +ZjFYM1V1QVYvbVJIRE96RG9yWHdRNEUvQ2R6S3g5a3VEQ2pjbERWRWNoMlBG +OUlYaHF3N2NqMGdaRU5rbE9tSHFkaDJKQXFhb0hTcWhzYktJYzF0SE9SS0o5 +Ty84ZnluNGNIbHRGVFFZNEhrRUhpYnNEU1k0eDFuU05NRElKRnhTUTNjZitz +dEI3WVhxeWNHUyt0cTVJK1Ava3pqWFFDNjNCSS9WNEZWMklQeDAyMkdsL0cr +Mm8rcmNvci92c0hMbGMvQmcrRkFvazYvWUFwZE1TbCtHelNraU9YZ1lJRnRp +eHZJYWI0S0UvWU9OZWh5dlVOZjQ5WGR4eGEzQVFIZ3VhOXgrK1VIMmljazRZ +alVzSlFFUXZuVU5QL24rSkZwM01EUU82bDZZeHBkMGdTZ3JNTVppREVSSzJV +S3lXNGN5RkJLV1hHTjNWbU94alh0c1BJSHhWaWNvNmN6OWhYakpkSVJUUXM3 +dTM4TjYwSnVXZHl0YyszMzFKT3FNNExuSFVadldjYW5GK1RmRno2ZUdDc0pZ +MzlJa3Q1NVV2cWpGemExM3ZNc1prTUcwVEFMbS9jMXhDWG9GTjlhU0VyeDZX +YzhnWlVYL3JzcmtOUzRNYUZNTmxzMlZBQzZ2YTJML2FZQStYRWxtU01rRHdi +dTNmeGtTNmd3czRGbEFiYzhOcFVqQ1JESFJyaEl4ZHkrWEZVVlFMT3UrakFQ +U2pBN04vVnVXdjR6U3NsT3NLSm9xbW91ZkVhQlFzUGN2a25yNk1iUHU3bDlG +VDd6VDVRc1N2cVhRajhGOVhNcVE5OG5PcFF5bitLZHlIbTVXZUlCM3o5ZEFO +QzBSbGVUbHNjaXgvV0xacDdnaUo1aEFHeXZVclFVSzRXa25LWXdtNk9QREhZ +czR1VkZwUHBscDhUMUNmNElNdk9lMFp4bHFZcjI0TjVpYjNhTkJOVXROMmY4 +K3ZqMDZjU0hVZmRmRHpTQitsTXpobHFrK2tYR3VUU1lHY21kSk92QXBxK0Ja +YmlQTTFJdHRSbVp5YThEVzl6MTcwZFZQeHlXMnJlRDFLdUZ3SVZVeTgyNFJl +eWFXQyt1T1JNd3VoUGN4V3ZWZHF0QWNzeUNRTS9OUFhJTk9hN1pTN0h3OEtJ +WEhLbUtIU1pMQnUwelNCNXUrTkhTTlZmNzUycTI2NTdGWmxvL3ppRnNEWGpn +bGY4d25tbThsQXdnQ0tvYVk4dEpVUXRyTVFPRzNRMDE0VUptUUZ3T1paYTVV +c1kzaSsraThoY2NjazhCaDNDU3FQdUdFQXZ3bkNFY3AwcjV5TUtXN1VMc1pL +QkdJWXNQQTdDSGRLR1hOaHVyQzl0WGl4bHYzZXgvWVliYitTQWpaUjE0Z1ht +Wks1SXR6Vk5jekllK2xkeFVPY0V0SXRDWEpZZ0owcnRpRlFiVFozY01GY0ts +c1B4NE9zZ1RUQm00WUF0dm9SZ1JqZ1poUzMyVm9vRU1vcGJxa2dkL1p0dDZq +d3ArWWJ5VGtjRXRHZzRYUEN3M1A2TWVLNEt4aUV2a2tZdzRjU0J3eXgvcXpC +N21aajFWZlN2emk4a0FIc09TUkQ1dFh2Rmdabm1VSmNyaVNVdFNwdW1OTmow +ekZoQjBSUjlvSTZtMW9TTm5CZFE0ZDRCOU1Fa1grU2hSb2oySGovSkF3dlJK +Y0YwQU9hMWJ3dWFkN05sUXJ3ZThuR3JHdVdKUEhNTXNlMjNUNmp0L1NiV3RR +K0dXckNVQmxRaElaSEYrOWtrQ0ZtMnJlSzFRZGFOMFdia1FKeEx0Y1hFb3c0 +dnVpZzBZOW95RXJ0TG1IOXJ6N3dGbWxOK0hlRm9XN2IzeTk2RDU3NHNTYU9N +d3N4TWsvcCswdVFVeFNTMm14WFNkaGJHZGhaOGw5QkZrYkxkeHNHOHVQK2Zx +dXdnWlBHdDRyN0hoSnp2VkYrNEVGaHN4Um10dDlxSjBNdlluSk80a0d2eXlS +UW9zT2NJaWpmRVZhaUt3UmZSZnpYcnVHdW4rSjd3UzE4c0h4L3Z3SkVhQ25y +eExlckF5UEd0b3gzbm9wZ2FKdXdpeHpqVlFKZGJzTWdsTE94a3NWMkdLL2xm +anBTSlhiN2ltcTVkdFAzL0ZuK0xqZWhTRkRyMUVEdExEM2taN2JIVnNFWHNt +ZVdlRUZDQlJoOFk4TDk3WVcvd3NHUWVRQUJDSXJKMyt3dkNLcG03bGNkeUhn +VmhSNXFzSWZKcVZJaGRjdnRaUnRDc3pSRWtGeDR4NXZ4TERNQ0lTU2sxVVRk +TGczMVI4VWl0TjczRWY5a1ltUkQ1dk5DcU5FR01uRHVxYjE2NUJoSVR4b2pw +WitvQ3hrQ3ZlUTJhMWtJVm9NK01mOS9Ka0k3S1Z1Yy82bW1lODlOZ2t3V3ZH +R2lQeThPelZNUEtMK3ZMOVYxQUVjMzhzRzRvQXliRGlmTzE5OU5FaGhKSjh2 +Ym1VdWpMbnArait1S1UwS2NYam92OFYwdnpxMW54VlZMcktuNkMrVVd1Ylpi +a2h0NTBxODFKRXlwVnRJM3A4Qi9kRVlmTEk2cDlobVB6aXJJVHExbWFGaFYz +VmxpTkdIN0JIYjM4eXRqY0dGcHRZdEFheE9XUjZFWkpXSkNGQkMza3ZPWDY2 +d1F6TzVPemlCc1d3M3R0Yy93c25hamFNcEZhSmFBZmVrZ25hYklDVjhEbjBt +RCtMMlVPcFNYeDJnUFp2YWs3ZUN2eS9NdWdpM1cwM3l6SHJ3Z1U3OUVsUXZ0 +K1lNaTBZWFp2am1vU1BnRVcvSXA2NXFBZVRNNFc3K1NiNFp1a1JOdFNiT1FZ +R2pBSXJLdnVIMTNKRUQyQmRCQmlEeTQ2NUdoaERNV3QyZXpCNnprSFBIOGZl +VmN2cVMxQ0UzL2VFeVZUQ2I1TVlNWkFTakJmd1RrbTk3OGxGOC9VVGExclZ1 +SElqY3RtZXZWNld6TVV6bnZyZHVjVDV2Ulk4NGV6MDZKb1haWEVib2t3cjhh +QU41ck1WVjI5UkQ0M0hkdE10akJsOW5TZjVCOWxmemcvYUpwODJ1bFp5S0RK +WCtyY285RVpWZkRpcVE4WU9seWVQZWRoUUQwYWNYMkJGNTRtdm15L1kyYzlP +ckdVWFJzV1JHeXJPTHQzQTJpMDBVdXFkZ1p2VFdiS3RvaGM5bmZaWTArTVRo +YnBNOXJjS3lReHZLYi9WNitad3UzdjVQR0xuQzhNUDJoSEFtOFJMVE05R0JV +VVNWTGhwdEJzVkpHMUs1OUFNb0pHajZXVC9IREtwQzBDVmh2aHFFN25BeWlG +blI1UGgzWTl3L2NGU1A2TGl2NXp2ZEMrYy94RFkzeWVESTN5MnNjMVJWSUpK +VFowRDVBU1Y3NS9ibmtqNFM1bm52aEQ0TFdKbzdzYmNwMElaWktEY2hQNmRj +dUpDNTBUVXVRVndNWUxRYTgzMVJEdlo2M3d0VXpVSE8rSDBsek04UW55Q1Fl +MWNYMkp5QnFoN3J3WEUrZVM1dmhPcWdmRlR2VmN5ZGtOUlh3TnVLV09HV2Yr +K01WWlhrUHEwcStlYWJUNmpiRTVSd1NKZGpXN1JQbC9xc1FpaS9ralMydUlN +RG80RnowUE9nYlAzQTltQSt1ZC40Rk1JaGxsRU9qL1R0ejI0LlptSWZrYjlF +a0dBUnQ0c0dZY2xTSXc9PSIsInNpZyI6IkgrbXZnTG5md3pRVG9ZM1NuNEVH +M285SXUzYW1qVGt1MzVkN0FlL243OHBJOFJMWmlhQzBZNUFHdDNvaDl1cWhn +VVl3YTJiNkdTbHlxR0xHYnZXRkJnPT0iLCJhbGciOiJhZXMtMjU2LWdjbStl +ZDI1NTE5In0= +-----END LICENSE FILE----- + diff --git a/testdata/release_license_not_found.txt b/testdata/release_license_not_found.txt new file mode 100644 index 0000000..14de10e --- /dev/null +++ b/testdata/release_license_not_found.txt @@ -0,0 +1,19 @@ +# Remove existing database +rm -f relay.sqlite + +# Start the server +env PORT=8086 +exec relay serve --port $PORT &server_process_test& + +# Wait for the server to start +exec sleep 1 + +# Attempt to release a license that was never claimed +exec curl -s -o response.txt -w "%{http_code}" -X DELETE http://localhost:$PORT/v1/nodes/test_fingerprint + +# Expect a not found response with status code 404 and error message +stdout '404' +exec grep '{"error":"Claim not found"}' response.txt + +# Stop the server +kill server_process_test diff --git a/testdata/release_license_success.txt b/testdata/release_license_success.txt new file mode 100644 index 0000000..24eb274 --- /dev/null +++ b/testdata/release_license_success.txt @@ -0,0 +1,25 @@ +# Remove existing database +rm -f relay.sqlite + +# Add the license +exec relay add --file license.lic --key 9E32DD-D8CC22-771926-C2D834-C506DC-V3 --public-key e8601e48b69383ba520245fd07971e983d06d22c4257cfd82304601479cee788 + +# Set a port as environment variable +env PORT=8085 + +# Start the server with heartbeat disabled +exec relay serve --port $PORT &server_process_test& + +# Wait for the server to start +exec sleep 1 + +# Claim a license +exec curl -s -o /dev/null -w "%{http_code}" -X PUT http://localhost:$PORT/v1/nodes/test_fingerprint +stdout '201' + +# Release the license +exec curl -s -o /dev/null -w "%{http_code}" -X DELETE http://localhost:$PORT/v1/nodes/test_fingerprint +stdout '204' + +# Stop the server +kill server_process_test diff --git a/testdata/server_database.txt b/testdata/server_database.txt new file mode 100644 index 0000000..a0fc21d --- /dev/null +++ b/testdata/server_database.txt @@ -0,0 +1,32 @@ +# Set a custom database path +env DATABASE_PATH=custom_relay.sqlite + +# Remove any existing custom database +rm -f $DATABASE_PATH + +# Add a license with a custom database path +exec relay add --file license.lic --key 9E32DD-D8CC22-771926-C2D834-C506DC-V3 --public-key e8601e48b69383ba520245fd07971e983d06d22c4257cfd82304601479cee788 --database $DATABASE_PATH + +# Ensure that the custom database is created +exec test -f $DATABASE_PATH + +# Set a port as environment variable +env PORT=8087 + +# Start the server with custom database path +exec relay serve --port $PORT --database $DATABASE_PATH &server_process_test& + +# Wait for the server to start +exec sleep 1 + +# Claim a license +exec curl -s -o response.txt -w "%{http_code}" -X PUT http://localhost:$PORT/v1/nodes/test_fingerprint + +# Expect a success response (status 201) +stdout '201' + +# Stop the server +kill server_process_test + +# Clean up the custom database +rm -f $DATABASE_PATH diff --git a/testdata/server_ttl.txt b/testdata/server_ttl.txt new file mode 100644 index 0000000..af6d085 --- /dev/null +++ b/testdata/server_ttl.txt @@ -0,0 +1,39 @@ +# Remove existing database +rm -f relay.sqlite + +# Add a license +exec relay add --file license.lic --key 9E32DD-D8CC22-771926-C2D834-C506DC-V3 --public-key e8601e48b69383ba520245fd07971e983d06d22c4257cfd82304601479cee788 + +# Set a short TTL (e.g., 2 seconds) +env PORT=8088 +env TTL=2s + +# Start the server with TTL flag set +exec relay serve --port $PORT --ttl $TTL --cleanup-interval 1s &server_process_test& + +# Wait for the server to start +exec sleep 1 + +# Claim a license (first time) +exec curl -s -o response.txt -w "%{http_code}" -X PUT http://localhost:$PORT/v1/nodes/test_fingerprint + +# Expect a success response (status 201 Created) +stdout '201' + +# Claim the license again before TTL expires +exec curl -s -o response_extend.txt -w "%{http_code}" -X PUT http://localhost:$PORT/v1/nodes/test_fingerprint + +# Expect a license extension (status 202 Accepted) +stdout '202' + +# Wait for the TTL to expire and cleanup interval to run +exec sleep 3 + +# Try claiming the license again after TTL has expired +exec curl -s -o response_after_ttl.txt -w "%{http_code}" -X PUT http://localhost:$PORT/v1/nodes/test_fingerprint + +# The license should have expired, allowing another claim (status 201 Created) +stdout '201' + +# Stop the server +kill server_process_test