Skip to content

Commit ac33825

Browse files
chore(parse-server-mongo): enrich flow.sh to reliably trigger boot-phase divergence (#95)
The previous 3-call flow (signup, POST GameScore, GET GameScore) was too tight to consistently trigger the chronology divergence the mongo/v2 boot-phase tiebreaker bug needs at replay. With only one user class and a fast post-flow, the recording often captured a single same-shape find _SCHEMA snapshot — no diverging candidate set for the tiebreaker to pick the wrong one against, so the falsifying lane in keploy/integrations would pass against the unfixed binary too. Enriched flow: - 3-second sleep after parse-server health check, so the eager- index sweep at boot has time to land multiple pre-mutation find _SCHEMA captures before any user class is inserted. - Tier 1: read-only probes (health, serverInfo, config, schemas). - Tier 2: signup + login (no user-class mutation). - Tier 3: three user classes inserted via POST /classes/<Name> (GameScore, PlayerStats, Achievement). Each insert mutates _SCHEMA + refreshes Parse Server's schema cache, capturing a fresh find _SCHEMA mock with the larger class set. - Tier 4: read-after-mutation calls so post-mutation snapshots also land in the recording. The recording now spans at least four distinct find _SCHEMA response shapes (empty, +GameScore, +GameScore +PlayerStats, +all three), which is wide enough that the unfixed tiebreaker will reliably pick a post-mutation mock at replay and the booting app will run a listIndexes query whose mock the recording never captured at boot phase. Signed-off-by: Akash Kumar <meakash7902@gmail.com>
1 parent 976955f commit ac33825

1 file changed

Lines changed: 78 additions & 23 deletions

File tree

parse-server-mongo/flow.sh

Lines changed: 78 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,39 @@
11
#!/usr/bin/env bash
2-
# Minimum reproducer traffic for the mongo/v2 boot-phase tiebreaker bug.
2+
# Reproducer traffic for the mongo/v2 boot-phase tiebreaker bug.
33
#
4-
# Three calls produce the chronology divergence the lane needs:
5-
# 1. POST /parse/users (signup) — drives parse-server's boot find _SCHEMA
6-
# sweep + insert _SCHEMA for system classes (_User, _Role, _Session, ...).
7-
# All these mocks land before the user-defined class exists in _SCHEMA.
8-
# 2. POST /parse/classes/GameScore — parse-server lazily inserts the
9-
# user-defined class into _SCHEMA AFTER its initial boot sweep,
10-
# mutating state mid-recording. From this point onward, find _SCHEMA
11-
# responses include GameScore.
12-
# 3. GET /parse/classes/GameScore/<id> — exercises the post-mutation
13-
# state so the recording captures find _SCHEMA mocks with the
14-
# diverged response shape.
4+
# What the bug needs to surface:
5+
# - The recording captures multiple same-shape `find _SCHEMA filter:{}`
6+
# mocks at boot, with diverging responses. Early ones see only
7+
# system classes (_User, _Role, _Session, ...); later ones see
8+
# user-defined classes Parse Server lazily added during traffic.
9+
# - At replay, the matcher's score-tied tiebreaker picks ONE of those
10+
# same-shape mocks. The unfixed tiebreaker biases toward the latest
11+
# (with user classes), which steers a booting app onto a steady-
12+
# state code path and runs `listIndexes <user-class>` for classes
13+
# the boot phase didn't witness — surfacing as a downstream cascade
14+
# mock-miss.
1515
#
16-
# At replay, the boot-phase matcher's score-tied tiebreaker decides which
17-
# of the multiple same-shape find _SCHEMA mocks wins. Without the fix, it
18-
# picks the latest (post-GameScore-insertion); the booting app sees the
19-
# user class in _SCHEMA, runs `listIndexes <user-class>` (never recorded),
20-
# and dies with MongoNetworkError. With the fix, it picks the earliest
21-
# (pre-insertion); parse-server processes only system classes at boot,
22-
# the recorded follow-on queries match, and the app boots cleanly.
16+
# To reliably trigger that divergence we (a) give Parse Server time to
17+
# complete its eager-index sweep before any HTTP test fires, and
18+
# (b) drive several class-mutating calls that each cause Parse Server
19+
# to refresh its schema cache and capture a new post-mutation
20+
# `find _SCHEMA` mock. The flow exercises three user classes
21+
# (GameScore, PlayerStats, Achievement) so the divergence window is
22+
# wide enough that even a one-off boot probe at replay will pick one
23+
# of the post-mutation mocks under the unfixed tiebreaker.
2324

2425
set -Eeuo pipefail
2526

2627
APP_PORT="${APP_PORT:-6100}"
2728
APP_ID="${PARSE_SERVER_APPLICATION_ID:-keploy-parse-app}"
2829
MASTER_KEY="${PARSE_SERVER_MASTER_KEY:-keploy-parse-master}"
2930
USER_ID="${USER_ID:-keploy-user-id}"
31+
USERNAME="${USERNAME:-keploy-user}"
32+
PASSWORD="${PASSWORD:-KeployPass123!}"
33+
EMAIL="${EMAIL:-keploy@example.com}"
3034
SCORE_ID="${SCORE_ID:-keploy-score-id}"
35+
PLAYER_ID="${PLAYER_ID:-keploy-player-id}"
36+
ACHIEVEMENT_ID="${ACHIEVEMENT_ID:-keploy-achievement-id}"
3137

3238
base="http://localhost:${APP_PORT}/parse"
3339
h_app=(-H "X-Parse-Application-Id: ${APP_ID}")
@@ -43,18 +49,67 @@ for i in $(seq 1 180); do
4349
sleep 1
4450
done
4551

52+
# Give Parse Server a beat to finish its boot eager-index sweep so the
53+
# recording captures multiple pre-mutation find _SCHEMA snapshots
54+
# before any state mutation lands. Without this, all the find _SCHEMA
55+
# captures might come AFTER the first user class is inserted, so
56+
# there's no diverging same-shape candidate set for the matcher's
57+
# tiebreaker to contend over.
58+
sleep 3
59+
60+
# --- Tier 1: read-only probes (no _SCHEMA mutation, but each handler
61+
# may cause Parse Server to refresh its schema cache, capturing more
62+
# pre-mutation find _SCHEMA snapshots) ---
63+
64+
curl -fsS "${h_app[@]}" "${base}/health" >/dev/null
65+
curl -fsS "${h_app[@]}" "${h_master[@]}" "${base}/serverInfo" >/dev/null
66+
curl -fsS "${h_app[@]}" "${h_master[@]}" "${base}/config" >/dev/null
67+
curl -fsS "${h_app[@]}" "${h_master[@]}" "${base}/schemas" >/dev/null
68+
echo "[flow] tier 1 (read-only probes) done"
69+
70+
# --- Tier 2: signup + login (mutates _Session but not user classes) ---
71+
4672
curl -fsS -X POST "${h_app[@]}" "${h_json[@]}" "${base}/users" \
47-
--data "{\"objectId\":\"${USER_ID}\",\"username\":\"keploy-user\",\"password\":\"KeployPass123!\",\"email\":\"keploy@example.com\"}" \
73+
--data "{\"objectId\":\"${USER_ID}\",\"username\":\"${USERNAME}\",\"password\":\"${PASSWORD}\",\"email\":\"${EMAIL}\"}" \
4874
>/dev/null
4975
echo "[flow] signup ok"
5076

77+
curl -fsS "${h_app[@]}" "${base}/login?username=${USERNAME}&password=${PASSWORD}" >/dev/null
78+
echo "[flow] login ok"
79+
80+
# --- Tier 3: user-class mutations. Each `POST /classes/<NewClass>`
81+
# triggers Parse Server to insert the class into _SCHEMA, refresh
82+
# its schema cache, and run listIndexes on the new collection. The
83+
# subsequent find _SCHEMA captures will include the newly-added
84+
# class. After three different classes, the recording's find
85+
# _SCHEMA mocks span four distinct response shapes. ---
86+
5187
curl -fsS -X POST "${h_app[@]}" "${h_master[@]}" "${h_json[@]}" "${base}/classes/GameScore" \
52-
--data "{\"objectId\":\"${SCORE_ID}\",\"score\":10,\"playerName\":\"keploy-user\"}" \
88+
--data "{\"objectId\":\"${SCORE_ID}\",\"score\":10,\"playerName\":\"${USERNAME}\"}" \
5389
>/dev/null
5490
echo "[flow] GameScore POST ok"
5591

56-
curl -fsS "${h_app[@]}" "${h_master[@]}" "${base}/classes/GameScore/${SCORE_ID}" \
92+
curl -fsS -X POST "${h_app[@]}" "${h_master[@]}" "${h_json[@]}" "${base}/classes/PlayerStats" \
93+
--data "{\"objectId\":\"${PLAYER_ID}\",\"level\":1,\"xp\":100,\"playerName\":\"${USERNAME}\"}" \
94+
>/dev/null
95+
echo "[flow] PlayerStats POST ok"
96+
97+
curl -fsS -X POST "${h_app[@]}" "${h_master[@]}" "${h_json[@]}" "${base}/classes/Achievement" \
98+
--data "{\"objectId\":\"${ACHIEVEMENT_ID}\",\"name\":\"first-class\",\"unlocked\":true}" \
5799
>/dev/null
58-
echo "[flow] GameScore GET ok"
100+
echo "[flow] Achievement POST ok"
101+
102+
# --- Tier 4: read-after-mutation. Each call may cause Parse Server
103+
# to consult its schema cache (recently invalidated by the inserts
104+
# above), capturing more post-mutation find _SCHEMA mocks. ---
105+
106+
curl -fsS "${h_app[@]}" "${h_master[@]}" "${base}/classes/GameScore/${SCORE_ID}" >/dev/null
107+
curl -fsS "${h_app[@]}" "${h_master[@]}" "${base}/classes/PlayerStats/${PLAYER_ID}" >/dev/null
108+
curl -fsS "${h_app[@]}" "${h_master[@]}" "${base}/classes/Achievement/${ACHIEVEMENT_ID}" >/dev/null
109+
curl -fsS -X PUT "${h_app[@]}" "${h_master[@]}" "${h_json[@]}" "${base}/classes/GameScore/${SCORE_ID}" \
110+
--data '{"score":99}' >/dev/null
111+
curl -fsS "${h_app[@]}" "${h_master[@]}" "${base}/schemas" >/dev/null
112+
curl -fsS "${h_app[@]}" "${h_master[@]}" "${base}/schemas/GameScore" >/dev/null
113+
echo "[flow] tier 4 (read-after-mutation) done"
59114

60115
echo "[flow] complete"

0 commit comments

Comments
 (0)