diff --git a/README.md b/README.md index d50194f2..1b365154 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,8 @@ $ make demo * [GET alive](docs/api.md#get-alive) * [GET ready](docs/api.md#get-ready) * [GET sha](docs/api.md#get-sha) +* [GET diff_lines_files(was_files,now_files)](docs/api.md#get-diff_lines_fileswas_filesnow_files) +* [GET diff_summary_files(was_files,now_files)](docs/api.md#get-diff_summary_fileswas_filesnow_files) * [GET diff_lines(id,was_index,now_index)](docs/api.md#get-diff_linesidwas_indexnow_index) * [GET diff_summary(id,was_index,now_index)](docs/api.md#get-diff_summaryidwas_indexnow_index) diff --git a/bin/echo_env_vars.sh b/bin/echo_env_vars.sh index 48bc3c02..5ed6e790 100644 --- a/bin/echo_env_vars.sh +++ b/bin/echo_env_vars.sh @@ -28,6 +28,7 @@ echo_env_vars() # echo CYBER_DOJO_DIFFER_CLIENT_CONTAINER_NAME=test_differ_client echo CYBER_DOJO_DIFFER_SERVER_CONTAINER_NAME=test_differ_server + echo CYBER_DOJO_SAVER_CONTAINER_NAME=test_differ_saver # local -r AWS_ACCOUNT_ID=244531986313 local -r AWS_REGION=eu-central-1 diff --git a/bin/lib.sh b/bin/lib.sh index 7e329427..238f2fde 100644 --- a/bin/lib.sh +++ b/bin/lib.sh @@ -41,7 +41,7 @@ exit_non_zero() copy_in_saver_test_data() { - local -r SAVER_CID=$(docker ps --filter status=running --format '{{.Names}}' | grep "saver") + local -r SAVER_CID="${CYBER_DOJO_SAVER_CONTAINER_NAME}" local -r SRC_PATH=${ROOT_DIR}/test/server/data/cyber-dojo local -r DEST_PATH=/cyber-dojo # You cannot docker cp to a tmpfs, so tar-piping instead... diff --git a/docker-compose.yml b/docker-compose.yml index 606f9ab1..9077d3b3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -49,6 +49,7 @@ services: saver: image: ${CYBER_DOJO_SAVER_IMAGE}:${CYBER_DOJO_SAVER_TAG} + container_name: ${CYBER_DOJO_SAVER_CONTAINER_NAME} user: saver ports: [ "${CYBER_DOJO_SAVER_PORT}:${CYBER_DOJO_SAVER_PORT}" ] env_file: [ .env ] diff --git a/docs/api.md b/docs/api.md index 2cd850e2..7d7d8eb4 100644 --- a/docs/api.md +++ b/docs/api.md @@ -3,7 +3,7 @@ - - - - ## GET diff_lines(id,was_index,now_index) A diff of two sets of files (designated with **was_index** and **now_index**) from the kata designated with **id**. -Also includes unchanged files and the content of files renamed but with identical content. +Also handles unchanged files and files renamed but with identical content. - parameters * **id:String** the id of the kata. * **was_index:Integer** the test-submission index of the first set of files. @@ -108,6 +108,139 @@ Also includes unchanged files and the content of files renamed but with identica ] ``` +- - - - +## GET diff_lines_files(was_files,now_files) +A diff of two sets of files supplied directly as parameters. +Also handles unchanged files and files renamed but with identical content. +- parameters + * **was_files:Hash** a Hash of filename to content Strings for the first set of files. + * **now_files:Hash** a Hash of filename to content Strings for the second set of files. + * eg + ```json + { + "was_files": { "hiker.h": "#ifndef HIKER_INCLUDED\n#define WIBBLE\n" }, + "now_files": { "hiker.h": "#ifndef HIKER_INCLUDED\n#define HIKER_INCLUDED\n" } + } + ``` +- returns an Array of Hashes with each Hash being the diff of a single file. Each Hash has the following keys: + * "type" - one of the Strings [ "created", "deleted", "renamed", "changed", "unchanged" ]. + * "old_filename" - the String name of the **was_files** file, unless "type" is "created" in which case **null**. + * "new_filename" - the String name of the **now_files** file, unless "type" is "deleted" in which case **null**. + * "lines" - an Array of Hashes, each Hash detailing an "added", "deleted", or "same" line, or + a "section" marker before a diff-chunk. + * "line_counts" - a Hash with three entries: + - "added" - the number of lines added to **now_files**'s "new_filename" file. + - "deleted" - the number of lines deleted from **was_files**'s "old_filename" file. + - "same" - the number of lines identical in both **now_files**'s "new_filename" and **was_files**'s "old_filename" file. + * + * eg a created file, which always has a single "section" marker. + ```json + [ + { + "type": "created", + "old_filename": null, + "new_filename": "the.created.filename", + "lines": + [ + { "type": "section", "index": 0 }, + { "type": "added", "line": "this file", "number": 1 }, + { "type": "added", "line": "is new", "number": 2 } + ], + "line_counts": { "added":2, "deleted":0, "same":0 } + } + , + ... + ] + ``` + * eg a deleted file, which always has a single "section" marker. + ```json + [ + { + "type": "deleted", + "old_filename": "the.deleted.filename", + "new_filename": null, + "lines": + [ + { "type": "section", "index": 0 }, + { "type": "deleted", "line": "this file", "number": 1 }, + { "type": "deleted", "line": "had 2 lines", "number": 2 } + ], + "line_counts": { "added":0, "deleted":2, "same":0 } + } + , + ... + ] + ``` + * eg a renamed file with identical content, which always has zero "section" markers. + ```json + [ + { + "type": "renamed", + "old_filename": "the.old.filename", + "new_filename": "the.new.filename", + "lines": + [ + { "type": "same", "line": "this file has", "number": 1 }, + { "type": "same", "line": "changed its name", "number": 2 } + { "type": "same", "line": "but not its contents", "number": 3 } + ], + "line_counts": { "added":0, "deleted":0, "same":3 } + } + , + ... + ] + ``` + * eg a changed file with two diff-chunks. + ```json + [ + { + "type": "changed", + "old_filename": "hiker.h", + "new_filename": "hiker.h", + "lines": + [ + { "type": "same", "line": "#ifndef HIKER_INCLUDED", "number": 1 }, + { "type": "section", "index": 0 }, + { "type": "deleted", "line": "#define WIBBLE", "number": 2 }, + { "type": "added", "line": "#define HIKER_INCLUDED", "number": 2 }, + { "type": "same", "line": "", "number": 3 }, + { "type": "section", "index": 1 }, + { "type": "deleted", "line": "struct wibble", "number": 3 }, + { "type": "added", "line": "struct hiker", "number": 3 }, + { "type": "same", "line": "{", "number": 4 }, + { "type": "same", "line": "};", "number": 5 }, + { "type": "same", "line": "#endif", "number": 6 }, + ], + "line_counts": { "added":2, "deleted":2, "same":5 } + } + , + ... + ] + ``` + +- - - - +## GET diff_summary_files(was_files,now_files) +A diff of two sets of files supplied directly as parameters. +Also handles unchanged files and files renamed but with identical content. +- parameters + * **was_files:Hash** a Hash of filename to content Strings for the first set of files. + * **now_files:Hash** a Hash of filename to content Strings for the second set of files. + * eg + ```json + { + "was_files": { "hiker.h": "#ifndef HIKER_INCLUDED\n#define WIBBLE\n" }, + "now_files": { "hiker.h": "#ifndef HIKER_INCLUDED\n#define HIKER_INCLUDED\n" } + } + ``` +- returns an Array of Hashes with each Hash being the diff of a single file. Each Hash has the following keys: + * "type" - one of the Strings [ "created", "deleted", "renamed", "changed", "unchanged" ]. + * "old_filename" - the String name of the **was_files** file, unless "type" is "created" in which case **null**. + * "new_filename" - the String name of the **now_files** file, unless "type" is "deleted" in which case **null**. + * "line_counts" - a Hash with three entries: + - "added" - the number of lines added to **now_files**'s "new_filename" file. + - "deleted" - the number of lines deleted from **was_files**'s "old_filename" file. + - "same" - the number of lines identical in both **now_files**'s "new_filename" and **was_files**'s "old_filename" file. + - - - - ## GET diff_summary(id,was_index,now_index) The same as `diff_lines` except its Hash entries do *not* include "lines". diff --git a/source/server/app.rb b/source/server/app.rb index b373604b..7ff4a278 100644 --- a/source/server/app.rb +++ b/source/server/app.rb @@ -7,6 +7,8 @@ class App < AppBase get_json(:ready, Prober) get_json(:sha, Prober) - get_json(:diff_lines, Differ) - get_json(:diff_summary, Differ) + get_json(:diff_lines, Differ) + get_json(:diff_summary, Differ) + get_json(:diff_lines_files, Differ) + get_json(:diff_summary_files, Differ) end diff --git a/test/client/lib/id58_test_base.rb b/test/client/lib/id58_test_base.rb index 01ba0f08..46bd91ac 100644 --- a/test/client/lib/id58_test_base.rb +++ b/test/client/lib/id58_test_base.rb @@ -1,8 +1,11 @@ require 'English' +require 'etc' require 'minitest/autorun' require 'minitest/reporters' require_relative 'slim_json_reporter' +Minitest.parallel_executor = Minitest::Parallel::Executor.new(Etc.nprocessors) + reporters = [ Minitest::Reporters::DefaultReporter.new, Minitest::Reporters::SlimJsonReporter.new, @@ -21,9 +24,12 @@ def initialize(arg) super end + parallelize_me! + @@args = (ARGV.sort.uniq - ['--']) # eg 2m4 @@seen_ids = [] @@timings = {} + TIMINGS_LOCK = Mutex.new def self.test(id58, *lines, &test_block) src = test_block.source_location @@ -34,7 +40,6 @@ def self.test(id58, *lines, &test_block) name58 = lines.join(' ') execute_around = lambda { - ENV['ID58'] = id58 @_id58 = id58 @_name58 = name58 id58_setup @@ -42,7 +47,7 @@ def self.test(id58, *lines, &test_block) t1 = Time.now instance_eval(&test_block) t2 = Time.now - @@timings["#{id58}:#{src_file}:#{src_line}:#{name58}"] = (t2 - t1) + TIMINGS_LOCK.synchronize { @@timings["#{id58}:#{src_file}:#{src_line}:#{name58}"] = (t2 - t1) } ensure puts $ERROR_INFO.message unless $ERROR_INFO.nil? id58_teardown diff --git a/test/client/lib/run.sh b/test/client/lib/run.sh index 8bb6e878..75d5b065 100755 --- a/test/client/lib/run.sh +++ b/test/client/lib/run.sh @@ -10,6 +10,7 @@ readonly TEST_FILES=(${MY_DIR}/../*_test.rb) readonly TEST_ARGS=(${@}) readonly SCRIPT=" +\$stdout.sync = true require '${MY_DIR}/coverage.rb' %w(${TEST_FILES[*]}).shuffle.each{ |file| require file diff --git a/test/server/lib/id58_test_base.rb b/test/server/lib/id58_test_base.rb index 01ba0f08..46bd91ac 100644 --- a/test/server/lib/id58_test_base.rb +++ b/test/server/lib/id58_test_base.rb @@ -1,8 +1,11 @@ require 'English' +require 'etc' require 'minitest/autorun' require 'minitest/reporters' require_relative 'slim_json_reporter' +Minitest.parallel_executor = Minitest::Parallel::Executor.new(Etc.nprocessors) + reporters = [ Minitest::Reporters::DefaultReporter.new, Minitest::Reporters::SlimJsonReporter.new, @@ -21,9 +24,12 @@ def initialize(arg) super end + parallelize_me! + @@args = (ARGV.sort.uniq - ['--']) # eg 2m4 @@seen_ids = [] @@timings = {} + TIMINGS_LOCK = Mutex.new def self.test(id58, *lines, &test_block) src = test_block.source_location @@ -34,7 +40,6 @@ def self.test(id58, *lines, &test_block) name58 = lines.join(' ') execute_around = lambda { - ENV['ID58'] = id58 @_id58 = id58 @_name58 = name58 id58_setup @@ -42,7 +47,7 @@ def self.test(id58, *lines, &test_block) t1 = Time.now instance_eval(&test_block) t2 = Time.now - @@timings["#{id58}:#{src_file}:#{src_line}:#{name58}"] = (t2 - t1) + TIMINGS_LOCK.synchronize { @@timings["#{id58}:#{src_file}:#{src_line}:#{name58}"] = (t2 - t1) } ensure puts $ERROR_INFO.message unless $ERROR_INFO.nil? id58_teardown diff --git a/test/server/lib/run.sh b/test/server/lib/run.sh index 8bb6e878..75d5b065 100755 --- a/test/server/lib/run.sh +++ b/test/server/lib/run.sh @@ -10,6 +10,7 @@ readonly TEST_FILES=(${MY_DIR}/../*_test.rb) readonly TEST_ARGS=(${@}) readonly SCRIPT=" +\$stdout.sync = true require '${MY_DIR}/coverage.rb' %w(${TEST_FILES[*]}).shuffle.each{ |file| require file