11#! /usr/bin/env bash
2- # The library service, checked end to end over sbml-exporter's fixture graph
3- # (spec 015 T063): the image this repository builds, its answers for the
4- # fixture's three events compared with the expected files of the sbml-exporter
5- # commit it is pinned to, by that commit's own ci/compare.py.
2+ # The library service, checked end to end (spec 015 T063, T069): the image this
3+ # repository builds, over each exporter's own fixture graph, its answers
4+ # compared with the expected files of the commit it is pinned to, by that
5+ # commit's own instruments:
6+ # - SBML over sbml-exporter's fixture: the three events' files, by its
7+ # ci/compare.py;
8+ # - BioPAX over BioPAX3Exporter's fixture: events of each kind and both
9+ # species, each contained in its species' expected file, by its
10+ # ci/contained.py, with the release's per-event xml:base.
611#
712# Usage: deploy/java-library/check.sh [image]
8- # GRAPH_PORT (7687) and FILES_PORT (8097) move the fixture graph and the files
9- # off ports a host already uses; the service keeps its own, 4360.
13+ # GRAPH_PORT (7687), FILES_PORT (8097) and SERVICE_PORT (4360) move the fixture
14+ # graph, the files and the service off ports a host already uses (a deployment's
15+ # own service is on 4360).
1016# Without an image, it builds one. Needs docker, curl and python3 with
1117# python-libsbml 5.21.2 (pip install python-libsbml==5.21.2).
1218set -euo pipefail
1319
1420graph_port=${GRAPH_PORT:- 7687}
1521files_port=${FILES_PORT:- 8097}
22+ service_port=${SERVICE_PORT:- 4360}
1623
17- # The check's own service takes 4360 on the host's network. One already there
24+ # The check's own service takes its port on the host's network. One already there
1825# (a deployment's) would answer the checks below in its place, over its graph.
1926# Any answer refuses, a 503 too (a deployment whose graph is down), and it is
2027# refused before the trap below, whose clean-up would remove another run's
2128# containers.
22- if curl -s -m 5 -o /dev/null http://127.0.0.1:4360 /health; then
23- echo " Something already answers on 127.0.0.1:4360 ; stop it, or run this elsewhere " >&2
29+ if curl -s -m 5 -o /dev/null http://127.0.0.1:$service_port /health; then
30+ echo " Something already answers on 127.0.0.1:$service_port ; stop it, or set SERVICE_PORT " >&2
2431 exit 1
2532fi
2633
@@ -30,9 +37,11 @@ work=$(mktemp -d)
3037# Named for this run, so a run that stops early removes only its own.
3138neo=java-library-check-graph-$$
3239service=java-library-check-$$
40+ neo2=java-library-check-graph2-$$
41+ service2=java-library-check2-$$
3342# shellcheck disable=SC2317 # called by the trap
3443cleanup () {
35- docker rm -f -v " $neo " " $service " > /dev/null 2>&1 || true
44+ docker rm -f -v " $neo " " $service " " $neo2 " " $service2 " > /dev/null 2>&1 || true
3645 if [ -n " ${server:- } " ]; then kill " $server " 2> /dev/null || true ; fi
3746 rm -rf " $work "
3847}
@@ -51,37 +60,47 @@ curl -fsSL "https://codeload.github.com/reactome/sbml-exporter/tar.gz/$commit" \
5160 | tar -xz -C " $work /sbml-exporter" --strip-components=1 --wildcards ' */ci/*'
5261ci=" $work /sbml-exporter/ci"
5362
54- # The fixture graph, on loopback.
55- docker run -d --name " $neo " -p " 127.0.0.1:$graph_port :7687" \
56- -e NEO4J_AUTH=neo4j/fixturepass -e NEO4J_dbms_default__database=graph.db \
57- -v " $ci /fixture/fixture.cypher:/fixture.cypher:ro" neo4j:4.4.48-community > /dev/null
58- for _ in $( seq 90) ; do
59- docker exec " $neo " cypher-shell -u neo4j -p fixturepass -d graph.db ' RETURN 1' > /dev/null 2>&1 && break
60- sleep 2
61- done
62- docker exec " $neo " cypher-shell -u neo4j -p fixturepass -d graph.db -f /fixture.cypher > /dev/null
63+ # A fixture graph, on loopback: start_graph <container> <fixture.cypher>
64+ start_graph () {
65+ docker run -d --name " $1 " -p " 127.0.0.1:$graph_port :7687" \
66+ -e NEO4J_AUTH=neo4j/fixturepass -e NEO4J_dbms_default__database=graph.db \
67+ -v " $2 :/fixture.cypher:ro" neo4j:4.4.48-community > /dev/null
68+ for _ in $( seq 90) ; do
69+ docker exec " $1 " cypher-shell -u neo4j -p fixturepass -d graph.db ' RETURN 1' > /dev/null 2>&1 && break
70+ sleep 2
71+ done
72+ docker exec " $1 " cypher-shell -u neo4j -p fixturepass -d graph.db -f /fixture.cypher > /dev/null
73+ }
74+
75+ # The service over it, answering its health check: start_service <container>
76+ start_service () {
77+ docker run -d --name " $1 " --network host \
78+ -e NEO4J_URI=" bolt://127.0.0.1:$graph_port " -e NEO4J_USER=neo4j -e NEO4J_PASSWORD=fixturepass \
79+ -e DIAGRAM_BASE=" http://127.0.0.1:$files_port /" -e SBML_CACHE=/cache \
80+ -e SERVER_PORT=" $service_port " " $image " > /dev/null
81+ for _ in $( seq 90) ; do
82+ curl -fs http://127.0.0.1:$service_port /health > /dev/null && break
83+ sleep 2
84+ done
85+ if ! curl -fsS http://127.0.0.1:$service_port /health; then
86+ echo " The service did not answer its health check. Its log:" >&2
87+ docker logs " $1 " 2>&1 | tail -60 >&2
88+ exit 1
89+ fi
90+ echo
91+ }
92+
93+ start_graph " $neo " " $ci /fixture/fixture.cypher"
6394
6495# The release's download directory, as far as the fixture needs it.
6596mkdir -p " $work /www/97/diagram"
6697cp " $ci " /fixture/R-* .json " $work /www/97/diagram/"
6798python3 -m http.server " $files_port " --bind 127.0.0.1 --directory " $work /www" > /dev/null 2>&1 &
6899server=$!
69100
70- docker run -d --name " $service " --network host \
71- -e NEO4J_URI=" bolt://127.0.0.1:$graph_port " -e NEO4J_USER=neo4j -e NEO4J_PASSWORD=fixturepass \
72- -e DIAGRAM_BASE=" http://127.0.0.1:$files_port /" -e SBML_CACHE=/cache " $image " > /dev/null
73- for _ in $( seq 90) ; do
74- curl -fs http://127.0.0.1:4360/health > /dev/null && break
75- sleep 2
76- done
77- if ! curl -fsS http://127.0.0.1:4360/health; then
78- echo " The service did not answer its health check. Its log:" >&2
79- docker logs " $service " 2>&1 | tail -60 >&2
80- exit 1
81- fi
82- echo
101+ start_service " $service "
83102
84- status () { curl -s -o " $2 " -w ' %{http_code}' " http://127.0.0.1:4360 /sbml/$1 " ; }
103+ status () { curl -s -o " $2 " -w ' %{http_code}' " http://127.0.0.1:$service_port /sbml/$1 " ; }
85104fail=0
86105mkdir " $work /out"
87106for id in $( find " $ci /fixture/expected" -name ' R-*.sbml' -exec basename {} .sbml \; | sort) ; do
@@ -93,6 +112,57 @@ code=$(status R-HSA-1 /dev/null)
93112code=$( status R-HSA-9613354.1 /dev/null)
94113[ " $code " = 400 ] || { echo " R-HSA-9613354.1 (not a bare stable id): $code , expected 400" >&2 ; fail=1; }
95114
96- python3 " $ci /validate.py" " $work /out"
97- python3 " $ci /compare.py" " $ci /fixture/expected" " $work /out"
115+ python3 " $ci /validate.py" " $work /out" || fail=1
116+ python3 " $ci /compare.py" " $ci /fixture/expected" " $work /out" || fail=1
117+
118+ # BioPAX, over BioPAX3Exporter's fixture graph (release 98), in a graph and a
119+ # service of their own.
120+ docker rm -f -v " $neo " " $service " > /dev/null
121+ bcommit=$( sed -n ' s/^ARG BIOPAX3_EXPORTER_COMMIT=\([0-9a-f]\{40\}\)$/\1/p' " $root /deploy/java-library/Dockerfile" | sort -u)
122+ [ " $( printf ' %s\n' " $bcommit " | wc -l) " -eq 1 ] || { echo " The Dockerfile names more than one BioPAX3Exporter commit" >&2 ; exit 1; }
123+ mkdir " $work /BioPAX3Exporter"
124+ curl -fsSL " https://codeload.github.com/reactome/BioPAX3Exporter/tar.gz/$bcommit " \
125+ | tar -xz -C " $work /BioPAX3Exporter" --strip-components=1 --wildcards ' */ci/*'
126+ bci=" $work /BioPAX3Exporter/ci"
127+ start_graph " $neo2 " " $bci /fixture/fixture.cypher"
128+ start_service " $service2 "
129+
130+ # Events of each kind and both species: of the graph's, by database id, the
131+ # first of each kind that its species' expected file holds (the fixture has
132+ # events beyond those files, such as an inferred event's source). Each line:
133+ # stId, dbId, species.
134+ candidates=$( docker exec " $neo2 " cypher-shell -u neo4j -p fixturepass -d graph.db --format plain '
135+ CALL {
136+ MATCH (e:TopLevelPathway {speciesName: "Homo sapiens"}) RETURN "pathway" AS kind, e
137+ UNION ALL MATCH (e:Reaction {speciesName: "Homo sapiens"}) RETURN "reaction" AS kind, e
138+ UNION ALL MATCH (e:BlackBoxEvent {speciesName: "Homo sapiens"}) RETURN "blackbox" AS kind, e
139+ UNION ALL MATCH (e:ReactionLikeEvent {dbId: 174731}) RETURN "degradation" AS kind, e
140+ UNION ALL MATCH (e:Pathway {speciesName: "Plasmodium falciparum"}) RETURN "falciparum" AS kind, e
141+ }
142+ RETURN kind + " " + e.stId + " " + e.dbId + " " + replace(e.speciesName, " ", "_")
143+ ORDER BY kind, e.dbId' | tail -n +2 | tr -d ' "' )
144+ events=$( while read -r kind id dbid species; do
145+ grep -q " >$dbid </bp:id>" " $bci /fixture/expected/$species .owl" && echo " $kind $id $dbid $species "
146+ done <<< " $candidates" | sort -u -k1,1 | cut -d' ' -f2-)
147+ [ " $( printf ' %s\n' " $events " | wc -l) " -eq 5 ] || { echo " Expected one event of each of five kinds in the fixture's files, got: $events " >&2 ; exit 1; }
148+
149+ bstatus () { curl -s -o " $2 " -w ' %{http_code}' " http://127.0.0.1:$service_port /biopax/$1 " ; }
150+ mkdir -p " $work /owl/Homo_sapiens" " $work /owl/Plasmodium_falciparum"
151+ while read -r id dbid species; do
152+ file=" $work /owl/$species /$id .owl"
153+ code=$( bstatus " $id " " $file " )
154+ [ " $code " = 200 ] || { echo " $id : $code , expected 200" >&2 ; fail=1; continue ; }
155+ # The release's per-event base: Reactome's BioPAX namespace, the release, the event's database id
156+ grep -q " xml:base=\" http://www.reactome.org/biopax/98/$dbid #\" " " $file " \
157+ || { echo " $id : not the release's per-event xml:base" >&2 ; fail=1; }
158+ done <<< " $events"
159+ code=$( bstatus R-HSA-1 /dev/null)
160+ [ " $code " = 404 ] || { echo " R-HSA-1 (not in the graph): $code , expected 404" >&2 ; fail=1; }
161+ code=$( bstatus R-HSA-174731.1 /dev/null)
162+ [ " $code " = 400 ] || { echo " R-HSA-174731.1 (not a bare stable id): $code , expected 400" >&2 ; fail=1; }
163+
164+ # Each event's file holds nothing its species' file lacks, and is whole
165+ for species in Homo_sapiens Plasmodium_falciparum; do
166+ python3 -I " $bci /contained.py" " $bci /fixture/expected/$species .owl" " $work /owl/$species " /* .owl || fail=1
167+ done
98168exit $fail
0 commit comments