image: "flowdalic/debian-testing-dev:1.20"

before_script:
  - ulimit -a
  - nproc
  - |
    readarray TOOLS <<EOF
    c++
    cc
    clang
    clang++
    clang-tidy
    doxygen
    g++
    gcc
    include-what-you-use
    meson
    nasm
    valgrind
    EOF
    for tool in ${TOOLS[@]}; do
      echo -n "$tool version: "
      $tool --version
    done

cache:
  paths:
    - subprojects/packagecache

variables:
  BUILDDTYPE: debugoptimized
  CC: gcc
  CXX: g++
  EXTRA_NINJA_ARGS: -v

stages:
  - smoke-test
  - test

.meson-test:
  artifacts:
    paths:
      - build-*/meson-logs
    when: on_failure
    reports:
      junit: build-*/meson-logs/testlog.junit.xml

smoke-test-suite:
  extends:
    - .meson-test
  stage: smoke-test
  script: make smoke-test-suite

fast-static-analysis:
   stage: smoke-test
   script: make fast-static-analysis
   variables:
       EMPER_IO: "true"

.fast-variant-check:
   stage: test
   script: make fast-static-analysis smoke-test-suite
   variables:
       EMPER_IO: "true"

iwyu:
   script: IWYU_TOOL="${CI_PROJECT_DIR}/tools/iwyu_tool.py" make iwyu
   variables:
       EMPER_IO: "true"

clang-tidy:
   script: make tidy
   variables:
       EMPER_IO: "true"

.build:
  stage: test
  script:
    - make

.test:
  extends:
    - .meson-test
  stage: test
  script:
    - make test

.gcc:
  variables:
    CC: gcc
    CXX: g++

.clang:
  variables:
    CC: clang
    CXX: clang++

.libc++:
  extends:
    - .clang
  variables:
    EMPER_USE_BUNDLED_DEPS: "always"
    EMPER_CPP_ARGS: "-stdlib=libc++"
    EMPER_CPP_LINK_ARGS: "-stdlib=libc++"

.emper-ws-scheduling:
  variables:
    EMPER_DEFAULT_SCHEDULING_STRATEGY: "work_stealing"

.emper-laws-scheduling:
  variables:
    EMPER_DEFAULT_SCHEDULING_STRATEGY: "locality_aware_work_stealing"

.emper-worker-no-sleep:
  variables:
    EMPER_WORKER_SLEEP: 'false'

.emper-stats:
  variables:
    EMPER_STATS_ALL: 'true'

.emper-userspace-rcu:
  variables:
    EMPER_USERSPACE_RCU: 'true'

.emper-no-io:
  variables:
    EMPER_IO: 'false'

.emper-pipe-sleep-strategy:
  variables:
    EMPER_WORKER_SLEEP_STRATEGY: 'pipe'

.emper-no-completer:
  variables:
    EMPER_IO_COMPLETER_BEHAVIOR: 'none'

.emper-single-poller:
  variables:
    EMPER_IO_URING_SQ_POLLER: 'one'

.emper-numa-poller:
  variables:
    EMPER_IO_URING_SQ_POLLER: 'numa'

.emper-each-poller:
  variables:
    EMPER_IO_URING_SQ_POLLER: 'each'

.emper-single-uring:
  variables:
    EMPER_IO_SINGLE_URING: 'true'

.emper-synchronous-io:
  variables:
    EMPER_IO_SYNCHRONOUS: 'true'

.emper-io-stealing:
  variables:
    EMPER_IO_STEALING: 'true'

.emper-lockless-cq:
  variables:
    EMPER_IO_LOCKLESS_CQ: 'true'

.emper-io-waitfree-stealing:
  variables:
    EMPER_IO_WAITFREE_STEALING: 'true'

.default-library-static:
  variables:
    EMPER_DEFAULT_LIBRARY: 'static'

.clang-sanitizer:
  extends:
    - .clang
    - .default-library-static
  variables:
    # Clang's sanitizers require undefined symbols to be allowed when
    # linking. See also:
    # - https://github.com/mesonbuild/meson/issues/764
    # - https://mesonbuild.com/Builtin-options.html
    EMPER_B_LUNDEF: 'false'


.clang-sanitizer-undefined:
  extends:
    - .clang-sanitizer
  variables:
    EMPER_B_SANITIZE: 'undefined'

#.clang-sanitizer-memory:
#  extends:
#    - .clang-sanitizer
#  variables:
#    EMPER_B_SANITIZE: 'memory'

#.sanitizer-address:
#  extends:
#    - .default-library-static
#  variables:
#    EMPER_B_SANITIZE: 'address'

.release-build:
  variables:
    BUILDTYPE: release

.debug-build:
  variables:
    BUILDTYPE: debug

.worker-wakeup-strategy-all:
  variables:
    EMPER_WORKER_WAKEUP_STRATEGY: "all"

.emper-worker-wakeup-strategy-throttle:
  variables:
    EMPER_WORKER_WAKEUP_STRATEGY: "throttle"

.do-not-log-timestamp:
  variables:
    EMPER_LOG_TIMESTAMP: "none"

.ws-queue-scheduler-locked:
  variables:
    EMPER_WS_QUEUE_SCHEDULER: "locked"

.ws-queue-scheduler-cl2:
  variables:
    EMPER_WS_QUEUE_SCHEDULER: "cl2"

.ws-queue-scheduler-cl3:
  variables:
    EMPER_WS_QUEUE_SCHEDULER: "cl3"

.ws-queue-scheduler-cl4:
  variables:
    EMPER_WS_QUEUE_SCHEDULER: "cl4"

.waitfree-ws:
  variables:
    EMPER_WAITFREE_WORK_STEALING: "true"

.futex-wakeup-semaphore:
  variables:
    EMPER_WAKEUP_SEMAPHORE_IMPLEMENTATION: "futex"

.futex2-wakeup-semaphore:
  variables:
    EMPER_WAKEUP_SEMAPHORE_IMPLEMENTATION: "futex2"

.locked-wakeup-semaphore:
  variables:
    EMPER_WAKEUP_SEMAPHORE_IMPLEMENTATION: "locked"

.set-affinity-on-block:
  variables:
    EMPER_SET_AFFINITY_ON_BLOCK: 'true'

test-gcc:
  extends:
    - .test
    - .gcc

test-gcc-release:
  extends:
    - test-gcc
    - .release-build

test-gcc-debug:
  extends:
    - test-gcc
    - .debug-build

test-clang:
  extends:
    - .test
    - .clang

test-clang-release:
  extends:
    - test-clang
    - .release-build

test-clang-debug:
  extends:
    - test-clang
    - .debug-build

smoke-test-libc++:
  stage: smoke-test
  extends:
    - .fast-variant-check
    - .libc++

test-libc++:
  extends:
    - .test
    - .libc++

test-worker-no-sleep:
  extends:
    - .test
    - .emper-worker-no-sleep

test-with-stats:
  extends:
    - .test
    - .emper-stats

test-with-userspace-rcu:
  extends:
    - .test
    - .emper-userspace-rcu

test-clang-sanitizer-undefined:
  extends:
    - .test
    - .clang-sanitizer-undefined

#test-clang-sanitizer-memory:
#  extends:
#    - .test
#    - .clang-sanitizer-memory

#test-clang-sanitizer-address:
#  extends:
#    - .test
#    - .clang
#    - .sanitizer-address

test-laws:
  extends:
    - .test
    - .emper-laws-scheduling

test-laws-release:
  extends:
    - test-laws
    - .release-build

test-worker-wakeup-strategy-all:
  extends:
    - .test
    - .worker-wakeup-strategy-all

# Disable throttle test till throttle works with notifySpecific
#test-worker-wakeup-strategy-throttle:
# extends:
#   - .test
#   - .emper-worker-wakeup-strategy-throttle

test-do-not-log-timestamp:
  extends:
    - .test
    - .do-not-log-timestamp

test-ws-queue-scheduler-locked:
  extends:
    - .test
    - .ws-queue-scheduler-locked

test-ws-queue-scheduler-cl2:
  extends:
    - .test
    - .ws-queue-scheduler-cl2

test-ws-queue-scheduler-cl3:
  extends:
    - .test
    - .ws-queue-scheduler-cl3

test-ws-queue-scheduler-cl3:
  extends:
    - .test
    - .ws-queue-scheduler-cl3

test-waitfree-ws:
  extends:
    - .test
    - .waitfree-ws

test-futex-wakeup-semaphore:
  extends:
    - .test
    - .futex-wakeup-semaphore

# TODO: enable this if the CI has linux >= 5.16
build-futex-wakeup-semaphore:
  extends:
    - .build
    - .futex2-wakeup-semaphore

test-locked-wakeup-semaphore:
  extends:
    - .test
    - .locked-wakeup-semaphore

test-set-affinity-on-block:
  extends:
    - .test
    - .set-affinity-on-block

test-mmapped-log:
  extends:
    - .meson-test
  script: make && EMPER_LOG_FILE=emper.log make test

test-no-io:
  extends:
    - .test
    - .emper-no-io

test-single-uring:
  extends:
    - .test
    - .emper-single-uring

test-synchronous-io:
  extends:
    - .test
    - .emper-synchronous-io

test-pipe-sleep-strategy:
  extends:
    - .test
    - .emper-pipe-sleep-strategy

test-pipe-sleep-strategy-no-completer:
  extends:
    - .test
    - .emper-pipe-sleep-strategy
    - .emper-no-completer

test-lockless-cq:
  extends:
    - .test
    - .emper-lockless-cq

test-io-stealing:
  extends:
    - .test
    - .emper-io-stealing

test-lockless-io-stealing:
  extends:
    - .test
    - .emper-io-stealing
    - .emper-lockless-cq

test-waitfree-io-stealing:
  extends:
    - .test
    - .emper-io-stealing
    - .emper-lockless-cq
    - .emper-io-waitfree-stealing

test-io-stealing-pipe-no-completer:
  extends:
    - .test
    - .emper-pipe-sleep-strategy
    - .emper-no-completer
    - .emper-io-stealing

test-io-stealing-pipe-no-completer-lockless:
  extends:
    - .test
    - .emper-pipe-sleep-strategy
    - .emper-no-completer
    - .emper-io-stealing
    - .emper-lockless-cq

smoke-test-locked-queue-rwlock:
  extends:
    - .fast-variant-check
  variables:
    EMPER_LOCKED_UNBOUNDED_QUEUE_IMPLEMENTATION: "rwlock"

smoke-test-locked-queue-shared-mutex:
  extends:
    - .fast-variant-check
  variables:
    EMPER_LOCKED_UNBOUNDED_QUEUE_IMPLEMENTATION: "shared_mutex"

smoke-test-locked-queue-boost-shared-mutex:
  extends:
    - .fast-variant-check
  variables:
    EMPER_LOCKED_UNBOUNDED_QUEUE_IMPLEMENTATION: "boost_shared_mutex"

smoke-test-locked-queue-boost-userspace-rcu:
  extends:
    - .fast-variant-check
  variables:
    EMPER_USERSPACE_RCU: "true"

# Only build the poller variants because sqpoll needs linux >= 5.15
# TODO: also test those variants if the CI uses linux >= 5.15
build-single-poller:
  extends:
    - .build
    - .emper-single-poller

build-numa-poller:
  extends:
    - .build
    - .emper-single-poller

build-each-poller:
  extends:
    - .build
    - .emper-each-poller

continuation-stealing-locked:
  extends:
    - .test
    - .ws-queue-scheduler-locked
  variables:
    EMPER_CONTINUATION_STEALING_MODE: 'locked'

continuation-stealing-madv-free:
  extends:
    - .test
  variables:
    EMPER_CONTINUATION_STEALING_MADVISE_STACK: 'free'

stack-guard-page:
  extends:
    - .test
  variables:
    EMPER_STACK_GUARD_PAGE: 'true'

build-only-emper-dep:
  extends:
    - .build
  variables:
    EMPER_BUILD_ONLY_EMPER_DEP: 'true'
