diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e0d5d16..98c0006 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,6 +6,32 @@ Thank you for contributing! Just a few tips here: 2. Run the test suite (e.g. `pgbench`) to make sure everything still works. The tests are in `.circleci/run_tests.sh`. 3. Performance is important, make sure there are no regressions in your branch vs. `main`. +## How to run the integration tests locally and iterate on them +We have integration tests written in Ruby, Python, Go and Rust. +Below are the steps to run them in a developer-friendly way that allows iterating and quick turnaround. +Hear me out, this should be easy, it will involve opening a shell into a container with all the necessary dependancies available for you and you can modify the test code and immediately rerun your test in the interactive shell. + + +Quite simply, make sure you have docker installed and then run +`./start_test_env.sh` + +That is it! + +Within this test environment you can modify the file in your favorite IDE and rerun the tests without having to bootstrap the entire environment again. + +Once the environment is ready, you can run the tests by running +Ruby: `cd /app/tests/ruby && bundle exec ruby .rb --format documentation` +Python: `cd /app && python3 tests/python/tests.py` +Rust: `cd /app/tests/rust && cargo run` +Go: `cd /app/tests/go && /usr/local/go/bin/go test` + +You can also rebuild PgCat directly within the environment and the tests will run against the newly built binary +To rebuild PgCat, just run `cargo build` within the container under `/app` + +![Animated gif showing how to run tests](https://github.com/user-attachments/assets/2258fde3-2aed-4efb-bdc5-e4f12dcd4d33) + + + Happy hacking! ## TODOs diff --git a/start_test_env.sh b/start_test_env.sh new file mode 100755 index 0000000..24a6b3f --- /dev/null +++ b/start_test_env.sh @@ -0,0 +1,34 @@ +GREEN="\033[0;32m" +RED="\033[0;31m" +BLUE="\033[0;34m" +RESET="\033[0m" + + +cd tests/docker/ +docker compose kill main || true +docker compose build main +docker compose down +docker compose up -d +# wait for the container to start +while ! docker compose exec main ls; do + echo "Waiting for test environment to start" + sleep 1 +done +echo "===================================" +docker compose exec -e LOG_LEVEL=error -d main toxiproxy-server +docker compose exec --workdir /app main cargo build +docker compose exec -d --workdir /app main ./target/debug/pgcat ./.circleci/pgcat.toml +docker compose exec --workdir /app/tests/ruby main bundle install +docker compose exec --workdir /app/tests/python main pip3 install -r requirements.txt +echo "Interactive test environment ready" +echo "To run integration tests, you can use the following commands:" +echo -e " ${BLUE}Ruby: ${RED}cd /app/tests/ruby && bundle exec ruby tests.rb --format documentation${RESET}" +echo -e " ${BLUE}Python: ${RED}cd /app && python3 tests/python/tests.py${RESET}" +echo -e " ${BLUE}Rust: ${RED}cd /app/tests/rust && cargo run ${RESET}" +echo -e " ${BLUE}Go: ${RED}cd /app/tests/go && /usr/local/go/bin/go test${RESET}" +echo "the source code for tests are directly linked to the source code in the container so you can modify the code and run the tests again" +echo "You can rebuild PgCat from within the container by running" +echo -e " ${GREEN}cargo build${RESET}" +echo "and then run the tests again" +echo "===================================" +docker compose exec --workdir /app/tests main bash diff --git a/tests/docker/docker-compose.yml b/tests/docker/docker-compose.yml index 93e9455..0e174d8 100644 --- a/tests/docker/docker-compose.yml +++ b/tests/docker/docker-compose.yml @@ -1,4 +1,3 @@ -version: "3" services: pg1: image: postgres:14 @@ -48,6 +47,8 @@ services: main: build: . command: ["bash", "/app/tests/docker/run.sh"] + environment: + - INTERACTIVE_TEST_ENVIRONMENT=true volumes: - ../../:/app/ - /app/target/ diff --git a/tests/docker/run.sh b/tests/docker/run.sh index ae30c97..07452cb 100644 --- a/tests/docker/run.sh +++ b/tests/docker/run.sh @@ -5,6 +5,38 @@ rm /app/*.profraw || true rm /app/pgcat.profdata || true rm -rf /app/cov || true +# Prepares the interactive test environment +# +if [ -n "$INTERACTIVE_TEST_ENVIRONMENT" ]; then + ports=(5432 7432 8432 9432 10432) + for port in "${ports[@]}"; do + is_it_up=0 + attempts=0 + while [ $is_it_up -eq 0 ]; do + PGPASSWORD=postgres psql -h 127.0.0.1 -p $port -U postgres -c '\q' > /dev/null 2>&1 + if [ $? -eq 0 ]; then + echo "PostgreSQL on port $port is up." + is_it_up=1 + else + attempts=$((attempts+1)) + if [ $attempts -gt 10 ]; then + echo "PostgreSQL on port $port is down, giving up." + exit 1 + fi + echo "PostgreSQL on port $port is down, waiting for it to start." + sleep 1 + fi + done + done + PGPASSWORD=postgres psql -e -h 127.0.0.1 -p 5432 -U postgres -f /app/tests/sharding/query_routing_setup.sql + PGPASSWORD=postgres psql -e -h 127.0.0.1 -p 7432 -U postgres -f /app/tests/sharding/query_routing_setup.sql + PGPASSWORD=postgres psql -e -h 127.0.0.1 -p 8432 -U postgres -f /app/tests/sharding/query_routing_setup.sql + PGPASSWORD=postgres psql -e -h 127.0.0.1 -p 9432 -U postgres -f /app/tests/sharding/query_routing_setup.sql + PGPASSWORD=postgres psql -e -h 127.0.0.1 -p 10432 -U postgres -f /app/tests/sharding/query_routing_setup.sql + sleep 100000000000000000 + exit 0 +fi + export LLVM_PROFILE_FILE="/app/pgcat-%m-%p.profraw" export RUSTC_BOOTSTRAP=1 export CARGO_INCREMENTAL=0