From 9523eb7407bd5a52549f5e2358da7a951348299d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20B=20Nagy?= <20251272+BNAndras@users.noreply.github.com> Date: Mon, 29 Apr 2024 21:28:55 -0700 Subject: [PATCH] Add allergies (#160) --- config.json | 8 + .../practice/allergies/.docs/instructions.md | 27 + .../practice/allergies/.meta/config.json | 19 + .../practice/allergies/.meta/example.red | 37 ++ exercises/practice/allergies/.meta/tests.toml | 160 ++++++ .../practice/allergies/allergies-test.red | 464 ++++++++++++++++++ exercises/practice/allergies/allergies.red | 18 + exercises/practice/allergies/testlib.red | 217 ++++++++ 8 files changed, 950 insertions(+) create mode 100644 exercises/practice/allergies/.docs/instructions.md create mode 100644 exercises/practice/allergies/.meta/config.json create mode 100644 exercises/practice/allergies/.meta/example.red create mode 100644 exercises/practice/allergies/.meta/tests.toml create mode 100644 exercises/practice/allergies/allergies-test.red create mode 100644 exercises/practice/allergies/allergies.red create mode 100644 exercises/practice/allergies/testlib.red diff --git a/config.json b/config.json index 1df7e8d..489424b 100644 --- a/config.json +++ b/config.json @@ -34,6 +34,14 @@ }, "exercises": { "practice": [ + { + "slug": "allergies", + "name": "Allergies", + "uuid": "62154622-ecd8-4443-be1a-5efb45c9b982", + "practices": [], + "prerequisites": [], + "difficulty": 2 + }, { "slug": "binary-search", "name": "Binary Search", diff --git a/exercises/practice/allergies/.docs/instructions.md b/exercises/practice/allergies/.docs/instructions.md new file mode 100644 index 0000000..daf8cfd --- /dev/null +++ b/exercises/practice/allergies/.docs/instructions.md @@ -0,0 +1,27 @@ +# Instructions + +Given a person's allergy score, determine whether or not they're allergic to a given item, and their full list of allergies. + +An allergy test produces a single numeric score which contains the information about all the allergies the person has (that they were tested for). + +The list of items (and their value) that were tested are: + +- eggs (1) +- peanuts (2) +- shellfish (4) +- strawberries (8) +- tomatoes (16) +- chocolate (32) +- pollen (64) +- cats (128) + +So if Tom is allergic to peanuts and chocolate, he gets a score of 34. + +Now, given just that score of 34, your program should be able to say: + +- Whether Tom is allergic to any one of those allergens listed above. +- All the allergens Tom is allergic to. + +Note: a given score may include allergens **not** listed above (i.e. allergens that score 256, 512, 1024, etc.). +Your program should ignore those components of the score. +For example, if the allergy score is 257, your program should only report the eggs (1) allergy. diff --git a/exercises/practice/allergies/.meta/config.json b/exercises/practice/allergies/.meta/config.json new file mode 100644 index 0000000..2a94bed --- /dev/null +++ b/exercises/practice/allergies/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "BNAndras" + ], + "files": { + "solution": [ + "allergies.red" + ], + "test": [ + "allergies-test.red" + ], + "example": [ + ".meta/example.red" + ] + }, + "blurb": "Given a person's allergy score, determine whether or not they're allergic to a given item, and their full list of allergies.", + "source": "Exercise by the JumpstartLab team for students at The Turing School of Software and Design.", + "source_url": "https://turing.edu" +} diff --git a/exercises/practice/allergies/.meta/example.red b/exercises/practice/allergies/.meta/example.red new file mode 100644 index 0000000..30aa797 --- /dev/null +++ b/exercises/practice/allergies/.meta/example.red @@ -0,0 +1,37 @@ +Red [ + description: {"Allergies" exercise solution for exercism platform} + author: "BNAndras" +] + +ALLERGIES: #[ + "eggs" 1 + "peanuts" 2 + "shellfish" 4 + "strawberries" 8 + "tomatoes" 16 + "chocolate" 32 + "pollen" 64 + "cats" 128 +] + + +allergic-to: function [ + item + score +] [ + 0 <> and~ score (select ALLERGIES item) +] + +list: function [ + score +] [ + results: copy [] + foreach [item value] ALLERGIES [ + if 0 <> and~ score value [ + append results item + ] + ] + + results +] + diff --git a/exercises/practice/allergies/.meta/tests.toml b/exercises/practice/allergies/.meta/tests.toml new file mode 100644 index 0000000..799ab85 --- /dev/null +++ b/exercises/practice/allergies/.meta/tests.toml @@ -0,0 +1,160 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[17fc7296-2440-4ac4-ad7b-d07c321bc5a0] +description = "testing for eggs allergy -> not allergic to anything" + +[07ced27b-1da5-4c2e-8ae2-cb2791437546] +description = "testing for eggs allergy -> allergic only to eggs" + +[5035b954-b6fa-4b9b-a487-dae69d8c5f96] +description = "testing for eggs allergy -> allergic to eggs and something else" + +[64a6a83a-5723-4b5b-a896-663307403310] +description = "testing for eggs allergy -> allergic to something, but not eggs" + +[90c8f484-456b-41c4-82ba-2d08d93231c6] +description = "testing for eggs allergy -> allergic to everything" + +[d266a59a-fccc-413b-ac53-d57cb1f0db9d] +description = "testing for peanuts allergy -> not allergic to anything" + +[ea210a98-860d-46b2-a5bf-50d8995b3f2a] +description = "testing for peanuts allergy -> allergic only to peanuts" + +[eac69ae9-8d14-4291-ac4b-7fd2c73d3a5b] +description = "testing for peanuts allergy -> allergic to peanuts and something else" + +[9152058c-ce39-4b16-9b1d-283ec6d25085] +description = "testing for peanuts allergy -> allergic to something, but not peanuts" + +[d2d71fd8-63d5-40f9-a627-fbdaf88caeab] +description = "testing for peanuts allergy -> allergic to everything" + +[b948b0a1-cbf7-4b28-a244-73ff56687c80] +description = "testing for shellfish allergy -> not allergic to anything" + +[9ce9a6f3-53e9-4923-85e0-73019047c567] +description = "testing for shellfish allergy -> allergic only to shellfish" + +[b272fca5-57ba-4b00-bd0c-43a737ab2131] +description = "testing for shellfish allergy -> allergic to shellfish and something else" + +[21ef8e17-c227-494e-8e78-470a1c59c3d8] +description = "testing for shellfish allergy -> allergic to something, but not shellfish" + +[cc789c19-2b5e-4c67-b146-625dc8cfa34e] +description = "testing for shellfish allergy -> allergic to everything" + +[651bde0a-2a74-46c4-ab55-02a0906ca2f5] +description = "testing for strawberries allergy -> not allergic to anything" + +[b649a750-9703-4f5f-b7f7-91da2c160ece] +description = "testing for strawberries allergy -> allergic only to strawberries" + +[50f5f8f3-3bac-47e6-8dba-2d94470a4bc6] +description = "testing for strawberries allergy -> allergic to strawberries and something else" + +[23dd6952-88c9-48d7-a7d5-5d0343deb18d] +description = "testing for strawberries allergy -> allergic to something, but not strawberries" + +[74afaae2-13b6-43a2-837a-286cd42e7d7e] +description = "testing for strawberries allergy -> allergic to everything" + +[c49a91ef-6252-415e-907e-a9d26ef61723] +description = "testing for tomatoes allergy -> not allergic to anything" + +[b69c5131-b7d0-41ad-a32c-e1b2cc632df8] +description = "testing for tomatoes allergy -> allergic only to tomatoes" + +[1ca50eb1-f042-4ccf-9050-341521b929ec] +description = "testing for tomatoes allergy -> allergic to tomatoes and something else" + +[e9846baa-456b-4eff-8025-034b9f77bd8e] +description = "testing for tomatoes allergy -> allergic to something, but not tomatoes" + +[b2414f01-f3ad-4965-8391-e65f54dad35f] +description = "testing for tomatoes allergy -> allergic to everything" + +[978467ab-bda4-49f7-b004-1d011ead947c] +description = "testing for chocolate allergy -> not allergic to anything" + +[59cf4e49-06ea-4139-a2c1-d7aad28f8cbc] +description = "testing for chocolate allergy -> allergic only to chocolate" + +[b0a7c07b-2db7-4f73-a180-565e07040ef1] +description = "testing for chocolate allergy -> allergic to chocolate and something else" + +[f5506893-f1ae-482a-b516-7532ba5ca9d2] +description = "testing for chocolate allergy -> allergic to something, but not chocolate" + +[02debb3d-d7e2-4376-a26b-3c974b6595c6] +description = "testing for chocolate allergy -> allergic to everything" + +[17f4a42b-c91e-41b8-8a76-4797886c2d96] +description = "testing for pollen allergy -> not allergic to anything" + +[7696eba7-1837-4488-882a-14b7b4e3e399] +description = "testing for pollen allergy -> allergic only to pollen" + +[9a49aec5-fa1f-405d-889e-4dfc420db2b6] +description = "testing for pollen allergy -> allergic to pollen and something else" + +[3cb8e79f-d108-4712-b620-aa146b1954a9] +description = "testing for pollen allergy -> allergic to something, but not pollen" + +[1dc3fe57-7c68-4043-9d51-5457128744b2] +description = "testing for pollen allergy -> allergic to everything" + +[d3f523d6-3d50-419b-a222-d4dfd62ce314] +description = "testing for cats allergy -> not allergic to anything" + +[eba541c3-c886-42d3-baef-c048cb7fcd8f] +description = "testing for cats allergy -> allergic only to cats" + +[ba718376-26e0-40b7-bbbe-060287637ea5] +description = "testing for cats allergy -> allergic to cats and something else" + +[3c6dbf4a-5277-436f-8b88-15a206f2d6c4] +description = "testing for cats allergy -> allergic to something, but not cats" + +[1faabb05-2b98-4995-9046-d83e4a48a7c1] +description = "testing for cats allergy -> allergic to everything" + +[f9c1b8e7-7dc5-4887-aa93-cebdcc29dd8f] +description = "list when: -> no allergies" + +[9e1a4364-09a6-4d94-990f-541a94a4c1e8] +description = "list when: -> just eggs" + +[8851c973-805e-4283-9e01-d0c0da0e4695] +description = "list when: -> just peanuts" + +[2c8943cb-005e-435f-ae11-3e8fb558ea98] +description = "list when: -> just strawberries" + +[6fa95d26-044c-48a9-8a7b-9ee46ec32c5c] +description = "list when: -> eggs and peanuts" + +[19890e22-f63f-4c5c-a9fb-fb6eacddfe8e] +description = "list when: -> more than eggs but not peanuts" + +[4b68f470-067c-44e4-889f-c9fe28917d2f] +description = "list when: -> lots of stuff" + +[0881b7c5-9efa-4530-91bd-68370d054bc7] +description = "list when: -> everything" + +[12ce86de-b347-42a0-ab7c-2e0570f0c65b] +description = "list when: -> no allergen score parts" + +[93c2df3e-4f55-4fed-8116-7513092819cd] +description = "list when: -> no allergen score parts without highest valid score" diff --git a/exercises/practice/allergies/allergies-test.red b/exercises/practice/allergies/allergies-test.red new file mode 100644 index 0000000..9d4bc4e --- /dev/null +++ b/exercises/practice/allergies/allergies-test.red @@ -0,0 +1,464 @@ +Red [ + description: {Tests for "Allergies" Exercism exercise} + author: "loziniak" +] + +#include %testlib.red + +test-init/limit %allergies.red 1 +; test-init/limit %.meta/example.red 1 ; test example solution + +canonical-cases: [#[ + description: "not allergic to anything" + input: #[ + item: "eggs" + score: 0 + ] + expected: false + function: "allergic-to" + uuid: "17fc7296-2440-4ac4-ad7b-d07c321bc5a0" +] #[ + description: "allergic only to eggs" + input: #[ + item: "eggs" + score: 1 + ] + expected: true + function: "allergic-to" + uuid: "07ced27b-1da5-4c2e-8ae2-cb2791437546" +] #[ + description: "allergic to eggs and something else" + input: #[ + item: "eggs" + score: 3 + ] + expected: true + function: "allergic-to" + uuid: "5035b954-b6fa-4b9b-a487-dae69d8c5f96" +] #[ + description: "allergic to something, but not eggs" + input: #[ + item: "eggs" + score: 2 + ] + expected: false + function: "allergic-to" + uuid: "64a6a83a-5723-4b5b-a896-663307403310" +] #[ + description: "allergic to everything" + input: #[ + item: "eggs" + score: 255 + ] + expected: true + function: "allergic-to" + uuid: "90c8f484-456b-41c4-82ba-2d08d93231c6" +] #[ + description: "not allergic to anything" + input: #[ + item: "peanuts" + score: 0 + ] + expected: false + function: "allergic-to" + uuid: "d266a59a-fccc-413b-ac53-d57cb1f0db9d" +] #[ + description: "allergic only to peanuts" + input: #[ + item: "peanuts" + score: 2 + ] + expected: true + function: "allergic-to" + uuid: "ea210a98-860d-46b2-a5bf-50d8995b3f2a" +] #[ + description: "allergic to peanuts and something else" + input: #[ + item: "peanuts" + score: 7 + ] + expected: true + function: "allergic-to" + uuid: "eac69ae9-8d14-4291-ac4b-7fd2c73d3a5b" +] #[ + description: "allergic to something, but not peanuts" + input: #[ + item: "peanuts" + score: 5 + ] + expected: false + function: "allergic-to" + uuid: "9152058c-ce39-4b16-9b1d-283ec6d25085" +] #[ + description: "allergic to everything" + input: #[ + item: "peanuts" + score: 255 + ] + expected: true + function: "allergic-to" + uuid: "d2d71fd8-63d5-40f9-a627-fbdaf88caeab" +] #[ + description: "not allergic to anything" + input: #[ + item: "shellfish" + score: 0 + ] + expected: false + function: "allergic-to" + uuid: "b948b0a1-cbf7-4b28-a244-73ff56687c80" +] #[ + description: "allergic only to shellfish" + input: #[ + item: "shellfish" + score: 4 + ] + expected: true + function: "allergic-to" + uuid: "9ce9a6f3-53e9-4923-85e0-73019047c567" +] #[ + description: "allergic to shellfish and something else" + input: #[ + item: "shellfish" + score: 14 + ] + expected: true + function: "allergic-to" + uuid: "b272fca5-57ba-4b00-bd0c-43a737ab2131" +] #[ + description: "allergic to something, but not shellfish" + input: #[ + item: "shellfish" + score: 10 + ] + expected: false + function: "allergic-to" + uuid: "21ef8e17-c227-494e-8e78-470a1c59c3d8" +] #[ + description: "allergic to everything" + input: #[ + item: "shellfish" + score: 255 + ] + expected: true + function: "allergic-to" + uuid: "cc789c19-2b5e-4c67-b146-625dc8cfa34e" +] #[ + description: "not allergic to anything" + input: #[ + item: "strawberries" + score: 0 + ] + expected: false + function: "allergic-to" + uuid: "651bde0a-2a74-46c4-ab55-02a0906ca2f5" +] #[ + description: "allergic only to strawberries" + input: #[ + item: "strawberries" + score: 8 + ] + expected: true + function: "allergic-to" + uuid: "b649a750-9703-4f5f-b7f7-91da2c160ece" +] #[ + description: "allergic to strawberries and something else" + input: #[ + item: "strawberries" + score: 28 + ] + expected: true + function: "allergic-to" + uuid: "50f5f8f3-3bac-47e6-8dba-2d94470a4bc6" +] #[ + description: "allergic to something, but not strawberries" + input: #[ + item: "strawberries" + score: 20 + ] + expected: false + function: "allergic-to" + uuid: "23dd6952-88c9-48d7-a7d5-5d0343deb18d" +] #[ + description: "allergic to everything" + input: #[ + item: "strawberries" + score: 255 + ] + expected: true + function: "allergic-to" + uuid: "74afaae2-13b6-43a2-837a-286cd42e7d7e" +] #[ + description: "not allergic to anything" + input: #[ + item: "tomatoes" + score: 0 + ] + expected: false + function: "allergic-to" + uuid: "c49a91ef-6252-415e-907e-a9d26ef61723" +] #[ + description: "allergic only to tomatoes" + input: #[ + item: "tomatoes" + score: 16 + ] + expected: true + function: "allergic-to" + uuid: "b69c5131-b7d0-41ad-a32c-e1b2cc632df8" +] #[ + description: "allergic to tomatoes and something else" + input: #[ + item: "tomatoes" + score: 56 + ] + expected: true + function: "allergic-to" + uuid: "1ca50eb1-f042-4ccf-9050-341521b929ec" +] #[ + description: "allergic to something, but not tomatoes" + input: #[ + item: "tomatoes" + score: 40 + ] + expected: false + function: "allergic-to" + uuid: "e9846baa-456b-4eff-8025-034b9f77bd8e" +] #[ + description: "allergic to everything" + input: #[ + item: "tomatoes" + score: 255 + ] + expected: true + function: "allergic-to" + uuid: "b2414f01-f3ad-4965-8391-e65f54dad35f" +] #[ + description: "not allergic to anything" + input: #[ + item: "chocolate" + score: 0 + ] + expected: false + function: "allergic-to" + uuid: "978467ab-bda4-49f7-b004-1d011ead947c" +] #[ + description: "allergic only to chocolate" + input: #[ + item: "chocolate" + score: 32 + ] + expected: true + function: "allergic-to" + uuid: "59cf4e49-06ea-4139-a2c1-d7aad28f8cbc" +] #[ + description: "allergic to chocolate and something else" + input: #[ + item: "chocolate" + score: 112 + ] + expected: true + function: "allergic-to" + uuid: "b0a7c07b-2db7-4f73-a180-565e07040ef1" +] #[ + description: "allergic to something, but not chocolate" + input: #[ + item: "chocolate" + score: 80 + ] + expected: false + function: "allergic-to" + uuid: "f5506893-f1ae-482a-b516-7532ba5ca9d2" +] #[ + description: "allergic to everything" + input: #[ + item: "chocolate" + score: 255 + ] + expected: true + function: "allergic-to" + uuid: "02debb3d-d7e2-4376-a26b-3c974b6595c6" +] #[ + description: "not allergic to anything" + input: #[ + item: "pollen" + score: 0 + ] + expected: false + function: "allergic-to" + uuid: "17f4a42b-c91e-41b8-8a76-4797886c2d96" +] #[ + description: "allergic only to pollen" + input: #[ + item: "pollen" + score: 64 + ] + expected: true + function: "allergic-to" + uuid: "7696eba7-1837-4488-882a-14b7b4e3e399" +] #[ + description: "allergic to pollen and something else" + input: #[ + item: "pollen" + score: 224 + ] + expected: true + function: "allergic-to" + uuid: "9a49aec5-fa1f-405d-889e-4dfc420db2b6" +] #[ + description: "allergic to something, but not pollen" + input: #[ + item: "pollen" + score: 160 + ] + expected: false + function: "allergic-to" + uuid: "3cb8e79f-d108-4712-b620-aa146b1954a9" +] #[ + description: "allergic to everything" + input: #[ + item: "pollen" + score: 255 + ] + expected: true + function: "allergic-to" + uuid: "1dc3fe57-7c68-4043-9d51-5457128744b2" +] #[ + description: "not allergic to anything" + input: #[ + item: "cats" + score: 0 + ] + expected: false + function: "allergic-to" + uuid: "d3f523d6-3d50-419b-a222-d4dfd62ce314" +] #[ + description: "allergic only to cats" + input: #[ + item: "cats" + score: 128 + ] + expected: true + function: "allergic-to" + uuid: "eba541c3-c886-42d3-baef-c048cb7fcd8f" +] #[ + description: "allergic to cats and something else" + input: #[ + item: "cats" + score: 192 + ] + expected: true + function: "allergic-to" + uuid: "ba718376-26e0-40b7-bbbe-060287637ea5" +] #[ + description: "allergic to something, but not cats" + input: #[ + item: "cats" + score: 64 + ] + expected: false + function: "allergic-to" + uuid: "3c6dbf4a-5277-436f-8b88-15a206f2d6c4" +] #[ + description: "allergic to everything" + input: #[ + item: "cats" + score: 255 + ] + expected: true + function: "allergic-to" + uuid: "1faabb05-2b98-4995-9046-d83e4a48a7c1" +] #[ + description: "no allergies" + input: #[ + score: 0 + ] + expected: [] + function: "list" + uuid: "f9c1b8e7-7dc5-4887-aa93-cebdcc29dd8f" +] #[ + description: "just eggs" + input: #[ + score: 1 + ] + expected: ["eggs"] + function: "list" + uuid: "9e1a4364-09a6-4d94-990f-541a94a4c1e8" +] #[ + description: "just peanuts" + input: #[ + score: 2 + ] + expected: ["peanuts"] + function: "list" + uuid: "8851c973-805e-4283-9e01-d0c0da0e4695" +] #[ + description: "just strawberries" + input: #[ + score: 8 + ] + expected: ["strawberries"] + function: "list" + uuid: "2c8943cb-005e-435f-ae11-3e8fb558ea98" +] #[ + description: "eggs and peanuts" + input: #[ + score: 3 + ] + expected: ["eggs" "peanuts"] + function: "list" + uuid: "6fa95d26-044c-48a9-8a7b-9ee46ec32c5c" +] #[ + description: "more than eggs but not peanuts" + input: #[ + score: 5 + ] + expected: ["eggs" "shellfish"] + function: "list" + uuid: "19890e22-f63f-4c5c-a9fb-fb6eacddfe8e" +] #[ + description: "lots of stuff" + input: #[ + score: 248 + ] + expected: ["strawberries" "tomatoes" "chocolate" "pollen" "cats"] + function: "list" + uuid: "4b68f470-067c-44e4-889f-c9fe28917d2f" +] #[ + description: "everything" + input: #[ + score: 255 + ] + expected: ["eggs" "peanuts" "shellfish" "strawberries" "tomatoes" "chocolate" "pollen" "cats"] + function: "list" + uuid: "0881b7c5-9efa-4530-91bd-68370d054bc7" +] #[ + description: "no allergen score parts" + input: #[ + score: 509 + ] + expected: ["eggs" "shellfish" "strawberries" "tomatoes" "chocolate" "pollen" "cats"] + function: "list" + uuid: "12ce86de-b347-42a0-ab7c-2e0570f0c65b" +] #[ + description: {no allergen score parts without highest valid score} + input: #[ + score: 257 + ] + expected: ["eggs"] + function: "list" + uuid: "93c2df3e-4f55-4fed-8116-7513092819cd" +]] + + +foreach c-case canonical-cases [ + case-code: reduce [ + 'expect c-case/expected compose [ + (to word! c-case/function) (values-of c-case/input) + ] + ] + + test c-case/description case-code +] + +test-results/print diff --git a/exercises/practice/allergies/allergies.red b/exercises/practice/allergies/allergies.red new file mode 100644 index 0000000..6101c12 --- /dev/null +++ b/exercises/practice/allergies/allergies.red @@ -0,0 +1,18 @@ +Red [ + description: {"Allergies" exercise solution for exercism platform} + author: "" ; you can write your name here, in quotes +] + +allergic-to: function [ + item + score +] [ + cause-error 'user 'message "You need to implement allergic-to function." +] + +list: function [ + score +] [ + cause-error 'user 'message "You need to implement list function." +] + diff --git a/exercises/practice/allergies/testlib.red b/exercises/practice/allergies/testlib.red new file mode 100644 index 0000000..9b0b79e --- /dev/null +++ b/exercises/practice/allergies/testlib.red @@ -0,0 +1,217 @@ +Red [ + description: {Unit testing library} + author: "loziniak" +] + + +context [ + tested: ignore-after: test-file: results: output: none + + set 'test-init function [ + file [file!] + /limit + ia [integer!] + ] [ + self/tested: 0 + self/ignore-after: either limit [ia] [none] + self/test-file: file + self/results: copy [] + self/output: copy "" + ] + + sandbox!: context [ + + assert: function [ + code [block!] + /local result + ] [ + res: last results + + set/any 'result do code + either :result = true [ + res/status: 'pass + ] [ + res/status: 'fail + throw/name none 'expect-fail + ] + + :result + ] + + expect: function [ + expectation [any-type!] + code [block!] + /local result + ] [ + res: last results + res/expected: :expectation + + set/any 'result do code + res/actual: :result + + either :result = :expectation [ + res/status: 'pass + ] [ + res/status: 'fail + throw/name none 'expect-fail + ] + + :result + ] + + expect-error: function [ + type [word!] + code [block!] + /message + msg [string!] + /local result result-or-error + ] [ + returned-error?: no + set/any 'result-or-error try [ + set/any 'result do code + returned-error?: yes + :result + ] + + res: last results + res/actual: :result-or-error + res/expected: compose [type: (type)] + if message [append res/expected compose [id: 'message arg1: (msg)]] + + either all [ + error? :result-or-error + not returned-error? + result-or-error/type = type + any [ + not message + all [ + result-or-error/id = 'message + result-or-error/arg1 = msg + ] + ] + ] [ + res/status: 'pass + ] [ + res/status: 'fail + throw/name none 'expect-fail + ] + + :result-or-error + ] + ] + + set 'test function [ + summary [string!] + code [block!] + /extern + tested + ] [ + append results result: make map! compose/only [ + summary: (summary) ;@@ [string!] + test-code: (copy code) ;@@ [block!] + status: none ;@@ [word!] : 'pass | 'fail | 'error | 'ignored + ;-- expected (optional field) + ;-- actual (optional field) + ;-- output (optional field) + ] + + either any [ + none? ignore-after + tested < ignore-after + ] [ + clear output + old-functions: override-console + + exercise: make sandbox! load test-file + code: bind code exercise + uncaught?: yes + outcome: catch [ + outcome: try [ + catch/name [ + do code + ] 'expect-fail + none + ] + uncaught?: no + outcome + ] + + case [ + error? outcome [ + result/status: 'error + result/actual: outcome + ] + uncaught? [ + result/status: 'error + result/actual: make error! [type: 'throw id: 'throw arg1: outcome] + ] + ] + + restore-console old-functions + result/output: copy output + ] [ + result/status: 'ignored + ] + + tested: tested + 1 + ] + + set 'test-results function [ + /print + ] [ + either print [ + foreach result self/results [ + system/words/print rejoin [ + pad/with result/summary 40 #"." + "... " + switch result/status [ + pass ["✓"] + fail [rejoin [ + {FAILED.} + either find result 'expected [rejoin [ + { Expected: } result/expected + either find result 'actual [rejoin [ + {, but got } result/actual + ]] [] + ]] [] + newline + result/output + ]] + error [rejoin [ + newline + result/output + form result/actual + ]] + ignored ["(ignored)"] + ] + ] + ] + ] [ + self/results + ] + ] + + + override-console: function [] [ + old-functions: reduce [:prin :print :probe] + + system/words/prin: function [value [any-type!]] [ + append self/output form :value + return () + ] + system/words/print: function [value [any-type!]] [ + append self/output reduce [form :value #"^/"] + return () + ] + system/words/probe: function [value [any-type!]] [ + append self/output reduce [mold :value #"^/"] + return :value + ] + return old-functions + ] + + restore-console: function [old-functions [block!]] [ + set [prin print probe] old-functions + ] + +]