From 338ed770917e7159a2908c94c0016a46bc63496a Mon Sep 17 00:00:00 2001
From: PGijsbers
Date: Wed, 7 Oct 2026 15:02:14 +0200
Subject: [PATCH 01/12] Add automatic test for dataset upload and processing
---
scripts/data/test.arff | 14 ++++++++++++
scripts/evaluation_engine_dataset.sh | 10 ++++++++
scripts/upload_dataset.sh | 34 ++++++++++++++++++++++++++++
scripts/wait_for_dataset.sh | 27 ++++++++++++++++++++++
4 files changed, 85 insertions(+)
create mode 100644 scripts/data/test.arff
create mode 100644 scripts/evaluation_engine_dataset.sh
create mode 100755 scripts/upload_dataset.sh
create mode 100755 scripts/wait_for_dataset.sh
diff --git a/scripts/data/test.arff b/scripts/data/test.arff
new file mode 100644
index 0000000..51ab11c
--- /dev/null
+++ b/scripts/data/test.arff
@@ -0,0 +1,14 @@
+@RELATION test-dataset
+@ATTRIBUTE foo NUMERIC
+@ATTRIBUTE bar NUMERIC
+@ATTRIBUTE bazz NUMERIC
+@ATTRIBUTE class {'a', 'b'}
+@DATA
+0,0,0,'a'
+0,0,1,'a'
+0,1,0,'a'
+0,1,1,'a'
+1,0,0,'b'
+1,0,1,'b'
+1,1,0,'b'
+1,1,1,'b'
diff --git a/scripts/evaluation_engine_dataset.sh b/scripts/evaluation_engine_dataset.sh
new file mode 100644
index 0000000..dd4f2ee
--- /dev/null
+++ b/scripts/evaluation_engine_dataset.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+# Tests the dataset upload and processing of the REST API and Evaluation Engine
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+DATASET_ID=$("${SCRIPT_DIR}/upload_dataset.sh")
+echo "Uploaded dataset with ID: $DATASET_ID"
+
+"${SCRIPT_DIR}/wait_for_dataset.sh" "$DATASET_ID"
diff --git a/scripts/upload_dataset.sh b/scripts/upload_dataset.sh
new file mode 100755
index 0000000..97c767c
--- /dev/null
+++ b/scripts/upload_dataset.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# Uploads a dataset to the REST API and prints the dataset ID to stdout.
+set -euo pipefail
+
+XML_DESCRIPTION='
+ test_dataset
+ test
+ arff
+ I
+ now
+ en
+ BSD (from scikit-learn)
+ class
+ test
+ citation
+ https://www4.stat.ncsu.edu/~boos/var.select/diabetes.html
+ url
+'
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+RESPONSE=$(curl -s -X POST "http://localhost:8000/api/v1/xml/data?api_key=normaluser" \
+ -F "description=<-;type=text/xml" <<< "${XML_DESCRIPTION}" \
+ -F "dataset=@${SCRIPT_DIR}/data/test.arff")
+
+DATASET_ID=$(echo "$RESPONSE" | sed -n 's/.*\([0-9]*\)<\/oml:id>.*/\1/p')
+
+if [ -z "$DATASET_ID" ]; then
+ echo "ERROR: Failed to parse dataset ID from response:" >&2
+ echo "$RESPONSE" >&2
+ exit 1
+fi
+
+echo "$DATASET_ID"
diff --git a/scripts/wait_for_dataset.sh b/scripts/wait_for_dataset.sh
new file mode 100755
index 0000000..6bdd0a9
--- /dev/null
+++ b/scripts/wait_for_dataset.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# Waits for a dataset to become active.
+# Usage: wait_for_dataset.sh DATASET_ID [TIMEOUT]
+set -euo pipefail
+
+DATASET_ID="${1:?Usage: wait_for_dataset.sh DATASET_ID [TIMEOUT]}"
+TIMEOUT="${2:-120}"
+INTERVAL=5
+ELAPSED=0
+
+while [ "$ELAPSED" -lt "$TIMEOUT" ]; do
+ STATUS_RESPONSE=$(curl -s "http://localhost:8000/api/v1/xml/data/${DATASET_ID}")
+ STATUS=$(echo "$STATUS_RESPONSE" | sed -n 's/.*\([a-zA-Z_]*\)<\/oml:status>.*/\1/p')
+
+ echo "Status after ${ELAPSED}s: ${STATUS:-unknown}"
+
+ if [ "$STATUS" = "active" ]; then
+ echo "Dataset $DATASET_ID is active."
+ exit 0
+ fi
+
+ sleep "$INTERVAL"
+ ELAPSED=$((ELAPSED + INTERVAL))
+done
+
+echo "ERROR: Dataset $DATASET_ID did not become active within ${TIMEOUT} seconds."
+exit 1
From 40a65026d6614315719a7b05a7e30c000045caea Mon Sep 17 00:00:00 2001
From: PGijsbers
Date: Wed, 7 Oct 2026 15:20:02 +0200
Subject: [PATCH 02/12] Add scripts to test creating tasks and task splits
---
scripts/create_task.sh | 33 +++++++++++++++++++++++++++++++++
scripts/upload_dataset.sh | 6 +++++-
scripts/wait_for_task.sh | 31 +++++++++++++++++++++++++++++++
3 files changed, 69 insertions(+), 1 deletion(-)
create mode 100755 scripts/create_task.sh
create mode 100755 scripts/wait_for_task.sh
diff --git a/scripts/create_task.sh b/scripts/create_task.sh
new file mode 100755
index 0000000..d09bc99
--- /dev/null
+++ b/scripts/create_task.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# Creates a task for a given dataset and estimation procedure, prints the task ID to stdout.
+# Usage: create_task.sh DATASET_ID ESTIMATION_PROCEDURE_ID [TARGET_FEATURE]
+set -euo pipefail
+
+DATASET_ID="${1:?Usage: create_task.sh DATASET_ID ESTIMATION_PROCEDURE_ID [TARGET_FEATURE]}"
+ESTIMATION_PROCEDURE_ID="${2:?Usage: create_task.sh DATASET_ID ESTIMATION_PROCEDURE_ID [TARGET_FEATURE]}"
+TARGET_FEATURE="${3:-class}"
+
+TMPFILE=$(mktemp /tmp/task_desc.XXXXXX.xml)
+trap 'rm -f "$TMPFILE"' EXIT
+
+cat > "$TMPFILE" << EOF
+
+ 1
+ ${DATASET_ID}
+ ${ESTIMATION_PROCEDURE_ID}
+ ${TARGET_FEATURE}
+
+EOF
+
+RESPONSE=$(curl -s -X POST "http://localhost:8000/api/v1/xml/task?api_key=normaluser" \
+ -F "description=@${TMPFILE};type=text/xml")
+
+TASK_ID=$(echo "$RESPONSE" | sed -n 's/.*\([0-9]*\)<\/oml:id>.*/\1/p')
+
+if [ -z "$TASK_ID" ]; then
+ echo "Server response:" >&2
+ echo "$RESPONSE" >&2
+ exit 1
+fi
+
+echo "$TASK_ID"
diff --git a/scripts/upload_dataset.sh b/scripts/upload_dataset.sh
index 97c767c..e031ad6 100755
--- a/scripts/upload_dataset.sh
+++ b/scripts/upload_dataset.sh
@@ -19,8 +19,12 @@ XML_DESCRIPTION='
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+TMPFILE=$(mktemp /tmp/dataset_desc.XXXXXX.xml)
+trap 'rm -f "$TMPFILE"' EXIT
+echo "$XML_DESCRIPTION" > "$TMPFILE"
+
RESPONSE=$(curl -s -X POST "http://localhost:8000/api/v1/xml/data?api_key=normaluser" \
- -F "description=<-;type=text/xml" <<< "${XML_DESCRIPTION}" \
+ -F "description=@${TMPFILE};type=text/xml" \
-F "dataset=@${SCRIPT_DIR}/data/test.arff")
DATASET_ID=$(echo "$RESPONSE" | sed -n 's/.*\([0-9]*\)<\/oml:id>.*/\1/p')
diff --git a/scripts/wait_for_task.sh b/scripts/wait_for_task.sh
new file mode 100755
index 0000000..4f9d3e6
--- /dev/null
+++ b/scripts/wait_for_task.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# Waits until a task has associated split files.
+# Usage: wait_for_task.sh TASK_ID [TIMEOUT]
+set -euo pipefail
+
+TASK_ID="${1:?Usage: wait_for_task.sh TASK_ID [TIMEOUT]}"
+TIMEOUT="${2:-120}"
+INTERVAL=5
+ELAPSED=0
+
+while [ "$ELAPSED" -lt "$TIMEOUT" ]; do
+ RESPONSE=$(curl -s "http://localhost:8000/api/v1/xml/task/${TASK_ID}")
+ SPLITS_URL=$(echo "$RESPONSE" | sed -n 's/.*\(.*\)<\/oml:data_splits_url>.*/\1/p')
+
+ if [ -n "$SPLITS_URL" ]; then
+ STATUS_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$SPLITS_URL")
+ if [ "$STATUS_CODE" = "200" ]; then
+ echo "Task $TASK_ID has split files available."
+ exit 0
+ fi
+ echo "Splits URL exists but returned HTTP $STATUS_CODE after ${ELAPSED}s"
+ else
+ echo "No splits URL yet after ${ELAPSED}s"
+ fi
+
+ sleep "$INTERVAL"
+ ELAPSED=$((ELAPSED + INTERVAL))
+done
+
+echo "ERROR: Task $TASK_ID did not get split files within ${TIMEOUT} seconds."
+exit 1
From deb46c0b48acc7f114c55a698e23b43785290b9b Mon Sep 17 00:00:00 2001
From: PGijsbers
Date: Thu, 8 Oct 2026 11:49:29 +0200
Subject: [PATCH 03/12] Add CI tests for dataset and task processing
---
.github/actions/start-services/action.yaml | 34 ++++++++++++++
.github/workflows/integration-test.yaml | 53 ++++++++++++++++++++++
2 files changed, 87 insertions(+)
create mode 100644 .github/actions/start-services/action.yaml
create mode 100644 .github/workflows/integration-test.yaml
diff --git a/.github/actions/start-services/action.yaml b/.github/actions/start-services/action.yaml
new file mode 100644
index 0000000..26572b0
--- /dev/null
+++ b/.github/actions/start-services/action.yaml
@@ -0,0 +1,34 @@
+name: Start Services
+description: Checkout the repo and start Docker Compose services
+
+inputs:
+ profiles:
+ description: "Comma-separated list of profiles to start (e.g. 'all' or 'rest-api,minio')"
+ required: false
+ default: "all"
+ services:
+ description: "Comma-separated list of specific services to start (e.g. 'database,elasticsearch')"
+ required: false
+ default: ""
+
+runs:
+ using: composite
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Start services
+ shell: bash
+ run: |
+ PROFILE_FLAGS=""
+ for profile in $(echo "${{ inputs.profiles }}" | tr ',' ' '); do
+ PROFILE_FLAGS="$PROFILE_FLAGS --profile $profile"
+ done
+ SERVICES=$(echo "${{ inputs.services }}" | tr ',' ' ')
+ docker compose $PROFILE_FLAGS up -d --build --wait $SERVICES
+ timeout-minutes: 10
+
+ - name: Show service status
+ if: always()
+ shell: bash
+ run: docker compose ps
diff --git a/.github/workflows/integration-test.yaml b/.github/workflows/integration-test.yaml
new file mode 100644
index 0000000..2dc8364
--- /dev/null
+++ b/.github/workflows/integration-test.yaml
@@ -0,0 +1,53 @@
+name: Integration Test
+
+on:
+ pull_request:
+ paths:
+ - "docker-compose.yaml"
+ - "scripts/**"
+ - "config/**"
+
+jobs:
+ dataset-processing:
+ runs-on: ubuntu-latest
+ timeout-minutes: 15
+
+ steps:
+ - name: Start services
+ uses: ./.github/actions/start-services
+ with:
+ profiles: "rest-api,evaluation-engine"
+
+ - name: Create dataset
+ id: dataset
+ run: |
+ DATASET_ID=$(bash scripts/upload_dataset.sh)
+ echo "Dataset ID: $DATASET_ID"
+ echo "id=$DATASET_ID" >> "$GITHUB_OUTPUT"
+
+ - name: Dataset Processing
+ run: bash scripts/wait_for_dataset.sh "${{ steps.dataset.outputs.id }}" 180
+
+ task-processing:
+ runs-on: ubuntu-latest
+ timeout-minutes: 15
+
+ steps:
+ - name: Start services
+ uses: ./.github/actions/start-services
+ with:
+ profiles: "rest-api,evaluation-engine"
+
+ - name: Create task
+ id: task
+ run: |
+ TASK_ID=$(bash scripts/create_task.sh 129 1)
+ echo "Task ID: $TASK_ID"
+ echo "id=$TASK_ID" >> "$GITHUB_OUTPUT"
+
+ - name: Task Processing
+ run: bash scripts/wait_for_task.sh "${{ steps.task.outputs.id }}" 180
+
+ - name: Show logs on failure
+ if: failure()
+ run: docker compose logs --tail=50
From 0f78f0a6ce030bd19dacbccf0908e43064593d30 Mon Sep 17 00:00:00 2001
From: PGijsbers
Date: Thu, 8 Oct 2026 11:56:45 +0200
Subject: [PATCH 04/12] Move checkout outside of action, otherwise it can't be
found
---
.github/actions/start-services/action.yaml | 5 +----
.github/workflows/integration-test.yaml | 10 ++++++++++
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/.github/actions/start-services/action.yaml b/.github/actions/start-services/action.yaml
index 26572b0..d71a93a 100644
--- a/.github/actions/start-services/action.yaml
+++ b/.github/actions/start-services/action.yaml
@@ -1,5 +1,5 @@
name: Start Services
-description: Checkout the repo and start Docker Compose services
+description: Start Docker Compose services
inputs:
profiles:
@@ -14,9 +14,6 @@ inputs:
runs:
using: composite
steps:
- - name: Checkout
- uses: actions/checkout@v4
-
- name: Start services
shell: bash
run: |
diff --git a/.github/workflows/integration-test.yaml b/.github/workflows/integration-test.yaml
index 2dc8364..839182b 100644
--- a/.github/workflows/integration-test.yaml
+++ b/.github/workflows/integration-test.yaml
@@ -13,6 +13,9 @@ jobs:
timeout-minutes: 15
steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
- name: Start services
uses: ./.github/actions/start-services
with:
@@ -28,11 +31,18 @@ jobs:
- name: Dataset Processing
run: bash scripts/wait_for_dataset.sh "${{ steps.dataset.outputs.id }}" 180
+ - name: Show logs on failure
+ if: failure()
+ run: docker compose logs --tail=50
+
task-processing:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
- name: Start services
uses: ./.github/actions/start-services
with:
From 281fdb464d2f53acd6ad0c0025461829a61d2584 Mon Sep 17 00:00:00 2001
From: PGijsbers
Date: Thu, 8 Oct 2026 11:58:53 +0200
Subject: [PATCH 05/12] Remove timeout directive as it's not allowed in comp
actions
---
.github/actions/start-services/action.yaml | 1 -
1 file changed, 1 deletion(-)
diff --git a/.github/actions/start-services/action.yaml b/.github/actions/start-services/action.yaml
index d71a93a..94665f2 100644
--- a/.github/actions/start-services/action.yaml
+++ b/.github/actions/start-services/action.yaml
@@ -23,7 +23,6 @@ runs:
done
SERVICES=$(echo "${{ inputs.services }}" | tr ',' ' ')
docker compose $PROFILE_FLAGS up -d --build --wait $SERVICES
- timeout-minutes: 10
- name: Show service status
if: always()
From cdb2292a266c57328684967bb1f1c03aace404ef Mon Sep 17 00:00:00 2001
From: PGijsbers
Date: Thu, 8 Oct 2026 12:10:21 +0200
Subject: [PATCH 06/12] Set permissions to allow containers to use the mounted
volumes
---
.github/actions/start-services/action.yaml | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/.github/actions/start-services/action.yaml b/.github/actions/start-services/action.yaml
index 94665f2..1e8aad5 100644
--- a/.github/actions/start-services/action.yaml
+++ b/.github/actions/start-services/action.yaml
@@ -14,6 +14,11 @@ inputs:
runs:
using: composite
steps:
+ - name: Set permission for mount paths
+ shell: bash
+ run: |
+ chmod -R 777 ./data/php
+ chmod -R 777 ./logs
- name: Start services
shell: bash
run: |
From 3eb2a216a7467c8a7e80de82ddb7da3900b59421 Mon Sep 17 00:00:00 2001
From: PGijsbers
Date: Thu, 8 Oct 2026 12:33:45 +0200
Subject: [PATCH 07/12] Print body on error
---
scripts/wait_for_task.sh | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/scripts/wait_for_task.sh b/scripts/wait_for_task.sh
index 4f9d3e6..6fdc98b 100755
--- a/scripts/wait_for_task.sh
+++ b/scripts/wait_for_task.sh
@@ -13,12 +13,15 @@ while [ "$ELAPSED" -lt "$TIMEOUT" ]; do
SPLITS_URL=$(echo "$RESPONSE" | sed -n 's/.*\(.*\)<\/oml:data_splits_url>.*/\1/p')
if [ -n "$SPLITS_URL" ]; then
- STATUS_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$SPLITS_URL")
+ SPLITS_RESPONSE=$(curl -s -w "\n%{http_code}" "$SPLITS_URL")
+ STATUS_CODE=$(echo "$SPLITS_RESPONSE" | tail -n1)
+ SPLITS_BODY=$(echo "$SPLITS_RESPONSE" | sed '$d')
if [ "$STATUS_CODE" = "200" ]; then
echo "Task $TASK_ID has split files available."
exit 0
fi
echo "Splits URL exists but returned HTTP $STATUS_CODE after ${ELAPSED}s"
+ echo "$SPLITS_BODY"
else
echo "No splits URL yet after ${ELAPSED}s"
fi
From 489cc1c2619ac75d97bf2a141783e2519c01a215 Mon Sep 17 00:00:00 2001
From: PGijsbers
Date: Thu, 8 Oct 2026 13:44:47 +0200
Subject: [PATCH 08/12] Start working on run evaluation check
---
.github/workflows/integration-test.yaml | 27 +++
scripts/data/run/description.xml | 305 ++++++++++++++++++++++++
scripts/data/run/predictions.arff | 170 +++++++++++++
scripts/upload_run.sh | 20 ++
scripts/wait_for_run.sh | 26 ++
5 files changed, 548 insertions(+)
create mode 100644 scripts/data/run/description.xml
create mode 100644 scripts/data/run/predictions.arff
create mode 100755 scripts/upload_run.sh
create mode 100755 scripts/wait_for_run.sh
diff --git a/.github/workflows/integration-test.yaml b/.github/workflows/integration-test.yaml
index 839182b..a01771b 100644
--- a/.github/workflows/integration-test.yaml
+++ b/.github/workflows/integration-test.yaml
@@ -61,3 +61,30 @@ jobs:
- name: Show logs on failure
if: failure()
run: docker compose logs --tail=50
+
+ run-processing:
+ runs-on: ubuntu-latest
+ timeout-minutes: 15
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Start services
+ uses: ./.github/actions/start-services
+ with:
+ profiles: "rest-api,evaluation-engine"
+
+ - name: Upload run
+ id: run
+ run: |
+ RUN_ID=$(bash scripts/upload_run.sh)
+ echo "Run ID: $RUN_ID"
+ echo "id=$RUN_ID" >> "$GITHUB_OUTPUT"
+
+ - name: Run Processing
+ run: bash scripts/wait_for_run.sh "${{ steps.run.outputs.id }}" 180
+
+ - name: Show logs on failure
+ if: failure()
+ run: docker compose logs --tail=50
diff --git a/scripts/data/run/description.xml b/scripts/data/run/description.xml
new file mode 100644
index 0000000..032178e
--- /dev/null
+++ b/scripts/data/run/description.xml
@@ -0,0 +1,305 @@
+
+ 1196
+ 1
+ Python_3.10.16. Sklearn_1.6.1. NumPy_2.2.2. SciPy_1.15.1.
+
+ -do-not-check-capabilities
+
+
+
+ batch-size
+ 100
+
+
+ num-decimal-places
+ 2
+
+
+ output-debug-info
+
+
+ openml-python
+ Sklearn_1.6.1.
+
+
+ usercpu_time_millis_training
+ 11.353665999999762
+
+
+ usercpu_time_millis_training
+ 1.2970839999999484
+
+
+ usercpu_time_millis_training
+ 1.1723329999995258
+
+
+ usercpu_time_millis_training
+ 1.1706670000002362
+
+
+ usercpu_time_millis_training
+ 1.2168329999999727
+
+
+ usercpu_time_millis_training
+ 1.226291000000046
+
+
+ usercpu_time_millis_training
+ 1.2974170000008556
+
+
+ usercpu_time_millis_training
+ 1.2798339999999797
+
+
+ usercpu_time_millis_training
+ 1.1370409999997833
+
+
+ usercpu_time_millis_training
+ 1.3173340000003364
+
+
+ wall_clock_time_millis_training
+ 11.349678039550781
+
+
+ wall_clock_time_millis_training
+ 1.294851303100586
+
+
+ wall_clock_time_millis_training
+ 1.1701583862304688
+
+
+ wall_clock_time_millis_training
+ 1.1692047119140625
+
+
+ wall_clock_time_millis_training
+ 1.2137889862060547
+
+
+ wall_clock_time_millis_training
+ 1.2259483337402344
+
+
+ wall_clock_time_millis_training
+ 1.294851303100586
+
+
+ wall_clock_time_millis_training
+ 1.2731552124023438
+
+
+ wall_clock_time_millis_training
+ 1.1365413665771484
+
+
+ wall_clock_time_millis_training
+ 1.318216323852539
+
+
+ usercpu_time_millis_testing
+ 0.8559159999999011
+
+
+ usercpu_time_millis_testing
+ 0.4579580000001471
+
+
+ usercpu_time_millis_testing
+ 0.45920799999965567
+
+
+ usercpu_time_millis_testing
+ 0.449209000000117
+
+
+ usercpu_time_millis_testing
+ 0.452333000000138
+
+
+ usercpu_time_millis_testing
+ 0.4404999999998438
+
+
+ usercpu_time_millis_testing
+ 0.46437499999996135
+
+
+ usercpu_time_millis_testing
+ 0.43887499999950563
+
+
+ usercpu_time_millis_testing
+ 0.4358330000000521
+
+
+ usercpu_time_millis_testing
+ 0.4521660000005312
+
+
+ usercpu_time_millis
+ 12.209581999999664
+
+
+ usercpu_time_millis
+ 1.7550420000000955
+
+
+ usercpu_time_millis
+ 1.6315409999991815
+
+
+ usercpu_time_millis
+ 1.6198760000003531
+
+
+ usercpu_time_millis
+ 1.6691660000001107
+
+
+ usercpu_time_millis
+ 1.6667909999998898
+
+
+ usercpu_time_millis
+ 1.761792000000817
+
+
+ usercpu_time_millis
+ 1.7187089999994853
+
+
+ usercpu_time_millis
+ 1.5728739999998353
+
+
+ usercpu_time_millis
+ 1.7695000000008676
+
+
+ wall_clock_time_millis_testing
+ 0.8571147918701172
+
+
+ wall_clock_time_millis_testing
+ 0.45943260192871094
+
+
+ wall_clock_time_millis_testing
+ 0.4608631134033203
+
+
+ wall_clock_time_millis_testing
+ 0.4506111145019531
+
+
+ wall_clock_time_millis_testing
+ 0.45418739318847656
+
+
+ wall_clock_time_millis_testing
+ 0.44226646423339844
+
+
+ wall_clock_time_millis_testing
+ 0.46944618225097656
+
+
+ wall_clock_time_millis_testing
+ 0.44035911560058594
+
+
+ wall_clock_time_millis_testing
+ 0.4374980926513672
+
+
+ wall_clock_time_millis_testing
+ 0.45371055603027344
+
+
+ wall_clock_time_millis
+ 12.206792831420898
+
+
+ wall_clock_time_millis
+ 1.7542839050292969
+
+
+ wall_clock_time_millis
+ 1.631021499633789
+
+
+ wall_clock_time_millis
+ 1.6198158264160156
+
+
+ wall_clock_time_millis
+ 1.6679763793945312
+
+
+ wall_clock_time_millis
+ 1.6682147979736328
+
+
+ wall_clock_time_millis
+ 1.7642974853515625
+
+
+ wall_clock_time_millis
+ 1.7135143280029297
+
+
+ wall_clock_time_millis
+ 1.5740394592285156
+
+
+ wall_clock_time_millis
+ 1.7719268798828125
+
+
+ predictive_accuracy
+ 0.9333333333333333
+
+
+ predictive_accuracy
+ 1.0
+
+
+ predictive_accuracy
+ 1.0
+
+
+ predictive_accuracy
+ 0.9333333333333333
+
+
+ predictive_accuracy
+ 1.0
+
+
+ predictive_accuracy
+ 0.9333333333333333
+
+
+ predictive_accuracy
+ 1.0
+
+
+ predictive_accuracy
+ 0.8666666666666667
+
+
+ predictive_accuracy
+ 0.8666666666666667
+
+
+ predictive_accuracy
+ 1.0
+
+
+
diff --git a/scripts/data/run/predictions.arff b/scripts/data/run/predictions.arff
new file mode 100644
index 0000000..31a0eb3
--- /dev/null
+++ b/scripts/data/run/predictions.arff
@@ -0,0 +1,170 @@
+% Python_3.10.16.
+% Sklearn_1.6.1.
+% NumPy_2.2.2.
+% SciPy_1.15.1.
+% Thu Oct 8 10:27:27 2026
+% Created by run_flow_on_task
+@RELATION openml_task_1196_predictions
+
+@ATTRIBUTE repeat NUMERIC
+@ATTRIBUTE fold NUMERIC
+@ATTRIBUTE sample NUMERIC
+@ATTRIBUTE row_id NUMERIC
+@ATTRIBUTE prediction {Iris-setosa, Iris-versicolor, Iris-virginica}
+@ATTRIBUTE correct {Iris-setosa, Iris-versicolor, Iris-virginica}
+@ATTRIBUTE confidence.Iris-setosa NUMERIC
+@ATTRIBUTE confidence.Iris-versicolor NUMERIC
+@ATTRIBUTE confidence.Iris-virginica NUMERIC
+
+@DATA
+0,0,0,43,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,0,0,14,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,0,0,37,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,0,0,23,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,0,0,10,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,0,0,99,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,0,0,87,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,0,0,97,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,0,0,62,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,0,0,92,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,0,0,119,Iris-versicolor,Iris-virginica,0.0,1.0,0.0
+0,0,0,111,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,0,0,144,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,0,0,116,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,0,0,125,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,1,0,49,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,1,0,15,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,1,0,47,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,1,0,0,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,1,0,44,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,1,0,76,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,1,0,89,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,1,0,58,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,1,0,54,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,1,0,53,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,1,0,149,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,1,0,114,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,1,0,112,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,1,0,115,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,1,0,139,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,2,0,42,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,2,0,41,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,2,0,31,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,2,0,48,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,2,0,7,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,2,0,94,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,2,0,93,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,2,0,95,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,2,0,51,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,2,0,72,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,2,0,135,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,2,0,124,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,2,0,141,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,2,0,105,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,2,0,143,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,3,0,34,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,3,0,22,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,3,0,45,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,3,0,3,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,3,0,16,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,3,0,79,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,3,0,55,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,3,0,98,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,3,0,80,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,3,0,77,Iris-virginica,Iris-versicolor,0.0,0.0,1.0
+0,3,0,120,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,3,0,122,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,3,0,145,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,3,0,100,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,3,0,107,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,4,0,4,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,4,0,27,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,4,0,38,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,4,0,19,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,4,0,33,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,4,0,96,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,4,0,50,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,4,0,61,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,4,0,65,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,4,0,73,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,4,0,109,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,4,0,126,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,4,0,110,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,4,0,148,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,4,0,103,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,5,0,46,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,5,0,6,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,5,0,18,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,5,0,36,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,5,0,24,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,5,0,83,Iris-virginica,Iris-versicolor,0.0,0.0,1.0
+0,5,0,90,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,5,0,68,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,5,0,52,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,5,0,75,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,5,0,134,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,5,0,104,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,5,0,117,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,5,0,127,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,5,0,121,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,6,0,26,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,6,0,13,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,6,0,32,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,6,0,20,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,6,0,17,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,6,0,63,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,6,0,88,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,6,0,64,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,6,0,91,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,6,0,81,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,6,0,137,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,6,0,101,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,6,0,130,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,6,0,118,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,6,0,108,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,7,0,29,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,7,0,40,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,7,0,12,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,7,0,35,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,7,0,8,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,7,0,86,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,7,0,82,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,7,0,84,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,7,0,74,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,7,0,57,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,7,0,140,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,7,0,133,Iris-versicolor,Iris-virginica,0.0,1.0,0.0
+0,7,0,106,Iris-versicolor,Iris-virginica,0.0,1.0,0.0
+0,7,0,128,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,7,0,102,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,8,0,25,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,8,0,1,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,8,0,21,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,8,0,30,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,8,0,28,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,8,0,67,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,8,0,78,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,8,0,66,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,8,0,70,Iris-virginica,Iris-versicolor,0.0,0.0,1.0
+0,8,0,59,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,8,0,136,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,8,0,138,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,8,0,129,Iris-versicolor,Iris-virginica,0.0,1.0,0.0
+0,8,0,113,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,8,0,132,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,9,0,5,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,9,0,11,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,9,0,9,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,9,0,39,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,9,0,2,Iris-setosa,Iris-setosa,1.0,0.0,0.0
+0,9,0,85,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,9,0,56,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,9,0,69,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,9,0,71,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,9,0,60,Iris-versicolor,Iris-versicolor,0.0,1.0,0.0
+0,9,0,142,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,9,0,123,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,9,0,131,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,9,0,147,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+0,9,0,146,Iris-virginica,Iris-virginica,0.0,0.0,1.0
+
diff --git a/scripts/upload_run.sh b/scripts/upload_run.sh
new file mode 100755
index 0000000..5b7a561
--- /dev/null
+++ b/scripts/upload_run.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# Uploads a run to the REST API and prints the run ID to stdout.
+# The predictions and description files are fixed in scripts/data/run/.
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+RESPONSE=$(curl -s -X POST "http://localhost:8000/api/v1/xml/run?api_key=normaluser" \
+ -F "description=@${SCRIPT_DIR}/data/run/description.xml;type=text/xml" \
+ -F "predictions=@${SCRIPT_DIR}/data/run/predictions.arff")
+
+RUN_ID=$(echo "$RESPONSE" | sed -n 's/.*\([0-9]*\)<\/oml:id>.*/\1/p')
+
+if [ -z "$RUN_ID" ]; then
+ echo "Server response:" >&2
+ echo "$RESPONSE" >&2
+ exit 1
+fi
+
+echo "$RUN_ID"
diff --git a/scripts/wait_for_run.sh b/scripts/wait_for_run.sh
new file mode 100755
index 0000000..29c273e
--- /dev/null
+++ b/scripts/wait_for_run.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# Waits until a run has evaluations computed by the evaluation engine.
+# Usage: wait_for_run.sh RUN_ID [TIMEOUT]
+set -euo pipefail
+
+RUN_ID="${1:?Usage: wait_for_run.sh RUN_ID [TIMEOUT]}"
+TIMEOUT="${2:-120}"
+INTERVAL=5
+ELAPSED=0
+
+while [ "$ELAPSED" -lt "$TIMEOUT" ]; do
+ RESPONSE=$(curl -s "http://localhost:8000/api/v1/xml/run/${RUN_ID}")
+
+ if echo "$RESPONSE" | grep -q "area_under_roc_curve"; then
+ echo "Run $RUN_ID has evaluations."
+ exit 0
+ fi
+
+ echo "No evaluations yet after ${ELAPSED}s"
+
+ sleep "$INTERVAL"
+ ELAPSED=$((ELAPSED + INTERVAL))
+done
+
+echo "ERROR: Run $RUN_ID did not get evaluations within ${TIMEOUT} seconds."
+exit 1
From 047c24c010821099c76539121613d5ac5f5459c1 Mon Sep 17 00:00:00 2001
From: PGijsbers
Date: Tue, 13 Oct 2026 12:16:41 +0200
Subject: [PATCH 09/12] Use correct identifier to extract run ID
---
scripts/upload_run.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/upload_run.sh b/scripts/upload_run.sh
index 5b7a561..27d2d43 100755
--- a/scripts/upload_run.sh
+++ b/scripts/upload_run.sh
@@ -9,7 +9,7 @@ RESPONSE=$(curl -s -X POST "http://localhost:8000/api/v1/xml/run?api_key=normalu
-F "description=@${SCRIPT_DIR}/data/run/description.xml;type=text/xml" \
-F "predictions=@${SCRIPT_DIR}/data/run/predictions.arff")
-RUN_ID=$(echo "$RESPONSE" | sed -n 's/.*\([0-9]*\)<\/oml:id>.*/\1/p')
+RUN_ID=$(echo "$RESPONSE" | sed -n 's/.*\([0-9]*\)<\/oml:run_id>.*/\1/p')
if [ -z "$RUN_ID" ]; then
echo "Server response:" >&2
From 3e923326080672bcb3cc98e139c9e8526143fed7 Mon Sep 17 00:00:00 2001
From: PGijsbers
Date: Tue, 13 Oct 2026 16:02:59 +0200
Subject: [PATCH 10/12] remove unused file
---
scripts/evaluation_engine_dataset.sh | 10 ----------
1 file changed, 10 deletions(-)
delete mode 100644 scripts/evaluation_engine_dataset.sh
diff --git a/scripts/evaluation_engine_dataset.sh b/scripts/evaluation_engine_dataset.sh
deleted file mode 100644
index dd4f2ee..0000000
--- a/scripts/evaluation_engine_dataset.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-# Tests the dataset upload and processing of the REST API and Evaluation Engine
-set -euo pipefail
-
-SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
-
-DATASET_ID=$("${SCRIPT_DIR}/upload_dataset.sh")
-echo "Uploaded dataset with ID: $DATASET_ID"
-
-"${SCRIPT_DIR}/wait_for_dataset.sh" "$DATASET_ID"
From c88cd03fb77ce62c0e9b9de8b516cc2f6dc40f26 Mon Sep 17 00:00:00 2001
From: PGijsbers
Date: Tue, 13 Oct 2026 16:05:01 +0200
Subject: [PATCH 11/12] show errors for curl
---
scripts/create_task.sh | 2 +-
scripts/upload_dataset.sh | 2 +-
scripts/upload_run.sh | 2 +-
scripts/wait_for_dataset.sh | 2 +-
scripts/wait_for_run.sh | 2 +-
scripts/wait_for_task.sh | 4 ++--
6 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/scripts/create_task.sh b/scripts/create_task.sh
index d09bc99..d7bc9ac 100755
--- a/scripts/create_task.sh
+++ b/scripts/create_task.sh
@@ -19,7 +19,7 @@ cat > "$TMPFILE" << EOF
EOF
-RESPONSE=$(curl -s -X POST "http://localhost:8000/api/v1/xml/task?api_key=normaluser" \
+RESPONSE=$(curl -sS -X POST "http://localhost:8000/api/v1/xml/task?api_key=normaluser" \
-F "description=@${TMPFILE};type=text/xml")
TASK_ID=$(echo "$RESPONSE" | sed -n 's/.*\([0-9]*\)<\/oml:id>.*/\1/p')
diff --git a/scripts/upload_dataset.sh b/scripts/upload_dataset.sh
index e031ad6..669ceb1 100755
--- a/scripts/upload_dataset.sh
+++ b/scripts/upload_dataset.sh
@@ -23,7 +23,7 @@ TMPFILE=$(mktemp /tmp/dataset_desc.XXXXXX.xml)
trap 'rm -f "$TMPFILE"' EXIT
echo "$XML_DESCRIPTION" > "$TMPFILE"
-RESPONSE=$(curl -s -X POST "http://localhost:8000/api/v1/xml/data?api_key=normaluser" \
+RESPONSE=$(curl -sS -X POST "http://localhost:8000/api/v1/xml/data?api_key=normaluser" \
-F "description=@${TMPFILE};type=text/xml" \
-F "dataset=@${SCRIPT_DIR}/data/test.arff")
diff --git a/scripts/upload_run.sh b/scripts/upload_run.sh
index 27d2d43..912b072 100755
--- a/scripts/upload_run.sh
+++ b/scripts/upload_run.sh
@@ -5,7 +5,7 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
-RESPONSE=$(curl -s -X POST "http://localhost:8000/api/v1/xml/run?api_key=normaluser" \
+RESPONSE=$(curl -sS -X POST "http://localhost:8000/api/v1/xml/run?api_key=normaluser" \
-F "description=@${SCRIPT_DIR}/data/run/description.xml;type=text/xml" \
-F "predictions=@${SCRIPT_DIR}/data/run/predictions.arff")
diff --git a/scripts/wait_for_dataset.sh b/scripts/wait_for_dataset.sh
index 6bdd0a9..f7c1c52 100755
--- a/scripts/wait_for_dataset.sh
+++ b/scripts/wait_for_dataset.sh
@@ -9,7 +9,7 @@ INTERVAL=5
ELAPSED=0
while [ "$ELAPSED" -lt "$TIMEOUT" ]; do
- STATUS_RESPONSE=$(curl -s "http://localhost:8000/api/v1/xml/data/${DATASET_ID}")
+ STATUS_RESPONSE=$(curl -sS "http://localhost:8000/api/v1/xml/data/${DATASET_ID}")
STATUS=$(echo "$STATUS_RESPONSE" | sed -n 's/.*\([a-zA-Z_]*\)<\/oml:status>.*/\1/p')
echo "Status after ${ELAPSED}s: ${STATUS:-unknown}"
diff --git a/scripts/wait_for_run.sh b/scripts/wait_for_run.sh
index 29c273e..9cecbd4 100755
--- a/scripts/wait_for_run.sh
+++ b/scripts/wait_for_run.sh
@@ -9,7 +9,7 @@ INTERVAL=5
ELAPSED=0
while [ "$ELAPSED" -lt "$TIMEOUT" ]; do
- RESPONSE=$(curl -s "http://localhost:8000/api/v1/xml/run/${RUN_ID}")
+ RESPONSE=$(curl -sS "http://localhost:8000/api/v1/xml/run/${RUN_ID}")
if echo "$RESPONSE" | grep -q "area_under_roc_curve"; then
echo "Run $RUN_ID has evaluations."
diff --git a/scripts/wait_for_task.sh b/scripts/wait_for_task.sh
index 6fdc98b..b77aece 100755
--- a/scripts/wait_for_task.sh
+++ b/scripts/wait_for_task.sh
@@ -9,11 +9,11 @@ INTERVAL=5
ELAPSED=0
while [ "$ELAPSED" -lt "$TIMEOUT" ]; do
- RESPONSE=$(curl -s "http://localhost:8000/api/v1/xml/task/${TASK_ID}")
+ RESPONSE=$(curl -sS "http://localhost:8000/api/v1/xml/task/${TASK_ID}")
SPLITS_URL=$(echo "$RESPONSE" | sed -n 's/.*\(.*\)<\/oml:data_splits_url>.*/\1/p')
if [ -n "$SPLITS_URL" ]; then
- SPLITS_RESPONSE=$(curl -s -w "\n%{http_code}" "$SPLITS_URL")
+ SPLITS_RESPONSE=$(curl -sS -w "\n%{http_code}" "$SPLITS_URL")
STATUS_CODE=$(echo "$SPLITS_RESPONSE" | tail -n1)
SPLITS_BODY=$(echo "$SPLITS_RESPONSE" | sed '$d')
if [ "$STATUS_CODE" = "200" ]; then
From 3a55ba166c431756caa63d4754b37b7f1d3c06b0 Mon Sep 17 00:00:00 2001
From: PGijsbers
Date: Tue, 13 Oct 2026 16:13:02 +0200
Subject: [PATCH 12/12] Mention the new test scripts in the README
---
README.md | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/README.md b/README.md
index 9d76501..f18ab25 100644
--- a/README.md
+++ b/README.md
@@ -114,6 +114,20 @@ be slightly altered to use them in the test setup: change https to http.
## Development
+### Services
+When working on the `services` repository itself, the `scripts` directory provides a small number of integration tests to catch the most glaring issues. They are currently limited to REST API and evaluation engine functionality and also run automatically in CI.
+
+For example, after starting services, to test dataset upload run:
+```bash
+./scripts/upload_dataset.sh
+```
+If successful, this will also print the dataset id assigned to the new dataset.
+To test if dataset processing works, we can then run:
+```bash
+./scripts/wait_for_dataset.sh DATASET_ID
+```
+where `DATASET_ID` is replaced by the identifier printed in the previous step.
+
### PHP, Parquet and Croissant converter
If you want to do local development on containers that are part of the docker-compose, you want those containers to change based on your code. You should have the relevant code somewhere on your system. You will need to tell the docker-compose where to find it. You can do so by setting environment variables.