Repository navigation
Expand file tree
/
Copy pathtest.sh
More file actions
executable file
·194 lines (177 loc) · 12.1 KB
/
Copy pathtest.sh
File metadata and controls
executable file
·194 lines (177 loc) · 12.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#!/usr/bin/env bash
# Keep a user-level ~/.npmrc (such as a private registry) out of this run unless a userconfig is set explicitly.
export NPM_CONFIG_USERCONFIG="${NPM_CONFIG_USERCONFIG:-${npm_config_userconfig:-/dev/null}}"
# Execute running tests from same directory as current script
cd "$(dirname "$0")"
# Install dependencies, then lint, build and run the unit and type tests. The first failure ends this script with its
# status, before the contract test runs.
npm install --min-release-age=14 && \
npm run lint && \
npm run build && \
npm run test || exit
# The contract test, test/mock-contract.cjs, runs this SDK against the Files.com Mock API Server generated from the same
# public schema: the one in FILES_CONTRACT_MOCK_SERVER, as CI sets it after generating it, or else the generator's
# sibling generated/mock-server. Its --check fails, and so does this script, when that server is missing or was not
# generated from this SDK's schema; no other server, such as the files-mock-server service, stands in for it. The
# server's own with-scenario.rb then runs the test against it, on loopback with the folder-list scenario, and keeps its
# evidence in a new directory under test-results/. It allows 30 s for the server to be ready and 60 s for the test,
# and waits up to 5 s each time it stops a process group, with TERM and then KILL.
#
# The server runs with the Mock's own bundle (`bundle exec puma`, with the Mock's Gemfile), whose gems the Mock's
# setup.sh installed in Bundler's original environment: the one before a `bundle exec` above this script, such as the
# generator's, changed it. with-scenario.rb drops that caller's Gemfile, preload and Bundler variables itself, but not
# the gem paths, PATH and RUBYLIB a `bundle exec` also passes down, so it runs here in that original environment too,
# as setup.sh does. With no `bundle exec` above this script, that is the environment as it is.
mock_server="${FILES_CONTRACT_MOCK_SERVER:-../mock-server}"
schema_sha256="$(node test/mock-contract.cjs --check "${mock_server}")" || exit
run_id="javascript-$(date -u +%Y%m%dT%H%M%SZ)-$$"
out="test-results/mock-contract-${run_id}"
ruby -rbundler -e 'Bundler.with_original_env { exec(RbConfig.ruby, *ARGV) }' -- \
"${mock_server}/with-scenario.rb" --scenario folder-list --out "${out}" --run-id "${run_id}" \
--schema-sha256 "${schema_sha256}" --startup-timeout 30 --consumer-timeout 60 --settle-timeout 5 \
-- "$(command -v node)" "${PWD}/test/mock-contract.cjs"
status=$?
# The run's record goes to the log as well, since a failed job's artifacts may not be kept: run.json, and, after a
# failure, the end of the server's own output, server.log, which says why a server that was never ready stopped.
echo "The Mock contract test ended with status ${status}; its evidence is in ${PWD}/${out}"
if [[ -f "${out}/run.json" ]]; then
cat "${out}/run.json"
fi
if [[ "${status}" -ne 0 && -f "${out}/server.log" ]]; then
echo "The last 200 lines of the Mock server's log, ${PWD}/${out}/server.log:"
tail -n 200 "${out}/server.log"
fi
# A failed contract test ends this script with its status, before the canonical namespace case runs.
if [[ "${status}" -ne 0 ]]; then
exit "${status}"
fi
# The canonical namespace case, test/scenarios/namespace.cjs, rendered from the shared API scenarios
# (verification/scenarios/api.json), runs the files.owned-folder-namespace scenario through this SDK against a new
# server of the same Mock, loaded with its api-scenarios-canonical preset, through the same with-scenario.rb in
# Bundler's original environment. It checks that the Mock in the directory it is given was generated from this SDK's
# Swagger document, and keeps its evidence in a directory of its own under test-results/: the launcher's records and
# the case's own receipt, javascript-namespace-case.json. The case allows itself 180 s, and 30 s more to remove what
# it created after a failure, so the launcher allows it 210 s.
mock_server_dir="$(cd "${mock_server}" && pwd)" || exit
namespace_run_id="javascript-namespace-$(date -u +%Y%m%dT%H%M%SZ)-$$"
namespace_out="test-results/mock-namespace-${namespace_run_id}"
ruby -rbundler -e 'Bundler.with_original_env { exec(RbConfig.ruby, *ARGV) }' -- \
"${mock_server}/with-scenario.rb" --scenario api-scenarios-canonical --out "${namespace_out}" \
--run-id "${namespace_run_id}" --schema-sha256 "${schema_sha256}" --startup-timeout 30 --consumer-timeout 210 \
--settle-timeout 5 -- "$(command -v node)" "${PWD}/test/scenarios/namespace.cjs" "${mock_server_dir}"
namespace_status=$?
echo "The canonical namespace case ended with status ${namespace_status}; its evidence is in ${PWD}/${namespace_out}"
if [[ -f "${namespace_out}/run.json" ]]; then
cat "${namespace_out}/run.json"
fi
if [[ -f "${namespace_out}/javascript-namespace-case.json" ]]; then
cat "${namespace_out}/javascript-namespace-case.json"
fi
if [[ "${namespace_status}" -ne 0 && -f "${namespace_out}/server.log" ]]; then
echo "The last 200 lines of the Mock server's log, ${PWD}/${namespace_out}/server.log:"
tail -n 200 "${namespace_out}/server.log"
fi
# A failed namespace case ends this script with its status, before the file cases run.
if [[ "${namespace_status}" -ne 0 ]]; then
exit "${namespace_status}"
fi
# The canonical file cases, test/scenarios/file-scenarios.cjs, rendered from the same shared API scenarios, run its
# three scenarios of files and folders (files.owned-binary-roundtrip, files.owned-namespace-extended and
# files.owned-directory-helpers) one at a time. Each case gets a new server of the same Mock, with the same preset and
# launcher in Bundler's original environment, and is given the Mock's directory and its scenario's id. Each keeps its
# evidence in a directory of its own under test-results/, with its receipt, javascript-<scenario>-case.json. Each has
# the namespace case's budgets: 30 s for the server to be ready, 210 s for the case (180 s of work and 30 s more to
# remove what it created after a failure), and 5 s each time a process group is stopped. Their larger uploads send parts
# bigger than the 1 MiB request body a Mock server takes by default, so each server runs with FILES_MOCK_MAX_BODY_BYTES
# of 16 MiB unless another is set. The first case to fail ends this script with its status.
file_max_body_bytes="${FILES_MOCK_MAX_BODY_BYTES:-16777216}"
for file_scenario in files.owned-binary-roundtrip files.owned-namespace-extended files.owned-directory-helpers; do
# A run ID with-scenario.rb accepts is at most 64 letters, digits, dots, hyphens and underscores: the scenario's own
# part of its ID keeps it within that whatever the process ID.
file_run_id="javascript-${file_scenario#files.owned-}-$(date -u +%Y%m%dT%H%M%SZ)-$$"
file_out="test-results/mock-${file_run_id}"
FILES_MOCK_MAX_BODY_BYTES="${file_max_body_bytes}" ruby -rbundler -e 'Bundler.with_original_env { exec(RbConfig.ruby, *ARGV) }' -- \
"${mock_server}/with-scenario.rb" --scenario api-scenarios-canonical --out "${file_out}" \
--run-id "${file_run_id}" --schema-sha256 "${schema_sha256}" --startup-timeout 30 --consumer-timeout 210 \
--settle-timeout 5 -- "$(command -v node)" "${PWD}/test/scenarios/file-scenarios.cjs" "${mock_server_dir}" "${file_scenario}"
file_status=$?
echo "The canonical file case ${file_scenario} ended with status ${file_status}; its evidence is in ${PWD}/${file_out}"
if [[ -f "${file_out}/run.json" ]]; then
cat "${file_out}/run.json"
fi
if [[ -f "${file_out}/javascript-${file_scenario}-case.json" ]]; then
cat "${file_out}/javascript-${file_scenario}-case.json"
fi
if [[ "${file_status}" -ne 0 && -f "${file_out}/server.log" ]]; then
echo "The last 200 lines of the Mock server's log, ${PWD}/${file_out}/server.log:"
tail -n 200 "${file_out}/server.log"
fi
if [[ "${file_status}" -ne 0 ]]; then
exit "${file_status}"
fi
done
# The filesystem parity case, test/scenarios/filesystem-parity.cjs, runs the cases of the native reference
# (test/support/filesystem-parity.cjs), which the unit tests run against Node.js's own fs/promises, against both
# Node.js's own fs/promises and this SDK's client.fs on a new server of the same Mock, with the same preset and launcher
# in Bundler's original environment. client.fs reaches the Mock through Node.js's own fetch, and the cases' files and
# folders are made, and their bytes read back, by plain requests of the API, apart from the SDK. It is given the Mock's
# directory, checks that the Mock there was generated from this SDK's Swagger document, and keeps its evidence in a
# directory of its own under test-results/, with its receipt, javascript-filesystem-parity.json. It has the canonical
# cases' budgets: 30 s for the server to be ready, 210 s for the case (180 s of work and 30 s more to remove what it
# created) and 5 s each time a process group is stopped. Its failure, or a run that leaves no run.json or no receipt,
# ends this script with a nonzero status.
parity_run_id="javascript-filesystem-parity-$(date -u +%Y%m%dT%H%M%SZ)-$$"
parity_out="test-results/mock-${parity_run_id}"
ruby -rbundler -e 'Bundler.with_original_env { exec(RbConfig.ruby, *ARGV) }' -- \
"${mock_server}/with-scenario.rb" --scenario api-scenarios-canonical --out "${parity_out}" \
--run-id "${parity_run_id}" --schema-sha256 "${schema_sha256}" --startup-timeout 30 --consumer-timeout 210 \
--settle-timeout 5 -- "$(command -v node)" "${PWD}/test/scenarios/filesystem-parity.cjs" "${mock_server_dir}"
parity_status=$?
echo "The filesystem parity case ended with status ${parity_status}; its evidence is in ${PWD}/${parity_out}"
if [[ -f "${parity_out}/run.json" ]]; then
cat "${parity_out}/run.json"
fi
if [[ -f "${parity_out}/javascript-filesystem-parity.json" ]]; then
cat "${parity_out}/javascript-filesystem-parity.json"
fi
if [[ "${parity_status}" -ne 0 && -f "${parity_out}/server.log" ]]; then
echo "The last 200 lines of the Mock server's log, ${PWD}/${parity_out}/server.log:"
tail -n 200 "${parity_out}/server.log"
fi
if [[ "${parity_status}" -eq 0 && ( ! -f "${parity_out}/run.json" || ! -f "${parity_out}/javascript-filesystem-parity.json" ) ]]; then
echo "The filesystem parity case left no run.json or no javascript-filesystem-parity.json in ${PWD}/${parity_out}"
parity_status=1
fi
if [[ "${parity_status}" -ne 0 ]]; then
exit "${parity_status}"
fi
# The shared failure-case matrix, test/failure-cases.cjs, makes each case's calls of the Mock's failure-cases scenario
# (enum and date-time validation errors, a dropped connection retried, retries spent on dropped connections, and a
# seeded random sequence of HTTP 422 faults, which no SDK retries) through this SDK's User.find and User#update, on a
# new server of the same Mock, through the same
# launcher in Bundler's original environment. The launcher resets the server to the scenario's users, adds its fault
# rules, and passes only when the case's receipt, failure-cases.json, reports every case passed, once and in order,
# and the journal and the fault rules' decisions show exactly each case's expected attempts. Its evidence goes to a
# directory of its own under test-results/. It has 30 s for the server to be ready, 120 s for the cases and 5 s each
# time a process group is stopped.
failure_run_id="javascript-failure-cases-$(date -u +%Y%m%dT%H%M%SZ)-$$"
failure_out="test-results/mock-${failure_run_id}"
ruby -rbundler -e 'Bundler.with_original_env { exec(RbConfig.ruby, *ARGV) }' -- \
"${mock_server}/with-scenario.rb" --scenario failure-cases --out "${failure_out}" \
--run-id "${failure_run_id}" --schema-sha256 "${schema_sha256}" --startup-timeout 30 --consumer-timeout 120 \
--settle-timeout 5 --failure-variant sdk-network-retries -- "$(command -v node)" "${PWD}/test/failure-cases.cjs"
failure_status=$?
echo "The failure cases ended with status ${failure_status}; their evidence is in ${PWD}/${failure_out}"
for record in run.json failure-cases.json; do
if [[ -f "${failure_out}/${record}" ]]; then
cat "${failure_out}/${record}"
fi
done
if [[ "${failure_status}" -ne 0 && -f "${failure_out}/server.log" ]]; then
echo "The last 200 lines of the Mock server's log, ${PWD}/${failure_out}/server.log:"
tail -n 200 "${failure_out}/server.log"
fi
if [[ "${failure_status}" -ne 0 ]]; then
exit "${failure_status}"
fi
exit 0