diff --git a/README.md b/README.md index 3e58d8d..8aa6a84 100644 --- a/README.md +++ b/README.md @@ -34,17 +34,32 @@ valkey-server --loadmodule ./target/release/libvalkey_bloom.so #### Local development script to build, run format checks, run unit / integration tests, and for cargo release: ``` -# Builds the valkey-server (unstable) for integration testing. +# Builds only the valkey-bloom module SERVER_VERSION=unstable ./build.sh -# Same as above, but uses valkey-server (8.0.0) for integration testing. + +# Same as above, but uses valkey-server (8.0.0). SERVER_VERSION=8.0.0 ./build.sh -# Build with asan, you may need to remove the old valkey binary if you have used ./build.sh before. You can do this by deleting the `.build` folder in the `tests` folder + +# To view the available arguments, use: +./build.sh --help + +# Clean build artifacts +./build.sh --clean + +# Build and run the unit tests +./build.sh --unit + +# Run all integration tests +./build.sh --integration + +# Run a unique set of integration tests +TEST_PATTERN= ./build.sh --integration + +# Build with asan, you may need to remove the old valkey binary if you have used ./build.sh before. You can do this by deleting the `.build` folder in the `tests` folder. This option can be used with any of the build script options. ASAN_BUILD=true ./build.sh -# Clean build artifacts -./build.sh clean ``` ## Load the Module diff --git a/build.sh b/build.sh index 8770e87..80459af 100755 --- a/build.sh +++ b/build.sh @@ -5,10 +5,81 @@ # Exit the script if any command fails set -e +function print_usage() { +cat< /dev/null 2>&1; then - echo "Using pip to install packages..." - pip install -r "$SCRIPT_DIR/$REQUIREMENTS_FILE" -# Check if pip3 is available -elif command -v pip3 > /dev/null 2>&1; then - echo "Using pip3 to install packages..." - pip3 install -r "$SCRIPT_DIR/$REQUIREMENTS_FILE" -else - echo "Error: Neither pip nor pip3 is available. Please install Python package installer." - exit 1 -fi +if [ $RUN_INTEGRATION -eq 1 ]; then + REPO_URL="https://github.com/valkey-io/valkey.git" + BINARY_PATH="tests/build/binaries/$SERVER_VERSION/valkey-server" + CACHED_VALKEY_PATH="tests/build/valkey" + if [ -f "$BINARY_PATH" ] && [ -x "$BINARY_PATH" ]; then + echo "valkey-server binary '$BINARY_PATH' found." + else + echo "valkey-server binary '$BINARY_PATH' not found." + mkdir -p "tests/build/binaries/$SERVER_VERSION" + rm -rf $CACHED_VALKEY_PATH + cd tests/build + git clone "$REPO_URL" + cd valkey + git checkout "$SERVER_VERSION" + make distclean + if [ ! -z "${ASAN_BUILD}" ]; then + make -j SANITIZER=address + else + make -j + fi + cp src/valkey-server ../binaries/$SERVER_VERSION/ + cd $SCRIPT_DIR + rm -rf $CACHED_VALKEY_PATH + fi + TEST_FRAMEWORK_REPO="https://github.com/valkey-io/valkey-test-framework" + TEST_FRAMEWORK_DIR="tests/build/valkeytestframework" -os_type=$(uname) -MODULE_EXT=".so" -if [[ "$os_type" == "Darwin" ]]; then - MODULE_EXT=".dylib" -elif [[ "$os_type" == "Linux" ]]; then - MODULE_EXT=".so" -else - echo "Unsupported OS type: $os_type" - exit 1 -fi -export MODULE_PATH="$SCRIPT_DIR/target/release/libvalkey_bloom$MODULE_EXT" -echo "Running the integration tests..." -if [ ! -z "${ASAN_BUILD}" ]; then - # TEST_PATTERN can be used to run specific tests or test patterns. - if [[ -n "$TEST_PATTERN" ]]; then - python3 -m pytest --capture=sys --cache-clear -v "$SCRIPT_DIR/tests/" -k $TEST_PATTERN 2>&1 | tee test_output.tmp + if [ -d "$TEST_FRAMEWORK_DIR" ]; then + echo "valkeytestframework found." else - echo "TEST_PATTERN is not set. Running all integration tests." - python3 -m pytest --capture=sys --cache-clear -v "$SCRIPT_DIR/tests/" 2>&1 | tee test_output.tmp + echo "Cloning valkey-test-framework..." + git clone "$TEST_FRAMEWORK_REPO" + mkdir -p "$TEST_FRAMEWORK_DIR" + mv "valkey-test-framework/src"/* "$TEST_FRAMEWORK_DIR/" + rm -rf valkey-test-framework fi - # Check for memory leaks in the output - if grep -q "LeakSanitizer: detected memory leaks" test_output.tmp; then - RED='\033[0;31m' - echo -e "${RED}Memory leaks detected in the following tests:" - LEAKING_TESTS=$(grep -B 2 "LeakSanitizer: detected memory leaks" test_output.tmp | \ - grep -v "LeakSanitizer" | \ - grep ".*\.py::") - - LEAK_COUNT=$(echo "$LEAKING_TESTS" | wc -l) - - # Output each leaking test - echo "$LEAKING_TESTS" | while read -r line; do - echo "::error::Test with leak: $line" - done - - echo -e "\n$LEAK_COUNT python integration tests have leaks detected in them" - rm test_output.tmp + REQUIREMENTS_FILE="requirements.txt" + + # Check if pip is available + if command -v pip > /dev/null 2>&1; then + echo "Using pip to install packages..." + pip install -r "$SCRIPT_DIR/$REQUIREMENTS_FILE" + # Check if pip3 is available + elif command -v pip3 > /dev/null 2>&1; then + echo "Using pip3 to install packages..." + pip3 install -r "$SCRIPT_DIR/$REQUIREMENTS_FILE" + else + echo "Error: Neither pip nor pip3 is available. Please install Python package installer." exit 1 fi - rm test_output.tmp -else - # TEST_PATTERN can be used to run specific tests or test patterns. - if [[ -n "$TEST_PATTERN" ]]; then - python3 -m pytest --cache-clear -v "$SCRIPT_DIR/tests/" -k $TEST_PATTERN + + os_type=$(uname) + MODULE_EXT=".so" + if [[ "$os_type" == "Darwin" ]]; then + MODULE_EXT=".dylib" + elif [[ "$os_type" == "Linux" ]]; then + MODULE_EXT=".so" else - echo "TEST_PATTERN is not set. Running all integration tests." - python3 -m pytest --cache-clear -v "$SCRIPT_DIR/tests/" + echo "Unsupported OS type: $os_type" + exit 1 + fi + export MODULE_PATH="$SCRIPT_DIR/target/release/libvalkey_bloom$MODULE_EXT" + + echo "Running the integration tests..." + if [ ! -z "${ASAN_BUILD}" ]; then + # TEST_PATTERN can be used to run specific tests or test patterns. + if [[ -n "$TEST_PATTERN" ]]; then + python3 -m pytest --capture=sys --cache-clear -v "$SCRIPT_DIR/tests/" -k $TEST_PATTERN -m "not skip_for_asan" 2>&1 | tee test_output.tmp + else + echo "TEST_PATTERN is not set. Running all integration tests." + python3 -m pytest --capture=sys --cache-clear -v "$SCRIPT_DIR/tests/" -m "not skip_for_asan" 2>&1 | tee test_output.tmp + fi + + # Check for memory leaks in the output + if grep -q "LeakSanitizer: detected memory leaks" test_output.tmp; then + RED='\033[0;31m' + echo -e "${RED}Memory leaks detected in the following tests:" + LEAKING_TESTS=$(grep -B 2 "LeakSanitizer: detected memory leaks" test_output.tmp | \ + grep -v "LeakSanitizer" | \ + grep ".*\.py::") + + LEAK_COUNT=$(echo "$LEAKING_TESTS" | wc -l) + + # Output each leaking test + echo "$LEAKING_TESTS" | while read -r line; do + echo "::error::Test with leak: $line" + done + + echo -e "\n$LEAK_COUNT python integration tests have leaks detected in them" + rm test_output.tmp + exit 1 + fi + rm test_output.tmp + else + # TEST_PATTERN can be used to run specific tests or test patterns. + if [[ -n "$TEST_PATTERN" ]]; then + python3 -m pytest --cache-clear -v "$SCRIPT_DIR/tests/" -k $TEST_PATTERN + else + echo "TEST_PATTERN is not set. Running all integration tests." + python3 -m pytest --cache-clear -v "$SCRIPT_DIR/tests/" + fi fi fi -echo "Build, Format Checks, Unit tests, and Integration Tests succeeded" + +# echo "Build, Format Checks, Unit tests, and Integration Tests succeeded"