@suffolklitlab/alkiln 5.10.4 ā 5.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/github_server.yml +45 -23
- package/.github/workflows/log_code_tests.yml +27 -0
- package/.github/workflows/playground.yml +38 -19
- package/.github/workflows/unit_tests.yml +2 -2
- package/CHANGELOG.md +30 -0
- package/action.yml +31 -54
- package/action_for_github_server/action.yml +61 -67
- package/lib/cucumber_8_shim.js +2 -1
- package/lib/docassemble/docassemble_api_REST.js +2 -2
- package/lib/docassemble/docassemble_api_interface.js +12 -8
- package/lib/docassemble/server_install.js +3 -2
- package/lib/docassemble/setup.js +5 -3
- package/lib/docassemble/takedown.js +4 -4
- package/lib/run_cucumber.js +21 -13
- package/lib/scope.js +123 -74
- package/lib/steps.js +82 -162
- package/lib/utils/log.js +56 -33
- package/lib/utils/reports.js +77 -20
- package/lib/utils/session_vars.js +12 -19
- package/package.json +4 -3
- package/tests/log_codes/check_codes.sh +138 -0
- package/tests/log_codes/deleted_codes.json +8 -0
package/lib/utils/reports.js
CHANGED
|
@@ -11,7 +11,7 @@ reports.addReportHeading = function (scope, { scenario }) {
|
|
|
11
11
|
/** Return printable heading based on Scenario name and tags.
|
|
12
12
|
* Allow characters from other languages.
|
|
13
13
|
*/
|
|
14
|
-
if ( session_vars.get_debug() ) { console.log(
|
|
14
|
+
if ( session_vars.get_debug() ) { console.log(`š ALK0175 INFO: reports.addReportHeading(): ${scenario.pickle.name} \n`); }
|
|
15
15
|
|
|
16
16
|
// Collect all tag names
|
|
17
17
|
let tag_names = [];
|
|
@@ -29,36 +29,48 @@ reports.addReportHeading = function (scope, { scenario }) {
|
|
|
29
29
|
heading += `\n---------------`;
|
|
30
30
|
|
|
31
31
|
reports.addToReport( scope, {
|
|
32
|
-
|
|
32
|
+
code: `ALK0176`,
|
|
33
|
+
type: `heading info`,
|
|
33
34
|
value: heading,
|
|
34
35
|
});
|
|
35
36
|
}; // Ends reports.addReportHeading()
|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
// TODO: Maybe return line so it can be used in error messages, etc.
|
|
39
|
+
reports.addToReport = function( scope, { type, code, value }) {
|
|
38
40
|
/** Add an item to a specific list in a scenario's report.
|
|
39
41
|
* Create report if necessary.
|
|
40
42
|
*
|
|
41
43
|
* The report has a key for each scenario and each of those
|
|
42
|
-
* keys should correspond to a list containing the relevant data.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
* keys should correspond to a list containing the relevant data.
|
|
45
|
+
*
|
|
46
|
+
* @params code {string} (Optional) Error or warning code. Default
|
|
47
|
+
* is unspecified error or warning.
|
|
48
|
+
* */
|
|
49
|
+
// Debugging logs
|
|
50
|
+
let debug_line = getDebugLine({ type, code, value });
|
|
51
|
+
if ( session_vars.get_debug() ) {
|
|
52
|
+
console.log( `Report: ${ debug_line }` );
|
|
53
|
+
}
|
|
46
54
|
|
|
55
|
+
// Ensure default file path for saving internal unit test logs
|
|
47
56
|
const MISC_ARTIFACTS_DIR = `_alkiln-misc_artifacts`;
|
|
48
|
-
// Ensure filepath for saving local unit test logs
|
|
49
57
|
if ( !scope.paths ) {
|
|
50
|
-
// TODO: would it be useful to put in existing artifacts folder if possible.
|
|
51
58
|
// Can this be usefully abstracted?
|
|
52
59
|
scope.paths = { debug_log: `${ MISC_ARTIFACTS_DIR }/unit_tests_logs-${ files.readable_date() }.txt` };
|
|
53
60
|
}
|
|
54
61
|
|
|
55
62
|
try {
|
|
56
|
-
fs.appendFileSync(scope.paths.debug_log, `\nReport:\
|
|
57
|
-
} catch (err) {
|
|
63
|
+
fs.appendFileSync( scope.paths.debug_log, `\nReport:\n${debug_line}` );
|
|
64
|
+
} catch ( err ) {
|
|
58
65
|
fs.mkdirSync( MISC_ARTIFACTS_DIR );
|
|
59
|
-
fs.appendFileSync(scope.paths.debug_log, `\nReport:\
|
|
66
|
+
fs.appendFileSync( scope.paths.debug_log, `\nReport:\n${debug_line}` );
|
|
67
|
+
// An error in here should throw (for now)
|
|
60
68
|
}
|
|
61
69
|
|
|
70
|
+
// Report stuff
|
|
71
|
+
let scenario = makeSureReportPartsExist( scope );
|
|
72
|
+
scenario.lines.push({ type, code, value });
|
|
73
|
+
|
|
62
74
|
return scenario;
|
|
63
75
|
}; // Ends reports.addToReport()
|
|
64
76
|
|
|
@@ -125,9 +137,9 @@ reports.getPrintableReport = function( scope ) {
|
|
|
125
137
|
else { other_reports += report; }
|
|
126
138
|
}; // ends for every scenario
|
|
127
139
|
|
|
128
|
-
if ( failed_reports !== `` ) { report += `\n\n===============================\n===============================\
|
|
129
|
-
if ( other_reports !== `` ) { report += `\n\n===============================\n===============================\
|
|
130
|
-
if ( passed_reports !== `` ) { report += `\n\n===============================\n===============================\
|
|
140
|
+
if ( failed_reports !== `` ) { report += `\n\n===============================\n===============================\nš¤ Failed scenarios:\n${ failed_reports }`; }
|
|
141
|
+
if ( other_reports !== `` ) { report += `\n\n===============================\n===============================\nš Scenarios that did not pass:\n${ other_reports }`; }
|
|
142
|
+
if ( passed_reports !== `` ) { report += `\n\n===============================\n===============================\nš Passed scenarios:\n${ passed_reports }`; }
|
|
131
143
|
|
|
132
144
|
return report;
|
|
133
145
|
}; // Ends reports.getPrintableReport()
|
|
@@ -137,11 +149,56 @@ reports.getPrintableScenario = function( scenario ) {
|
|
|
137
149
|
let [ scenario_id, data ] = scenario;
|
|
138
150
|
let report = ``;
|
|
139
151
|
for ( let line of data.lines ) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
else if ( line.type === `warning` ) { report += `WARNING: `; }
|
|
143
|
-
else if ( line.type === `error` ) { report += `\nERROR: ` }
|
|
144
|
-
report += `${ line.value }\n`;
|
|
152
|
+
let { type, code, value } = line;
|
|
153
|
+
report += `${ getLineText({ type, code, value }) }\n`;
|
|
145
154
|
}
|
|
146
155
|
return report;
|
|
147
156
|
}; // Ends reports.getPrintableScenario()
|
|
157
|
+
|
|
158
|
+
let getLineText = function ({ type=`no type`, code=`ALK0000`, value=`` }) {
|
|
159
|
+
let start = ``;
|
|
160
|
+
if ( type.includes(`page_id`) ) { start += `screen id: `; }
|
|
161
|
+
else if ( type.includes(`outcome`) ) { start += `\n`; } // extra new line
|
|
162
|
+
else if ( type.includes(`warning`) ) { start += `š ${ code } WARNING: `; }
|
|
163
|
+
else if ( type.includes(`error`) ) { start += `\nš¤ ${ code } ERROR: `; } // extra new line
|
|
164
|
+
return `${ start }${ value }`;
|
|
165
|
+
}; // Ends getLine()
|
|
166
|
+
|
|
167
|
+
let getDebugLine = function ({ type=``, code=`ALK0000`, value=`` }) {
|
|
168
|
+
/** In debug log lines, include all the information possible. */
|
|
169
|
+
|
|
170
|
+
// `plain` is usually used for visual clarity and shouldn't have
|
|
171
|
+
// codes and such associated with it. Return right away.
|
|
172
|
+
if ( type.includes(`plain`) ) { return value; }
|
|
173
|
+
|
|
174
|
+
let start = ``;
|
|
175
|
+
|
|
176
|
+
// Get all the relevant emoji
|
|
177
|
+
if ( type.includes(`debug`) ) { start += `š`; }
|
|
178
|
+
if ( type.includes(`info`) ) { start += `š”`; }
|
|
179
|
+
if ( type.includes(`success`) ) { start += `š`; }
|
|
180
|
+
if ( type.includes(`warning`) ) { start += `š`; }
|
|
181
|
+
if ( type.includes(`error`) ) { start += `š¤`; }
|
|
182
|
+
// Default
|
|
183
|
+
if ( start === `` ) { start += `?`; }
|
|
184
|
+
|
|
185
|
+
start += ` ${ code }`;
|
|
186
|
+
|
|
187
|
+
// TODO: This doesn't take care
|
|
188
|
+
let extra_types = type.replace(/debug|info|success|warning|error/i, ``).replace(/ +/g, ' ').trim();
|
|
189
|
+
if ( extra_types.length > 0 ) { start += ` ${ extra_types } `; }
|
|
190
|
+
|
|
191
|
+
// Get all the relevant descriptive text
|
|
192
|
+
let description_parts = [];
|
|
193
|
+
if ( type.includes(`debug`) ) { description_parts.push( `DEBUG` ); }
|
|
194
|
+
if ( type.includes(`info`) ) { description_parts.push( `INFO` ); }
|
|
195
|
+
if ( type.includes(`success`) ) { description_parts.push( `SUCCESS` ); }
|
|
196
|
+
if ( type.includes(`warning`) ) { description_parts.push( `WARNING` ); }
|
|
197
|
+
if ( type.includes(`error`) ) { description_parts.push( `ERROR` ); }
|
|
198
|
+
// Default
|
|
199
|
+
if ( description_parts.length <= 0 ) { description_parts.push( `UNKNOWN` ); }
|
|
200
|
+
|
|
201
|
+
start = [ start, ...description_parts ].join(` `);
|
|
202
|
+
|
|
203
|
+
return `${ start }: ${ value }`;
|
|
204
|
+
}; // Ends getLine()
|
|
@@ -120,7 +120,7 @@ session_vars.save_project_name = function ( project_name ) {
|
|
|
120
120
|
// Warn local developers if file already exists
|
|
121
121
|
if ( fs.existsSync( runtime_config_path ) ) {
|
|
122
122
|
let old_project_name = session_vars.get_project_name();
|
|
123
|
-
let session_project_already_exists_msg =
|
|
123
|
+
let session_project_already_exists_msg = `š ALK0035 WARNING: `
|
|
124
124
|
+ `This session had a project name already: ${ old_project_name }. `
|
|
125
125
|
+ `A new project has now been created called ${ project_name }. `
|
|
126
126
|
+ `Remember to delete ${ old_project_name }`;
|
|
@@ -136,7 +136,7 @@ session_vars.save_project_name = function ( project_name ) {
|
|
|
136
136
|
let file = fs.writeFileSync( runtime_config_path, JSON.stringify( json, null, 2 ) );
|
|
137
137
|
|
|
138
138
|
if ( session_vars.get_debug() ) {
|
|
139
|
-
console.log(
|
|
139
|
+
console.log( `š ALK0036 DEBUG: Stored name of Project "${ project_name }" locally.` );
|
|
140
140
|
}
|
|
141
141
|
return file;
|
|
142
142
|
}; // Ends save_project_name()
|
|
@@ -148,7 +148,7 @@ session_vars.get_project_name = function () {
|
|
|
148
148
|
}
|
|
149
149
|
let json = JSON.parse( fs.readFileSync( runtime_config_path ));
|
|
150
150
|
let project_name = json[ project_name_key ] || null;
|
|
151
|
-
if ( session_vars.get_debug() ) { console.log(
|
|
151
|
+
if ( session_vars.get_debug() ) { console.log( `š ALK0037 DEBUG: Project name from file is "${ project_name }".` ); }
|
|
152
152
|
return project_name;
|
|
153
153
|
}; // Ends get_project_name()
|
|
154
154
|
|
|
@@ -158,11 +158,11 @@ session_vars.delete_project_name = function () {
|
|
|
158
158
|
// Get the json, changing it, and re-write the file from scratch
|
|
159
159
|
let json = JSON.parse( fs.readFileSync( runtime_config_path ));
|
|
160
160
|
json[ project_name_key ] = ``;
|
|
161
|
-
console.log(
|
|
161
|
+
console.log( `š” ALK0038 INFO: Deleted the data that stored the name of the Project.` );
|
|
162
162
|
fs.writeFileSync( runtime_config_path, JSON.stringify( json, null, 2 ) );
|
|
163
163
|
return true;
|
|
164
164
|
} catch ( error ) {
|
|
165
|
-
console.warn(
|
|
165
|
+
console.warn( `š ALK0039 WARNING: Could not delete the Project name data. Error: ${ error }.` );
|
|
166
166
|
return false;
|
|
167
167
|
}
|
|
168
168
|
};
|
|
@@ -226,7 +226,7 @@ session_vars.save_runtime_config_var = function ({ key, value }) {
|
|
|
226
226
|
let file = fs.writeFileSync( runtime_config_path, JSON.stringify( json, null, 2 ) );
|
|
227
227
|
|
|
228
228
|
if ( session_vars.get_debug() ) {
|
|
229
|
-
console.log(
|
|
229
|
+
console.log( `š ALK0040 DEBUG: Stored runtime config var "${key}" locally as "${value}".` );
|
|
230
230
|
}
|
|
231
231
|
return file;
|
|
232
232
|
}; // Ends session_vars.save_runtime_config_var()
|
|
@@ -242,7 +242,7 @@ session_vars.get_runtime_config_var = function ( key ) {
|
|
|
242
242
|
let json = JSON.parse( fs.readFileSync( runtime_config_path ));
|
|
243
243
|
let value = json[ key ];
|
|
244
244
|
if ( session_vars.get_debug() ) {
|
|
245
|
-
console.log(
|
|
245
|
+
console.log( `š ALK0041 DEBUG: Runtime config var "${key}"" is "${value}".` );
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
return value;
|
|
@@ -280,13 +280,6 @@ session_vars.set_sources_paths = function ( paths ) {
|
|
|
280
280
|
}
|
|
281
281
|
}
|
|
282
282
|
|
|
283
|
-
// Warn about missing paths
|
|
284
|
-
if ( missing_paths.length > 0 ) {
|
|
285
|
-
console.warn(
|
|
286
|
-
`ALKiln WARNING: ALKiln can't find folders at "${ paths.join('", "') }".`
|
|
287
|
-
);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
283
|
// If no paths were valid
|
|
291
284
|
if ( existing_paths.length <= 0 ) {
|
|
292
285
|
session_vars._sources_paths = null;
|
|
@@ -294,7 +287,7 @@ session_vars.set_sources_paths = function ( paths ) {
|
|
|
294
287
|
}
|
|
295
288
|
|
|
296
289
|
console.info(
|
|
297
|
-
|
|
290
|
+
`š ALK0042 SUCCESS: Did find "sources" file(s) at "${ existing_paths.join('", "') }".`
|
|
298
291
|
)
|
|
299
292
|
|
|
300
293
|
// Otherwise, store valid paths
|
|
@@ -334,7 +327,7 @@ session_vars.validateEnvironment = function() {
|
|
|
334
327
|
|
|
335
328
|
let origin = session_vars.get_origin();
|
|
336
329
|
if ( origin !== 'github' && origin !== 'local' && origin !== 'playground' ) {
|
|
337
|
-
errorMessage += `\nThe _ORIGIN environment variable should be set to a valid value automatically. If you see this error, file an issue at https://github.com/
|
|
330
|
+
errorMessage += `\nThe _ORIGIN environment variable should be set to a valid value automatically. If you see this error, file an issue at https://github.com/SuffolkLITLab/docassemble-ALKilnInThePlayground. It must be defined as either 'playground', 'github', or 'local', but its value was ${origin}`;
|
|
338
331
|
|
|
339
332
|
// If origin has one of the allowed values, we can do the rest of the validations
|
|
340
333
|
} else {
|
|
@@ -358,10 +351,10 @@ session_vars.validateEnvironment = function() {
|
|
|
358
351
|
// We're the ones ensuring these exist for Playground runs
|
|
359
352
|
if ( origin === 'playground' ) {
|
|
360
353
|
if ( !session_vars.get_user_project_name() ) {
|
|
361
|
-
errorMessage += `\nThe _PROJECT_NAME environment variable should automatically exist. If you see this error, file an issue at https://github.com/
|
|
354
|
+
errorMessage += `\nThe _PROJECT_NAME environment variable should automatically exist. If you see this error, file an issue at https://github.com/SuffolkLITLab/docassemble-ALKilnInThePlayground. It is the name of the Project the developer chose to test.`
|
|
362
355
|
}
|
|
363
356
|
if ( !session_vars.get_user_id() ) {
|
|
364
|
-
errorMessage += `\nThe _USER_ID environment variable should automatically exist. If you see this error, file an issue at https://github.com/
|
|
357
|
+
errorMessage += `\nThe _USER_ID environment variable should automatically exist. If you see this error, file an issue at https://github.com/SuffolkLITLab/docassemble-ALKilnInThePlayground. It is the user ID of the developer on the server.`
|
|
365
358
|
}
|
|
366
359
|
// Tags are optional
|
|
367
360
|
} // ends Playground env vars
|
|
@@ -371,6 +364,6 @@ session_vars.validateEnvironment = function() {
|
|
|
371
364
|
errorMessage = errorMessage.trim();
|
|
372
365
|
|
|
373
366
|
if (errorMessage !== '') {
|
|
374
|
-
throw new ReferenceError(
|
|
367
|
+
throw new ReferenceError(`š¤ ALK0043 ERROR:\n${errorMessage}`);
|
|
375
368
|
}
|
|
376
369
|
};
|
package/package.json
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suffolklitlab/alkiln",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.11.1",
|
|
4
4
|
"description": "Integrated automated end-to-end testing with docassemble, puppeteer, and cucumber.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"test": "npm run unit && npm run cucumber",
|
|
7
|
+
"test": "npm run unit && npm run codes && npm run cucumber",
|
|
8
8
|
"cucumber": "./lib/run_cucumber.js",
|
|
9
9
|
"local": "npm run setup && npm run cucumber; npm run takedown",
|
|
10
10
|
"setup": "./lib/docassemble/setup.js",
|
|
11
11
|
"takedown": "./lib/docassemble/takedown.js",
|
|
12
12
|
"server_install": "./lib/docassemble/server_install.js",
|
|
13
|
-
"unit": "mocha tests/unit_tests/*.test.*"
|
|
13
|
+
"unit": "mocha tests/unit_tests/*.test.*",
|
|
14
|
+
"codes": "tests/log_codes/check_codes.sh ."
|
|
14
15
|
},
|
|
15
16
|
"repository": {
|
|
16
17
|
"type": "git",
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Identify missing and duplicate message code issues
|
|
4
|
+
|
|
5
|
+
exit_code=0
|
|
6
|
+
|
|
7
|
+
# Check if the caller sent an argument to the script
|
|
8
|
+
if [ $# -eq 0 ]; then
|
|
9
|
+
# If there was no argument, set a default value
|
|
10
|
+
directory="../.."
|
|
11
|
+
else
|
|
12
|
+
# If there was an argument, use it
|
|
13
|
+
directory="$1"
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
# The grepped files will include the list of all the codes that have been
|
|
17
|
+
# removed and are no longer used. Syntax used works with GitHub cli ([[:digit:]])
|
|
18
|
+
# https://stackoverflow.com/a/6901221
|
|
19
|
+
lines=$(grep -roh --exclude="tests/log_codes/check_codes.sh" --exclude="debug_log.txt" --exclude-dir="node_modules" --exclude-dir='alkiln-*' --exclude-dir='_alkiln*' 'ALK[[:digit:]][[:digit:]][[:digit:]][[:digit:]]' "$directory")
|
|
20
|
+
sorted=$(echo "$lines" | sort -n)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
echo "=== Missing codes ==="
|
|
24
|
+
|
|
25
|
+
# # -- Version 1 --
|
|
26
|
+
# # More understandable version that doesn't yet come out with a final variable
|
|
27
|
+
# # Keeping it here for discussion
|
|
28
|
+
# nums=$(echo "$sorted" | sed 's/^ALK0*//')
|
|
29
|
+
|
|
30
|
+
# missing_numbers=()
|
|
31
|
+
# prev_number=0
|
|
32
|
+
# echo "$nums" | while read -r current_number; do
|
|
33
|
+
|
|
34
|
+
# diff=$((current_number - prev_number))
|
|
35
|
+
# # If the difference is more than 1, print the missing
|
|
36
|
+
# # numbers until we catch up with the current number
|
|
37
|
+
# if [ $diff -gt 1 ]; then
|
|
38
|
+
# for ((i=prev_number+1; i<current_number; i++)); do
|
|
39
|
+
# printf -v missing_number "ALK%04d" $i
|
|
40
|
+
# missing_numbers+=("$missing_number")
|
|
41
|
+
# echo $missing_number
|
|
42
|
+
# # missing_numbers+=$(echo "%04d\n" $missing_number)
|
|
43
|
+
# done
|
|
44
|
+
# echo "---"
|
|
45
|
+
# fi
|
|
46
|
+
|
|
47
|
+
# prev_number=$current_number
|
|
48
|
+
|
|
49
|
+
# done
|
|
50
|
+
|
|
51
|
+
# missing_numbers_str=$(printf '%s' "${missing_numbers[@]}")
|
|
52
|
+
# echo "missing: $missing_numbers_str"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# -- Version 2 --
|
|
56
|
+
# Version that is opaque, but generates a variable to check at the end
|
|
57
|
+
|
|
58
|
+
# 0's in front of numbers confuses bash about the number format. Remove them.
|
|
59
|
+
just_numbers=$(echo "$sorted" | sed 's/^ALK0*//')
|
|
60
|
+
|
|
61
|
+
# Convert the list into an array
|
|
62
|
+
IFS=$'\n' read -rd '' -a num_array <<<"$just_numbers"
|
|
63
|
+
# Find the minimum and maximum numbers in the array
|
|
64
|
+
min_num=$(printf "%s\n" "${num_array[@]}" | sort -n | head -n 1)
|
|
65
|
+
max_num=$(printf "%s\n" "${num_array[@]}" | sort -n | tail -n 1)
|
|
66
|
+
|
|
67
|
+
# Generate a sequence of numbers from min to max with leading zeros
|
|
68
|
+
expected_sequence=""
|
|
69
|
+
for ((i=min_num; i<=max_num; i++)); do
|
|
70
|
+
# Make sure these won't look like numbers to avoid confusing bash
|
|
71
|
+
expected_sequence+=$(printf "ALK%04d" $i)$'\n'
|
|
72
|
+
done
|
|
73
|
+
# # Alternative code for above. seq doesn't exist everywhere. Keep this
|
|
74
|
+
# till we look up installing seq to avoid loop)
|
|
75
|
+
# expected_sequence=$(printf "ALK%04d\n" $(seq $min_num $max_num))
|
|
76
|
+
|
|
77
|
+
# Compare the expected sequence with the actual numbers
|
|
78
|
+
missing_numbers=$(comm -23 <(printf "%s\n" "$expected_sequence" | sort -n) <(printf "%s\n" "$sorted"))
|
|
79
|
+
if [ -z "$missing_numbers" ]; then
|
|
80
|
+
echo "None"
|
|
81
|
+
else
|
|
82
|
+
echo "$missing_numbers"
|
|
83
|
+
((exit_code+=2))
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
echo "
|
|
88
|
+
=== Duplicate codes ==="
|
|
89
|
+
|
|
90
|
+
# We know these duplicates are ok
|
|
91
|
+
accepted_duplicates="ALK0000
|
|
92
|
+
ALK0002
|
|
93
|
+
ALK0003
|
|
94
|
+
ALK0006
|
|
95
|
+
ALK0007
|
|
96
|
+
ALK0008
|
|
97
|
+
ALK0009
|
|
98
|
+
ALK0010
|
|
99
|
+
ALK0011
|
|
100
|
+
ALK0012
|
|
101
|
+
ALK0018
|
|
102
|
+
ALK0019
|
|
103
|
+
ALK0023
|
|
104
|
+
ALK0024
|
|
105
|
+
ALK0026
|
|
106
|
+
ALK0027
|
|
107
|
+
ALK0028
|
|
108
|
+
ALK0030
|
|
109
|
+
ALK0049"
|
|
110
|
+
|
|
111
|
+
# Use a sorted list. `uniq` only detects consecutive duplicates
|
|
112
|
+
duplicates=$(echo "$sorted" | uniq -d)
|
|
113
|
+
unaccepted_duplicates=$(echo "$duplicates" | grep -v -f <(echo "$accepted_duplicates"))
|
|
114
|
+
|
|
115
|
+
if [ -z "$unaccepted_duplicates" ]; then
|
|
116
|
+
echo "None"
|
|
117
|
+
else
|
|
118
|
+
echo "$unaccepted_duplicates"
|
|
119
|
+
((exit_code+=20))
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
# === Final messages ===
|
|
123
|
+
echo "
|
|
124
|
+
Exit code meanings:
|
|
125
|
+
- code 2: missing codes
|
|
126
|
+
- code 20: duplicate codes
|
|
127
|
+
- code 22: both
|
|
128
|
+
"
|
|
129
|
+
|
|
130
|
+
if test $exit_code -eq 0; then
|
|
131
|
+
echo "š Passed! The codes for logs are as they should be."
|
|
132
|
+
highest=$(echo "$sorted" | tail -n 1)
|
|
133
|
+
echo "The highest log code is $highest"
|
|
134
|
+
else
|
|
135
|
+
echo "š¤ ERROR: Log codes are messed up. Exited with exit code $exit_code. See above for more details."
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
exit $exit_code
|