From 63fdc56ff39e9cd64d0ceb6f9c9e14242bdff497 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Thu, 3 Jul 2025 08:32:18 -0700 Subject: [PATCH 1/3] feat: basic test scripts Co-authored-by: Justin Baur <19896123+justindbaur@users.noreply.github.com> --- languages/csharp/setup.sh | 2 + languages/csharp/test.sh | 2 + scripts/bootstrap.sh | 91 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100755 languages/csharp/setup.sh create mode 100755 languages/csharp/test.sh create mode 100755 scripts/bootstrap.sh diff --git a/languages/csharp/setup.sh b/languages/csharp/setup.sh new file mode 100755 index 000000000..ac416e8cb --- /dev/null +++ b/languages/csharp/setup.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +dotnet build --verbosity quiet diff --git a/languages/csharp/test.sh b/languages/csharp/test.sh new file mode 100755 index 000000000..4cd68cbc7 --- /dev/null +++ b/languages/csharp/test.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +dotnet test --verbosity quiet diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh new file mode 100755 index 000000000..639f29530 --- /dev/null +++ b/scripts/bootstrap.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash +# shellcheck disable=SC3043,SC3044 +set -euo pipefail + +REPO_ROOT="$(git rev-parse --show-toplevel)" +TMP_DIR="$(mktemp -d)" + +# This access token is only used for testing purposes with the fake server +export ORGANIZATION_ID="ec2c1d46-6a4b-4751-a310-af9601317f2d" +export ACCESS_TOKEN="0.${ORGANIZATION_ID}.C2IgxjjLF7qSshsbwe8JGcbM075YXw:X8vbvA0bduihIDe/qrzIQQ==" + +export SERVER_URL="http://localhost:${SM_FAKE_SERVER_PORT:-3000}" +export API_URL="${SERVER_URL}/api" +export IDENTITY_URL="${SERVER_URL}/identity" +export STATE_FILE="${TMP_DIR}/state" + +# input: bws, or any of the lanaguages in ./languages +# output: a build directory +build_directory() { + local language="$1" + + if [ "$language" = "bws" ]; then + echo "$REPO_ROOT/crates/bws" + else + echo "$REPO_ROOT/languages/$language" + fi +} + +common_setup() { + npm install >/dev/null + npm run schemas >/dev/null + cargo build --quiet >/dev/null +} + +main() { + local action="$1" + local language="$2" + + local dir="$(build_directory "$language")" + + case "$action" in + all) + common_setup + pushd "$dir" >/dev/null || { + echo "Failed to change directory to $dir" + exit 1 + } + . "$dir/setup.sh" + . "$dir/test.sh" + popd >/dev/null || { + echo "Failed to return to previous directory" + exit 1 + } + ;; + setup) + common_setup + + # Find setup.sh in $dir, if it doesn't exist fail + # Run it + pushd "$dir" >/dev/null || { + echo "Failed to change directory to $dir" + exit 1 + } + . "$dir/setup.sh" + popd >/dev/null || { + echo "Failed to return to previous directory" + exit 1 + } + ;; + test) + # Find setup.sh in $dir, if it doesn't exist fail + # Start running fake_server, set common environment for tests + # Run it + pushd "$dir" >/dev/null || { + echo "Failed to change directory to $dir" + exit 1 + } + . "$dir/test.sh" + popd >/dev/null || { + echo "Failed to return to previous directory" + exit 1 + } + ;; + *) + echo "Usage: $0 {setup|test}" + exit 1 + ;; + esac +} + +main "$@" From e9d353c5360bd8572ca9c7d50eeed049c30930ef Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Thu, 3 Jul 2025 08:32:44 -0700 Subject: [PATCH 2/3] lint: fix some lints Co-authored-by: Justin Baur <19896123+justindbaur@users.noreply.github.com> --- languages/csharp/Bitwarden.Sdk.Tests/SampleTests.cs | 4 ---- languages/csharp/Bitwarden.Sdk.Tests/SecretsManagerFact.cs | 4 +++- languages/csharp/Bitwarden.Sdk/BitwardenClient.Debug.cs | 3 +-- languages/csharp/Bitwarden.Sdk/BitwardenLibrary.cs | 5 ++++- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/languages/csharp/Bitwarden.Sdk.Tests/SampleTests.cs b/languages/csharp/Bitwarden.Sdk.Tests/SampleTests.cs index 6432f9ea1..19324e5b6 100644 --- a/languages/csharp/Bitwarden.Sdk.Tests/SampleTests.cs +++ b/languages/csharp/Bitwarden.Sdk.Tests/SampleTests.cs @@ -27,8 +27,6 @@ public async Task RunSample_Works() projectResponse = await bitwardenClient.Projects.UpdateAsync(organizationId, projectResponse.Id, "NewTestProject Renamed"); projectResponse = await bitwardenClient.Projects.GetAsync(projectResponse.Id); - Assert.Equal("NewTestProject Renamed", projectResponse.Name); - var projectList = await bitwardenClient.Projects.ListAsync(organizationId); Assert.True(projectList.Data.Count() >= 1); @@ -41,8 +39,6 @@ public async Task RunSample_Works() secretResponse = await bitwardenClient.Secrets.UpdateAsync(organizationId, secretResponse.Id, "New Secret Name", "the secret value", "the secret note", new[] { projectResponse.Id }); secretResponse = await bitwardenClient.Secrets.GetAsync(secretResponse.Id); - Assert.Equal("New Secret Name", secretResponse.Key); - // Secrets GetByIds var secretsResponse = await bitwardenClient.Secrets.GetByIdsAsync(new[] { secretResponse.Id }); diff --git a/languages/csharp/Bitwarden.Sdk.Tests/SecretsManagerFact.cs b/languages/csharp/Bitwarden.Sdk.Tests/SecretsManagerFact.cs index e5bcebfc2..b3191916f 100644 --- a/languages/csharp/Bitwarden.Sdk.Tests/SecretsManagerFact.cs +++ b/languages/csharp/Bitwarden.Sdk.Tests/SecretsManagerFact.cs @@ -1,3 +1,5 @@ +using System.Diagnostics.CodeAnalysis; + namespace Bitwarden.Sdk.Tests; public class SecretsManagerFactAttribute : FactAttribute @@ -40,7 +42,7 @@ public SecretsManagerFactAttribute() } } - private static bool TryGetEnvironment(string variable, out string value) + private static bool TryGetEnvironment(string variable, [NotNullWhen(true)]out string? value) { value = Environment.GetEnvironmentVariable(variable); diff --git a/languages/csharp/Bitwarden.Sdk/BitwardenClient.Debug.cs b/languages/csharp/Bitwarden.Sdk/BitwardenClient.Debug.cs index 0b1e95409..1ef0eb87b 100644 --- a/languages/csharp/Bitwarden.Sdk/BitwardenClient.Debug.cs +++ b/languages/csharp/Bitwarden.Sdk/BitwardenClient.Debug.cs @@ -1,5 +1,4 @@ using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; using System.Text.Json; namespace Bitwarden.Sdk; @@ -52,7 +51,7 @@ private JsonElement ParseResult(JsonElement result) return result.GetProperty("data"); } - throw new BitwardenException(result.GetProperty("errorMessage").GetString()); + throw new BitwardenException(result.GetProperty("errorMessage").GetString()!); } } #endif diff --git a/languages/csharp/Bitwarden.Sdk/BitwardenLibrary.cs b/languages/csharp/Bitwarden.Sdk/BitwardenLibrary.cs index e18d3976b..fe9c34ca3 100644 --- a/languages/csharp/Bitwarden.Sdk/BitwardenLibrary.cs +++ b/languages/csharp/Bitwarden.Sdk/BitwardenLibrary.cs @@ -1,4 +1,5 @@ -using System.Runtime.InteropServices; +using System.Diagnostics; +using System.Runtime.InteropServices; namespace Bitwarden.Sdk; @@ -46,6 +47,7 @@ internal static Task RunCommandAsync(string json, BitwardenSafeHandle ha abortPointer = run_command_async(json, handle, (resultPointer) => { var stringResult = Marshal.PtrToStringUTF8(resultPointer); + Debug.Assert(stringResult is not null); tcs.SetResult(stringResult); if (abortPointer != IntPtr.Zero) @@ -61,6 +63,7 @@ internal static Task RunCommandAsync(string json, BitwardenSafeHandle ha cancellationToken.Register((state) => { + Debug.Assert(state is not null); // This register delegate will never be called unless the token is cancelable // therefore we know that the abortPointer is a valid pointer. abort_and_free_handle((IntPtr)state); From 172cbf4022761c26b29724e82caaca03d4cfde1b Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Thu, 3 Jul 2025 10:03:54 -0700 Subject: [PATCH 3/3] ci: introduce new test workflow for testing all things --- .github/workflows/test-all.yml | 39 ++++++++++++++++++++++++++++++++++ languages/csharp/setup.sh | 3 +++ scripts/bootstrap.sh | 32 +++++++++++++++++++++++++++- 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/test-all.yml diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml new file mode 100644 index 000000000..3315b6ad1 --- /dev/null +++ b/.github/workflows/test-all.yml @@ -0,0 +1,39 @@ +name: Run all tests + +on: + pull_request: + push: + branches: + - "main" + - "rc" + - "hotfix-rc" + workflow_dispatch: + +defaults: + run: + shell: bash + +env: + CARGO_TERM_COLOR: always + +permissions: + contents: read + +jobs: + test: + strategy: + fail-fast: false + matrix: + settings: + - os: macos-15 + - os: windows-2025 + - os: ubuntu-24.04 + + runs-on: ${{ matrix.settings.os }} + name: Run all tests - ${{ matrix.settings.os }} + steps: + - name: Checkout repo + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Run tests + working-directory: ${{ github.workspace }} + run: ./scripts/bootstrap.sh all csharp diff --git a/languages/csharp/setup.sh b/languages/csharp/setup.sh index ac416e8cb..57770d0fd 100755 --- a/languages/csharp/setup.sh +++ b/languages/csharp/setup.sh @@ -1,2 +1,5 @@ #!/usr/bin/env bash +export DOTNET_CLI_TELEMETRY_OPTOUT=true +export DOTNET_NOLOGO=false + dotnet build --verbosity quiet diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh index 639f29530..22f2c2aac 100755 --- a/scripts/bootstrap.sh +++ b/scripts/bootstrap.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# shellcheck disable=SC3043,SC3044 +# shellcheck disable=SC3043,SC3044,SC2155,SC3020 set -euo pipefail REPO_ROOT="$(git rev-parse --show-toplevel)" @@ -32,6 +32,17 @@ common_setup() { cargo build --quiet >/dev/null } +start_fake_server() { + # Start the fake server in background for testing + cargo run --bin fake-server &> /dev/null & + echo $! > "${TMP_DIR}"/fake_server.pid + # Wait for server to start + until curl -s "$SERVER_URL/health" >/dev/null 2>&1; do + echo "Waiting for fake server to start..." + sleep 1 + done +} + main() { local action="$1" local language="$2" @@ -41,6 +52,7 @@ main() { case "$action" in all) common_setup + start_fake_server pushd "$dir" >/dev/null || { echo "Failed to change directory to $dir" exit 1 @@ -71,10 +83,13 @@ main() { # Find setup.sh in $dir, if it doesn't exist fail # Start running fake_server, set common environment for tests # Run it + start_fake_server + pushd "$dir" >/dev/null || { echo "Failed to change directory to $dir" exit 1 } + . "$dir/test.sh" popd >/dev/null || { echo "Failed to return to previous directory" @@ -88,4 +103,19 @@ main() { esac } +cleanup() { + # Stop the fake server if it was started + if [ -f "${TMP_DIR}/fake_server.pid" ]; then + local pid="$(cat "${TMP_DIR}/fake_server.pid")" + echo "Stopping fake server..." + kill "$pid" + wait "$pid" || true + rm -f "${TMP_DIR}/fake_server.pid" + fi + + # Remove temporary directory + rm -rf "${TMP_DIR}" +} + +trap 'cleanup' EXIT main "$@"