Skip to content
Open
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
4 changes: 2 additions & 2 deletions .github/variables/cpp-sdk-versions.env
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
sdk=3.14.0
redis_source=2.4.2
sdk=3.15.0
redis_source=2.4.3
23 changes: 23 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,26 @@ jobs:
--env LAUNCHDARKLY_SDK_KEY="$LAUNCHDARKLY_SDK_KEY" \
--env LAUNCHDARKLY_FLAG_KEY="$LAUNCHDARKLY_FLAG_KEY" \
launchdarkly:${{ matrix.name }}

contract-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Get C++ Versions
id: cpp-versions
uses: ./.github/actions/cpp-versions
- name: Build contract test service image
run: |
docker build \
--build-arg="CPP_SDK_VERSION=${{ steps.cpp-versions.outputs.sdk }}" \
-t lua-contract-tests -f ./contract-tests/Dockerfile .
- name: Launch contract test service
run: docker run -d --name lua-contract-tests --network host lua-contract-tests
- uses: launchdarkly/gh-actions/actions/contract-tests@contract-tests-v1
with:
test_service_port: 8000
token: ${{ secrets.GITHUB_TOKEN }}
extra_params: -skip-from=./contract-tests/test-suppressions.txt -status-timeout=30
- name: Show contract test service logs
if: always()
run: docker logs lua-contract-tests
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ If Redis support is desired, then it optionally depends on the C++ server-side S

| Dependency | Minimum Version | Notes |
|--------------------------------|--------------------------------------------------------------------------------------------------------------|--------------------------------------------|
| C++ Server-Side SDK | [3.9.0](https://github.com/launchdarkly/cpp-sdks/releases/tag/launchdarkly-cpp-server-v3.9.0) | Required dependency. |
| C++ Server-Side SDK with Redis | [2.1.19](https://github.com/launchdarkly/cpp-sdks/releases/tag/launchdarkly-cpp-server-redis-source-v2.1.19) | Optional, if using Redis as a data source. |
| C++ Server-Side SDK | [3.15.0](https://github.com/launchdarkly/cpp-sdks/releases/tag/launchdarkly-cpp-server-v3.15.0) | Required dependency. |
| C++ Server-Side SDK with Redis | [2.4.3](https://github.com/launchdarkly/cpp-sdks/releases/tag/launchdarkly-cpp-server-redis-source-v2.4.3) | Optional, if using Redis as a data source. |


3rd Party Dependencies
Expand Down
38 changes: 38 additions & 0 deletions contract-tests/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Builds the contract test service: the Lua SDK from this checkout, served by OpenResty.
FROM openresty/openresty:1.31.8.1-0-jammy

ARG CPP_SDK_VERSION=3.15.0

RUN apt-get update && apt-get install -y \
git netbase curl libssl-dev apt-transport-https ca-certificates \
software-properties-common \
cmake ninja-build locales-all

# OpenResty bundles its own OpenSSL, and the SDK uses that OpenSSL at runtime.
# The bundled OpenSSL looks for CA certificates in a directory that the image does not have.
# This variable points it at the system CA bundle. nginx.conf passes it to the worker process.
ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt

RUN add-apt-repository ppa:mhier/libboost-latest && \
apt-get update && \
apt-get install -y boost1.81

RUN mkdir cpp-sdk-libs
RUN git clone --branch launchdarkly-cpp-server-v${CPP_SDK_VERSION} https://github.com/launchdarkly/cpp-sdks.git && \
cd cpp-sdks && \
mkdir build-dynamic && \
cd build-dynamic && \
cmake -GNinja \
-DLD_BUILD_EXAMPLES=OFF \
-DBUILD_TESTING=OFF \
-DLD_BUILD_SHARED_LIBS=ON \
-DLD_DYNAMIC_LINK_OPENSSL=ON .. && \
cmake --build . --target launchdarkly-cpp-server && \
cmake --install . --prefix=../../cpp-sdk-libs

COPY . .
COPY ./contract-tests/nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
COPY ./contract-tests/service.lua /usr/local/openresty/nginx/contract-tests/

RUN luarocks make launchdarkly-server-sdk-[0-9]*-0.rockspec LD_DIR=./cpp-sdk-libs && \
cp launchdarkly_server_sdk.so /usr/local/openresty/lualib/
27 changes: 27 additions & 0 deletions contract-tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Lua SDK contract test service

This directory contains the test service for the LaunchDarkly [SDK test harness](https://github.com/launchdarkly/sdk-test-harness). The service is an OpenResty application that runs the Lua SDK built from this checkout. It implements the harness's [service specification](https://github.com/launchdarkly/sdk-test-harness/blob/main/docs/service_spec.md).

## Running locally

From the **root** of the repository, build and start the service. It listens on port 8000:

```bash
docker build -t lua-contract-tests -f ./contract-tests/Dockerfile .
docker run --rm --name lua-contract-tests --network host lua-contract-tests
```

Then run the test harness against it. The harness calls back to the SDK on port 8111, so the service uses host networking:

```bash
./sdk-test-harness -url http://localhost:8000 -skip-from ./contract-tests/test-suppressions.txt
```

`test-suppressions.txt` lists the tests that are known to fail. Remove a line from it when the SDK starts to pass that test.

## Known failures

- Evaluation reasons do not include `ruleIndex`, `ruleId` or `prerequisiteKey`. The C API of the C++ SDK does not expose these fields.
- `allFlags` returns only flag values. The harness expects the full flags state, with `$flagsState` and `$valid`.
- Lua tables cannot tell an empty JSON object from an empty JSON array, so `{}` becomes `[]` in contexts, event data and default values.
- JSON null values inside objects are lost, because the SDK converts them to `nil`.
29 changes: 29 additions & 0 deletions contract-tests/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# The test service keeps its SDK clients in Lua memory, so it must run in one worker.
worker_processes 1;
error_log /dev/stderr info;

events {
worker_connections 1024;
}

env SSL_CERT_FILE;

http {
access_log off;

lua_package_path "/usr/local/openresty/nginx/contract-tests/?.lua;;";

# Keep request bodies in memory so that the service can read them with ngx.req.get_body_data.
client_max_body_size 10m;
client_body_buffer_size 10m;

server {
listen 8000;

location / {
content_by_lua_block {
require("service").handle()
}
}
}
}
Loading
Loading