diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..cf9a6a2 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,88 @@ +name: CI Build and Test + +on: + push: + branches: [master] + pull_request: + branches: [master] + +env: + BUILD_DIR: obj + +jobs: + native: + runs-on: ${{ matrix.os }} + name: "Native build and test on ${{ matrix.os }}" + strategy: + matrix: + # MacOS-13 is x86_64, MacOS-14 is ARM64 + os: [ubuntu-20.04, ubuntu-22.04, windows-latest, macos-13, macos-14] + fail-fast: false + + steps: + - name: Checkout code + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + + - name: Build for slow machine + if: matrix.os == 'macos-14' + run: | + cmake -S . -B "${{ env.BUILD_DIR }}" -DNSYNC_TESTING_SLOW_MACHINE=ON + cmake --build "${{ env.BUILD_DIR }}" + + - name: Build + if: matrix.os != 'macos-14' + run: | + cmake -S . -B "${{ env.BUILD_DIR }}" + cmake --build "${{ env.BUILD_DIR }}" + + - name: Run Native Test + run: | + ctest --test-dir "${{ env.BUILD_DIR }}" --output-on-failure -C "Debug" + + cross: + runs-on: ubuntu-22.04 + name: "Cross build and test for ${{ matrix.platform.arch }}" + strategy: + matrix: + # Arch: arch for QEmu + # Libs: path to cross-libs + # Triplet: triplet of the compiler + platform: [ + { + arch: alpha, + libs: /usr/alpha-linux-gnu, + triplet: alpha-linux-gnu + }, + { + arch: mips, + libs: /usr/mips-linux-gnu, + triplet: mips-linux-gnu + }, + { + arch: riscv64, + libs: /usr/riscv64-linux-gnu, + triplet: riscv64-linux-gnu + } + ] + fail-fast: false + + env: + QEMU_LD_PREFIX: ${{ matrix.platform.libs }} + + steps: + - name: Checkout code + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + + - name: Setup cross-compilation toolchain and QEMU + run: | + sudo apt-get update + sudo apt-get install -y g++-${{ matrix.platform.triplet }} qemu-user-static + + - name: Cross Compilation for ${{ matrix.platform.arch }} + run: | + CC=${{ matrix.platform.triplet }}-gcc CXX=${{ matrix.platform.triplet }}-g++ cmake -S . -B "${{ env.BUILD_DIR }}" -DCMAKE_CROSSCOMPILING_EMULATOR="qemu-${{ matrix.platform.arch }}-static" + cmake --build "${{ env.BUILD_DIR }}" -j4 + + - name: Test w/ Qemu for ${{ matrix.platform.arch }} + run: | + ctest --test-dir "${{ env.BUILD_DIR }}" --output-on-failure diff --git a/CMakeLists.txt b/CMakeLists.txt index fcc3f41..fafb85b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ set (CMAKE_POSITION_INDEPENDENT_CODE ON) # Allow nsync users to turn the tests on or off. option (NSYNC_ENABLE_TESTS "Enable for building tests" ON) +option (NSYNC_TESTING_SLOW_MACHINE "Allow relax waiting time for very slow machine" OFF) # ----------------------------------------------------------------- # Functions to set common options on targets and files. @@ -291,6 +292,10 @@ set_cpp_target (nsync_cpp "${NSYNC_CPP_SRC_COPY}") if (NSYNC_ENABLE_TESTS) + if (NSYNC_TESTING_SLOW_MACHINE) + add_compile_options ("-DNSYNC_TESTING_SLOW_MACHINE") + endif() + set (NSYNC_TEST_SRC "testing/array.c" "testing/atm_log.c" diff --git a/testing/cv_test.c b/testing/cv_test.c index b0aa31a..7cc5ba5 100644 --- a/testing/cv_test.c +++ b/testing/cv_test.c @@ -203,7 +203,11 @@ static void test_cv_producer_consumer6 (testing t) { /* The following values control how aggressively we police the timeout. */ #define TOO_EARLY_MS 1 +#ifdef NSYNC_TESTING_SLOW_MACHINE +#define TOO_LATE_MS 200 /* longer, to accommodate scheduling delays */ +#else #define TOO_LATE_MS 100 /* longer, to accommodate scheduling delays */ +#endif #define TOO_LATE_ALLOWED 25 /* number of iterations permitted to violate too_late */ /* Check timeouts on a CV wait_with_deadline(). */ diff --git a/testing/cv_wait_example_test.c b/testing/cv_wait_example_test.c index ab34cb5..9eb1eeb 100644 --- a/testing/cv_wait_example_test.c +++ b/testing/cv_wait_example_test.c @@ -136,6 +136,19 @@ static void example_cv_wait (testing t) { static const char *input[] = { "one", "two", "three", "four", "five" }; string_priority_queue_cv q; a_char output; +#ifdef NSYNC_TESTING_SLOW_MACHINE + static const int waiting_factor = 2; + static const char *expected = + "one\n" + "three\n" + "two\n" + "timeout 0.2s\n" + "four\n" + "timeout 0.2s\n" + "five\n" + "timeout 2s\n"; +#else + static const int waiting_factor = 1; static const char *expected = "one\n" "three\n" @@ -145,24 +158,25 @@ static void example_cv_wait (testing t) { "timeout 0.1s\n" "five\n" "timeout 1s\n"; +#endif memset ((void *) &q, 0, sizeof (q)); memset (&output, 0, sizeof (output)); closure_fork (closure_add_and_wait_cv (&add_and_wait_cv, &q, - nsync_time_ms (500), NELEM (input), input)); + nsync_time_ms (waiting_factor * 500), NELEM (input), input)); /* delay: "one", "two", "three" are queued; not "four" */ - nsync_time_sleep (nsync_time_ms (1200)); - - remove_and_print_cv (&q, nsync_time_ms (1000), &output); /* "one" */ - remove_and_print_cv (&q, nsync_time_ms (1000), &output); /* "three" (less than "two") */ - remove_and_print_cv (&q, nsync_time_ms (1000), &output); /* "two" */ - remove_and_print_cv (&q, nsync_time_ms (100), &output); /* time out because 1.3 < 0.5*3 */ - remove_and_print_cv (&q, nsync_time_ms (1000), &output); /* "four" */ - remove_and_print_cv (&q, nsync_time_ms (100), &output); /* time out because 0.1 < 0.5 */ - remove_and_print_cv (&q, nsync_time_ms (1000), &output); /* "five" */ - remove_and_print_cv (&q, nsync_time_ms (1000), &output); /* time out: no more to fetch */ + nsync_time_sleep (nsync_time_ms (waiting_factor * 1200)); + + remove_and_print_cv (&q, nsync_time_ms (waiting_factor * 1000), &output); /* "one" */ + remove_and_print_cv (&q, nsync_time_ms (waiting_factor * 1000), &output); /* "three" (less than "two") */ + remove_and_print_cv (&q, nsync_time_ms (waiting_factor * 1000), &output); /* "two" */ + remove_and_print_cv (&q, nsync_time_ms (waiting_factor * 100), &output); /* time out because 1.3 < 0.5*3 */ + remove_and_print_cv (&q, nsync_time_ms (waiting_factor * 1000), &output); /* "four" */ + remove_and_print_cv (&q, nsync_time_ms (waiting_factor * 100), &output); /* time out because 0.1 < 0.5 */ + remove_and_print_cv (&q, nsync_time_ms (waiting_factor * 1000), &output); /* "five" */ + remove_and_print_cv (&q, nsync_time_ms (waiting_factor * 1000), &output); /* time out: no more to fetch */ A_PUSH (&output) = 0; if (strcmp (&A (&output, 0), expected) != 0) {