Browse Source

func tests improvements (#2759)

* faster reload test
* decode-jwt script
* replace 'netcat' requirement with python script
* fix lapi status test
mmetc 1 year ago
parent
commit
ce32fc019e

+ 1 - 1
.github/workflows/bats-hub.yml

@@ -42,7 +42,7 @@ jobs:
       env:
       env:
         GOBIN: /usr/local/bin
         GOBIN: /usr/local/bin
       run: |
       run: |
-        sudo apt -qq -y -o=Dpkg::Use-Pty=0 install build-essential daemonize jq netcat-openbsd libre2-dev
+        sudo apt -qq -y -o=Dpkg::Use-Pty=0 install build-essential daemonize jq libre2-dev
 
 
     - name: "Build crowdsec and fixture"
     - name: "Build crowdsec and fixture"
       run: make bats-clean bats-build bats-fixture BUILD_STATIC=1
       run: make bats-clean bats-build bats-fixture BUILD_STATIC=1

+ 1 - 1
.github/workflows/bats-mysql.yml

@@ -49,7 +49,7 @@ jobs:
       env:
       env:
         GOBIN: /usr/local/bin
         GOBIN: /usr/local/bin
       run: |
       run: |
-        sudo apt -qq -y -o=Dpkg::Use-Pty=0 install build-essential daemonize jq netcat-openbsd libre2-dev
+        sudo apt -qq -y -o=Dpkg::Use-Pty=0 install build-essential daemonize jq libre2-dev
 
 
     - name: "Build crowdsec and fixture"
     - name: "Build crowdsec and fixture"
       run: |
       run: |

+ 1 - 1
.github/workflows/bats-postgres.yml

@@ -58,7 +58,7 @@ jobs:
       env:
       env:
         GOBIN: /usr/local/bin
         GOBIN: /usr/local/bin
       run: |
       run: |
-        sudo apt -qq -y -o=Dpkg::Use-Pty=0 install build-essential daemonize jq netcat-openbsd libre2-dev
+        sudo apt -qq -y -o=Dpkg::Use-Pty=0 install build-essential daemonize jq libre2-dev
 
 
     - name: "Build crowdsec and fixture (DB_BACKEND: pgx)"
     - name: "Build crowdsec and fixture (DB_BACKEND: pgx)"
       run: |
       run: |

+ 1 - 1
.github/workflows/bats-sqlite-coverage.yml

@@ -39,7 +39,7 @@ jobs:
       env:
       env:
         GOBIN: /usr/local/bin
         GOBIN: /usr/local/bin
       run: |
       run: |
-        sudo apt -qq -y -o=Dpkg::Use-Pty=0 install build-essential daemonize jq netcat-openbsd libre2-dev
+        sudo apt -qq -y -o=Dpkg::Use-Pty=0 install build-essential daemonize jq libre2-dev
 
 
     - name: "Build crowdsec and fixture"
     - name: "Build crowdsec and fixture"
       run: |
       run: |

+ 0 - 1
test/README.md

@@ -63,7 +63,6 @@ architectures.
  - `jq`
  - `jq`
  - `nc`
  - `nc`
  - `openssl`
  - `openssl`
- - `openbsd-netcat`
  - `python3`
  - `python3`
 
 
 ## Running all tests
 ## Running all tests

+ 1 - 1
test/ansible/README.md

@@ -18,7 +18,7 @@ installation and run the tests, or run the playbooks separately to iterate while
 
 
 - run-all.yml: run the other playbooks in the correct order.
 - run-all.yml: run the other playbooks in the correct order.
 
 
-- provision-dependencies.yml: install the bats requirements (bash, netcat, cfssl, etc.), compilers, and database.
+- provision-dependencies.yml: install the bats requirements (bash, cfssl, etc.), compilers, and database.
 
 
 - provision-test-suite.yml: install the tests scripts and bats environment, and the crowdsec sources if we want to build the `crowdsec under test`.
 - provision-test-suite.yml: install the tests scripts and bats environment, and the crowdsec sources if we want to build the `crowdsec under test`.
 
 

+ 1 - 1
test/ansible/vagrant/experimental/alpine-3.16/bootstrap

@@ -3,5 +3,5 @@ unset IFS
 set -euf
 set -euf
 
 
 # coreutils -> for timeout (busybox is not enough)
 # coreutils -> for timeout (busybox is not enough)
-sudo apk add python3 go tar procps netcat-openbsd coreutils
+sudo apk add python3 go tar procps coreutils
 
 

+ 1 - 1
test/ansible/vagrant/experimental/gentoo/bootstrap

@@ -1,3 +1,3 @@
 #!/bin/sh
 #!/bin/sh
 
 
-sudo emerge --quiet app-portage/gentoolkit dev-vcs/git net-misc/curl app-misc/jq net-analyzer/openbsd-netcat
+sudo emerge --quiet app-portage/gentoolkit dev-vcs/git net-misc/curl app-misc/jq

+ 3 - 3
test/bats/01_crowdsec.bats

@@ -84,7 +84,7 @@ teardown() {
 
 
     config_disable_agent
     config_disable_agent
 
 
-    sleep 5
+    sleep 2
 
 
     rune -0 kill -HUP "$PID"
     rune -0 kill -HUP "$PID"
 
 
@@ -107,13 +107,13 @@ teardown() {
     assert_file_contains "$log_old" "Bucket routine exiting"
     assert_file_contains "$log_old" "Bucket routine exiting"
     assert_file_contains "$log_old" "serve: shutting down api server"
     assert_file_contains "$log_old" "serve: shutting down api server"
 
 
-    sleep 5
+    sleep 2
 
 
     assert_file_exists "$log_new"
     assert_file_exists "$log_new"
 
 
     for ((i=0; i<10; i++)); do
     for ((i=0; i<10; i++)); do
         sleep 1
         sleep 1
-        grep -q "Reload is finished" <"$log_old" && break
+        grep -q "Reload is finished" <"$log_new" && break
     done
     done
 
 
     echo "waited $i seconds"
     echo "waited $i seconds"

+ 0 - 1
test/bats/02_nolapi.bats

@@ -80,7 +80,6 @@ teardown() {
 
 
 @test "lapi status shouldn't be ok without api.server" {
 @test "lapi status shouldn't be ok without api.server" {
     config_disable_lapi
     config_disable_lapi
-    ./instance-crowdsec start || true
     rune -1 cscli machines list
     rune -1 cscli machines list
     assert_stderr --partial "local API is disabled -- this command must be run on the local API machine"
     assert_stderr --partial "local API is disabled -- this command must be run on the local API machine"
 }
 }

+ 0 - 7
test/bin/check-requirements

@@ -36,12 +36,6 @@ check_jq() {
     fi
     fi
 }
 }
 
 
-check_nc() {
-    if ! command -v nc >/dev/null; then
-        die "missing required program 'nc' (package 'netcat-openbsd')"
-    fi
-}
-
 check_base64() {
 check_base64() {
     if ! command -v base64 >/dev/null; then
     if ! command -v base64 >/dev/null; then
         die "missing required program 'base64'"
         die "missing required program 'base64'"
@@ -66,7 +60,6 @@ check_bats_core
 check_curl
 check_curl
 check_daemonizer
 check_daemonizer
 check_jq
 check_jq
-check_nc
 check_base64
 check_base64
 check_python3
 check_python3
 check_pkill
 check_pkill

+ 40 - 0
test/bin/decode-jwt

@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+
+import base64
+import json
+import sys
+
+
+def decode_base64url(data):
+    # Not the same as "bin/base64 -d":
+    # + -> -
+    # / -> _
+    # = -> ''
+    pad = len(data) % 4
+    if pad > 0:
+        data += '=' * (4 - pad)
+    return base64.urlsafe_b64decode(data)
+
+
+def decode_jwt(token):
+    token = token.rstrip('\n')
+    header, payload, signature = token.split('.')
+    decoded_header = json.loads(decode_base64url(header))
+    decoded_payload = json.loads(decode_base64url(payload))
+    # the signature is binary, so we don't decode it
+
+    return decoded_header, decoded_payload, signature
+
+
+def main():
+    header, payload, signature = decode_jwt(sys.stdin.read())
+    out = {
+        'header': header,
+        'payload': payload,
+        'signature': signature,
+    }
+    print(json.dumps(out, indent=4))
+
+
+if __name__ == '__main__':
+    main()

+ 52 - 30
test/bin/wait-for-port

@@ -1,42 +1,64 @@
-#!/usr/bin/env bash
+#!/usr/bin/env python3
 
 
-set -eu
+import argparse
+import os
+import socket
+import sys
+import time
 
 
-script_name=$0
+initial_interval = 0.02
+max_interval = 0.5
 
 
-die() {
-    echo >&2 "$@"
-    exit 1
-}
 
 
-about() {
-    die "usage: ${script_name} [-q] <port_number>"
-}
+def is_fd_open(fd):
+    try:
+        os.fstat(fd)
+        return True
+    except OSError:
+        return False
 
 
-[[ $# -lt 1 ]] && about
 
 
-QUIET=
-if [[ "$1" == "-q" ]]; then
-    QUIET=quiet
-    shift
-fi
+# write to file descriptor 3 if it is open (during bats tests), otherwise stderr
+def write_error(ex):
+    fd = 2
+    if is_fd_open(3):
+        fd = 3
+    os.write(fd, str(ex).encode())
 
 
-[[ $# -lt 1 ]] && about
 
 
-port_number=$1
+def wait(host, port, timeout):
+    t0 = time.perf_counter()
+    current_interval = initial_interval
+    while True:
+        try:
+            with socket.create_connection((host, port), timeout=timeout):
+                break
+        except OSError as ex:
+            if time.perf_counter() - t0 >= timeout:
+                raise TimeoutError(f'Timeout waiting for {host}:{port} after {timeout}s') from ex
+            time.sleep(current_interval)
+            current_interval = min(current_interval * 1.5, max_interval)
 
 
-# 4 seconds may seem long, but the tests must work on embedded, slow arm boxes too
-for _ in $(seq 40); do
-    nc -z localhost "${port_number}" >/dev/null 2>&1 && exit 0
-    sleep .1
-done
 
 
-# send to &3 if open
-if { true >&3; } 2>/dev/null; then
-    [[ -z "${QUIET}" ]] && echo "Can't connect to port ${port_number}" >&3
-else
-    [[ -z "${QUIET}" ]] && echo "Can't connect to port ${port_number}" >&2
-fi
+def main(argv):
+    parser = argparse.ArgumentParser(description="Check if a port is open.")
+    parser.add_argument("port", type=int, help="Port number to check")
+    parser.add_argument("--host", type=str, default="localhost", help="Host to check")
+    parser.add_argument("-t", "--timeout", type=float, default=10.0, help="Timeout duration in seconds")
+    parser.add_argument("-q", "--quiet", action="store_true", help="Enable quiet mode")
+    args = parser.parse_args(argv)
 
 
-exit 1
+    try:
+        wait(args.host, args.port, args.timeout)
+    except TimeoutError as ex:
+        if not args.quiet:
+            write_error(ex)
+        sys.exit(1)
+    else:
+        sys.exit(0)
 
 
+    sys.exit(1)
+
+
+if __name__ == "__main__":
+    main(sys.argv[1:])