{
  "id": "P154",
  "slug": "mutation-tester",
  "key": "P154-mutation-tester",
  "title": "Mutation tester",
  "summary": "One small function and four mutants of it, test suites scored by the branches they run and the mutants they catch, the values that tell each mutant apart, and a test double that agrees with all of them.",
  "entry": "main.eml",
  "ui": "terminal",
  "readme": "# P154 - Mutation tester\n\nOne small function, four mutants of it, and test suites scored two ways:\nby the branches they run and by the mutants they catch.\n\n- `main.eml` - the menu, the function and its mutants, the suites, one\n  suite check by check, the values that tell each mutant apart, and a suite\n  of your own\n- `mutants.eml` - the band of a quantity with each mutant, the rate\n  service and its fixed double, the price, the suites, the branches a\n  suite runs, and the first check that catches a mutant\n\nHow each part works:\n\n- band(n) puts a quantity in invalid, low (0 to 9), mid (10 to 99) or\n  high (100 and up), and the price is the band's rate from a service. The\n  mutants: a negative put in low, 10 put in low, 100 put in mid, mid and\n  high swapped.\n- As in the corpus case `mutation-survival`, coverage counts the branches a\n  suite runs and the mutants count what it notices. Round numbers - -5, 5,\n  50, 500 - run all four branches and catch 2 of the 4 mutants: full\n  coverage, and a broken function passes. Checking every edge catches all\n  four.\n- As in the corpus case `fixture-avoids-the-boundary`, which values tell a\n  mutant from the function is swept, not guessed: in -3 to 103 the low\n  edge is told apart by 10 alone and the high edge by 100 alone.\n- As in the corpus case `mock-ignores-input`, a test double that answers 8\n  whatever band it is asked about agrees with every mutant: the round\n  numbers checked against it run every branch and catch none.\n\nWhat is checked: menu choices 1 to 6; a suite from 1 to 4; 1 to 6 whole\nnumbers from -999 to 999, and the double faithful or fixed. An empty\nanswer cancels.\n\nSessions: `sessions/basic.in` gives:\n- the function and the suites; suites 2, 3 and 4 check by check;\n- the values that tell; a suite of 0, 10 and 100 with the faithful double,\n  and of 50 with the fixed one.\n\n`sessions/bad-input.in` gives:\n- menu choices 0 and x;\n- suites: a cancel, 5 and x;\n- quantities: a cancel, seven of them, 1000, a lone minus sign and a;\n- 10 with a cancel and mock for the double; -1 and 0 with the faithful\n  double.\n\nBuilt on the verified corpus cases `mutation-survival` (full coverage\nagainst the mutants a suite kills), `fixture-avoids-the-boundary` (the\nvalues that detect each off-by-one, swept) and `mock-ignores-input` (a\ndouble that returns success whatever it is called with).\n",
  "modules": [
    {
      "name": "main.eml",
      "eml": "# P154 mutation tester: the function and its mutants, the suites scored by\n# coverage and by mutants caught, one suite check by check, the values that\n# tell each mutant apart, and a suite of your own.\nimport mutants\n\ndef plain(s):\n    0 => i\n    len(s) => j\n    while i < j and s[i] == \" \":\n        i + 1 => i\n    while j > i and s[j - 1] == \" \":\n        j - 1 => j\n    return s[i:j]\n\ndef pad(s, n):\n    s => out\n    while len(out) < n:\n        out + \" \" => out\n    return out\n\ndef lpad(s, n):\n    s => out\n    while len(out) < n:\n        \" \" + out => out\n    return out\n\ndef listed(ns):\n    \"\" => out\n    for n in ns:\n        if out == \"\":\n            str(n) => out\n        else:\n            out + \", \" + str(n) => out\n    return out\n\ndef caught(ns, double):\n    0 => k\n    for m in mutants.mutants():\n        if mutants.kills(ns, double, m) > 0 - 1000:\n            k + 1 => k\n    return k\n\ndef show_function():\n    \"band(n): invalid below 0, low 0 to 9, mid 10 to 99, high 100 and up; price(n) asks the rate service for the band's rate.\" ^0\n    \"The real service answers 5 for low, 8 for mid, 12 for high, 0 for invalid. The mutants, each one small change:\" ^0\n    0 => i\n    for m in mutants.mutants():\n        (\"  \" + pad(m, 11) + mutants.what()[i]) ^0\n        i + 1 => i\n\ndef show_suites():\n    (\"  \" + pad(\"suite\", 21) + pad(\"checks\", 23) + pad(\"double\", 10) + \"branches  mutants caught\") ^0\n    for s in mutants.suites():\n        (\"  \" + pad(s[0], 21) + pad(listed(s[1]), 23) + pad(s[2], 10) + lpad(str(mutants.branches(s[1])) + \" of 4\", 8) + lpad(str(caught(s[1], s[2])) + \" of 4\", 15)) ^0\n    for s in mutants.suites():\n        mutants.branches(s[1]) => b\n        caught(s[1], s[2]) => k\n        if b == 4 and k < 4:\n            (\"  \" + s[0] + \" runs every branch and catches \" + str(k) + \" of 4: full coverage, and a broken function passes.\") ^0\n    \"  A mutant that survives names a behaviour no check is watching.\" ^0\n\ndef one_suite():\n    plain(input(\"suite (1 to 4)> \")) => t\n    if t == \"\":\n        \"Cancelled.\" ^0\n        return\n    if t != \"1\" and t != \"2\" and t != \"3\" and t != \"4\":\n        \"Type a suite from 1 to 4.\" ^0\n        return\n    mutants.suites()[int(t) - 1] => s\n    report(s[0], s[1], s[2])\n\ndef report(name, ns, double):\n    (name + \": checks \" + listed(ns) + \" with the \" + double + \" double; \" + str(mutants.branches(ns)) + \" of 4 branches run.\") ^0\n    for m in mutants.mutants():\n        mutants.kills(ns, double, m) => n\n        if n > 0 - 1000:\n            (\"  \" + pad(m, 11) + \"caught by \" + str(n) + \": price \" + str(mutants.price(n, m, double)) + \" instead of \" + str(mutants.price(n, \"none\", double))) ^0\n        else:\n            (\"  \" + pad(m, 11) + \"survives: no check's price changes\") ^0\n    if double == \"fixed\":\n        \"The fixed double answers 8 whatever band it is asked about, so no band mutant can change a price.\" ^0\n\ndef tell():\n    \"In -3 to 103, the values whose price tells each mutant from the function (faithful service):\" ^0\n    for m in mutants.mutants():\n        \"\" => out\n        0 - 4 => start\n        0 - 4 => last\n        0 - 3 => n\n        while n <= 104:\n            n <= 103 and mutants.price(n, m, \"faithful\") != mutants.price(n, \"none\", \"faithful\") => d\n            if d and start == 0 - 4:\n                n => start\n            if d:\n                n => last\n            if not d and start != 0 - 4:\n                if out != \"\":\n                    out + \", \" => out\n                if start == last:\n                    out + str(start) => out\n                else:\n                    out + str(start) + \" to \" + str(last) => out\n                0 - 4 => start\n            n + 1 => n\n        (\"  \" + pad(m, 11) + out) ^0\n    \"An edge mutant is told apart by its edge alone: a fixture of round numbers never meets it.\" ^0\n\ndef own():\n    plain(input(\"quantities, up to 6, separated by spaces> \")) => t\n    if t == \"\":\n        \"Cancelled.\" ^0\n        return\n    [] => ns\n    \"\" => cur\n    for c in t + \" \":\n        if c == \" \":\n            if cur != \"\":\n                0 => start\n                if cur[0] == \"-\":\n                    1 => start\n                if len(cur) == start or len(cur) - start > 3:\n                    \"Type 1 to 6 whole numbers from -999 to 999.\" ^0\n                    return\n                0 => v\n                for d in cur[start:len(cur)]:\n                    if d < \"0\" or d > \"9\":\n                        \"Type 1 to 6 whole numbers from -999 to 999.\" ^0\n                        return\n                    v * 10 + int(d) => v\n                if start == 1:\n                    0 - v => v\n                ns + [v] => ns\n                \"\" => cur\n        else:\n            cur + c => cur\n    if len(ns) > 6:\n        \"Type 1 to 6 whole numbers from -999 to 999.\" ^0\n        return\n    plain(input(\"double (faithful or fixed)> \")) => d\n    if d == \"\":\n        \"Cancelled.\" ^0\n        return\n    if d != \"faithful\" and d != \"fixed\":\n        \"Type faithful or fixed.\" ^0\n        return\n    report(\"Your suite\", ns, d)\n\n\"== Mutation tester ==\" ^0\n\"One small function, its mutants, and test suites scored by coverage and by the mutants they catch.\" ^0\nTrue => running\nwhile running:\n    \"\" ^0\n    \"1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\" ^0\n    plain(input(\"choice> \")) => choice\n    if choice == \"1\":\n        show_function()\n    elif choice == \"2\":\n        show_suites()\n    elif choice == \"3\":\n        one_suite()\n    elif choice == \"4\":\n        tell()\n    elif choice == \"5\":\n        own()\n    elif choice == \"6\":\n        False => running\n    else:\n        \"Pick a number from 1 to 6.\" ^0\n\"Bye.\" ^0\n",
      "python": "import mutants\n\ndef plain(s):\n    i = 0\n    j = len(s)\n    while i < j and s[i] == \" \":\n        i = i + 1\n    while j > i and s[j - 1] == \" \":\n        j = j - 1\n    return s[i:j]\n\ndef pad(s, n):\n    out = s\n    while len(out) < n:\n        out = out + \" \"\n    return out\n\ndef lpad(s, n):\n    out = s\n    while len(out) < n:\n        out = \" \" + out\n    return out\n\ndef listed(ns):\n    out = \"\"\n    for n in ns:\n        if out == \"\":\n            out = str(n)\n        else:\n            out = out + \", \" + str(n)\n    return out\n\ndef caught(ns, double):\n    k = 0\n    for m in mutants.mutants():\n        if mutants.kills(ns, double, m) > 0 - 1000:\n            k = k + 1\n    return k\n\ndef show_function():\n    print(\"band(n): invalid below 0, low 0 to 9, mid 10 to 99, high 100 and up; price(n) asks the rate service for the band's rate.\")\n    print(\"The real service answers 5 for low, 8 for mid, 12 for high, 0 for invalid. The mutants, each one small change:\")\n    i = 0\n    for m in mutants.mutants():\n        print(\"  \" + pad(m, 11) + mutants.what()[i])\n        i = i + 1\n\ndef show_suites():\n    print(\"  \" + pad(\"suite\", 21) + pad(\"checks\", 23) + pad(\"double\", 10) + \"branches  mutants caught\")\n    for s in mutants.suites():\n        print(\"  \" + pad(s[0], 21) + pad(listed(s[1]), 23) + pad(s[2], 10) + lpad(str(mutants.branches(s[1])) + \" of 4\", 8) + lpad(str(caught(s[1], s[2])) + \" of 4\", 15))\n    for s in mutants.suites():\n        b = mutants.branches(s[1])\n        k = caught(s[1], s[2])\n        if b == 4 and k < 4:\n            print(\"  \" + s[0] + \" runs every branch and catches \" + str(k) + \" of 4: full coverage, and a broken function passes.\")\n    print(\"  A mutant that survives names a behaviour no check is watching.\")\n\ndef one_suite():\n    t = plain(input(\"suite (1 to 4)> \"))\n    if t == \"\":\n        print(\"Cancelled.\")\n        return\n    if t != \"1\" and t != \"2\" and t != \"3\" and t != \"4\":\n        print(\"Type a suite from 1 to 4.\")\n        return\n    s = mutants.suites()[int(t) - 1]\n    report(s[0], s[1], s[2])\n\ndef report(name, ns, double):\n    print(name + \": checks \" + listed(ns) + \" with the \" + double + \" double; \" + str(mutants.branches(ns)) + \" of 4 branches run.\")\n    for m in mutants.mutants():\n        n = mutants.kills(ns, double, m)\n        if n > 0 - 1000:\n            print(\"  \" + pad(m, 11) + \"caught by \" + str(n) + \": price \" + str(mutants.price(n, m, double)) + \" instead of \" + str(mutants.price(n, \"none\", double)))\n        else:\n            print(\"  \" + pad(m, 11) + \"survives: no check's price changes\")\n    if double == \"fixed\":\n        print(\"The fixed double answers 8 whatever band it is asked about, so no band mutant can change a price.\")\n\ndef tell():\n    print(\"In -3 to 103, the values whose price tells each mutant from the function (faithful service):\")\n    for m in mutants.mutants():\n        out = \"\"\n        start = 0 - 4\n        last = 0 - 4\n        n = 0 - 3\n        while n <= 104:\n            d = n <= 103 and mutants.price(n, m, \"faithful\") != mutants.price(n, \"none\", \"faithful\")\n            if d and start == 0 - 4:\n                start = n\n            if d:\n                last = n\n            if not d and start != 0 - 4:\n                if out != \"\":\n                    out = out + \", \"\n                if start == last:\n                    out = out + str(start)\n                else:\n                    out = out + str(start) + \" to \" + str(last)\n                start = 0 - 4\n            n = n + 1\n        print(\"  \" + pad(m, 11) + out)\n    print(\"An edge mutant is told apart by its edge alone: a fixture of round numbers never meets it.\")\n\ndef own():\n    t = plain(input(\"quantities, up to 6, separated by spaces> \"))\n    if t == \"\":\n        print(\"Cancelled.\")\n        return\n    ns = []\n    cur = \"\"\n    for c in t + \" \":\n        if c == \" \":\n            if cur != \"\":\n                start = 0\n                if cur[0] == \"-\":\n                    start = 1\n                if len(cur) == start or len(cur) - start > 3:\n                    print(\"Type 1 to 6 whole numbers from -999 to 999.\")\n                    return\n                v = 0\n                for d in cur[start:len(cur)]:\n                    if d < \"0\" or d > \"9\":\n                        print(\"Type 1 to 6 whole numbers from -999 to 999.\")\n                        return\n                    v = v * 10 + int(d)\n                if start == 1:\n                    v = 0 - v\n                ns = ns + [v]\n                cur = \"\"\n        else:\n            cur = cur + c\n    if len(ns) > 6:\n        print(\"Type 1 to 6 whole numbers from -999 to 999.\")\n        return\n    d = plain(input(\"double (faithful or fixed)> \"))\n    if d == \"\":\n        print(\"Cancelled.\")\n        return\n    if d != \"faithful\" and d != \"fixed\":\n        print(\"Type faithful or fixed.\")\n        return\n    report(\"Your suite\", ns, d)\n\nprint(\"== Mutation tester ==\")\nprint(\"One small function, its mutants, and test suites scored by coverage and by the mutants they catch.\")\nrunning = True\nwhile running:\n    print(\"\")\n    print(\"1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\")\n    choice = plain(input(\"choice> \"))\n    if choice == \"1\":\n        show_function()\n    elif choice == \"2\":\n        show_suites()\n    elif choice == \"3\":\n        one_suite()\n    elif choice == \"4\":\n        tell()\n    elif choice == \"5\":\n        own()\n    elif choice == \"6\":\n        running = False\n    else:\n        print(\"Pick a number from 1 to 6.\")\nprint(\"Bye.\")\n"
    },
    {
      "name": "mutants.eml",
      "eml": "# P154 mutation tester - one small function, the mutants of it, and test\n# suites scored two ways. As in the corpus case mutation-survival, coverage\n# counts the branches a suite runs and a mutant counts what it notices: a\n# suite can run every branch and miss a broken one. As in the corpus case\n# fixture-avoids-the-boundary, which values can tell a mutant from the\n# function is computed by sweeping them, not guessed: an edge mutant is told\n# apart by one value only. As in the corpus case mock-ignores-input, a test\n# double that answers the same whatever it is asked agrees with every\n# mutant. The function: a band for a quantity, and the price the band's\n# rate service gives.\n\ndef mutants():\n    return [\"sign\", \"low edge\", \"high edge\", \"swap\"]\n\ndef what():\n    return [\"a negative quantity is put in low\", \"10 is put in low (n < 11)\", \"100 is put in mid (n < 101)\", \"mid and high are swapped\"]\n\ndef band(n, m):\n    # invalid below 0, low 0 to 9, mid 10 to 99, high 100 and up;\n    # m names a mutant, or \"none\"\n    if n < 0:\n        if m == \"sign\":\n            return \"low\"\n        return \"invalid\"\n    10 => top_low\n    if m == \"low edge\":\n        11 => top_low\n    if n < top_low:\n        return \"low\"\n    100 => top_mid\n    if m == \"high edge\":\n        101 => top_mid\n    if n < top_mid:\n        if m == \"swap\":\n            return \"high\"\n        return \"mid\"\n    if m == \"swap\":\n        return \"mid\"\n    return \"high\"\n\ndef rate(b, double):\n    # the rate service: faithful answers for the band asked, fixed answers 8\n    # whatever it is asked\n    if double == \"fixed\":\n        return 8\n    if b == \"low\":\n        return 5\n    if b == \"mid\":\n        return 8\n    if b == \"high\":\n        return 12\n    return 0\n\ndef price(n, m, double):\n    return rate(band(n, m), double)\n\ndef suites():\n    # [name, the quantities it checks, the double it uses]\n    return [[\"happy path\", [50], \"fixed\"], [\"round numbers\", [0 - 5, 5, 50, 500], \"faithful\"], [\"round, fixed double\", [0 - 5, 5, 50, 500], \"fixed\"], [\"every edge\", [0 - 1, 0, 9, 10, 99, 100], \"faithful\"]]\n\ndef branches(ns):\n    # the bands, of 4, that the quantities run\n    [] => seen\n    for n in ns:\n        band(n, \"none\") => b\n        False => have\n        for s in seen:\n            if s == b:\n                True => have\n        if not have:\n            seen + [b] => seen\n    return len(seen)\n\ndef kills(ns, double, m):\n    # the first quantity whose expected price the mutant changes, or -1000\n    for n in ns:\n        if price(n, m, double) != price(n, \"none\", double):\n            return n\n    return 0 - 1000\n",
      "python": "def mutants():\n    return [\"sign\", \"low edge\", \"high edge\", \"swap\"]\n\ndef what():\n    return [\"a negative quantity is put in low\", \"10 is put in low (n < 11)\", \"100 is put in mid (n < 101)\", \"mid and high are swapped\"]\n\ndef band(n, m):\n    if n < 0:\n        if m == \"sign\":\n            return \"low\"\n        return \"invalid\"\n    top_low = 10\n    if m == \"low edge\":\n        top_low = 11\n    if n < top_low:\n        return \"low\"\n    top_mid = 100\n    if m == \"high edge\":\n        top_mid = 101\n    if n < top_mid:\n        if m == \"swap\":\n            return \"high\"\n        return \"mid\"\n    if m == \"swap\":\n        return \"mid\"\n    return \"high\"\n\ndef rate(b, double):\n    if double == \"fixed\":\n        return 8\n    if b == \"low\":\n        return 5\n    if b == \"mid\":\n        return 8\n    if b == \"high\":\n        return 12\n    return 0\n\ndef price(n, m, double):\n    return rate(band(n, m), double)\n\ndef suites():\n    return [[\"happy path\", [50], \"fixed\"], [\"round numbers\", [0 - 5, 5, 50, 500], \"faithful\"], [\"round, fixed double\", [0 - 5, 5, 50, 500], \"fixed\"], [\"every edge\", [0 - 1, 0, 9, 10, 99, 100], \"faithful\"]]\n\ndef branches(ns):\n    seen = []\n    for n in ns:\n        b = band(n, \"none\")\n        have = False\n        for s in seen:\n            if s == b:\n                have = True\n        if not have:\n            seen = seen + [b]\n    return len(seen)\n\ndef kills(ns, double, m):\n    for n in ns:\n        if price(n, m, double) != price(n, \"none\", double):\n            return n\n    return 0 - 1000\n"
    }
  ],
  "sessions": [
    {
      "name": "bad-input",
      "input": "0\nx\n3\n\n3\n5\n3\nx\n5\n\n5\n1 2 3 4 5 6 7\n5\n1000\n5\n-\n5\na\n5\n10\n\n5\n10\nmock\n5\n-1 0\nfaithful\n6\n",
      "screen": "== Mutation tester ==\nOne small function, its mutants, and test suites scored by coverage and by the mutants they catch.\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 0\nPick a number from 1 to 6.\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> x\nPick a number from 1 to 6.\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 3\nsuite (1 to 4)> \nCancelled.\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 3\nsuite (1 to 4)> 5\nType a suite from 1 to 4.\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 3\nsuite (1 to 4)> x\nType a suite from 1 to 4.\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 5\nquantities, up to 6, separated by spaces> \nCancelled.\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 5\nquantities, up to 6, separated by spaces> 1 2 3 4 5 6 7\nType 1 to 6 whole numbers from -999 to 999.\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 5\nquantities, up to 6, separated by spaces> 1000\nType 1 to 6 whole numbers from -999 to 999.\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 5\nquantities, up to 6, separated by spaces> -\nType 1 to 6 whole numbers from -999 to 999.\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 5\nquantities, up to 6, separated by spaces> a\nType 1 to 6 whole numbers from -999 to 999.\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 5\nquantities, up to 6, separated by spaces> 10\ndouble (faithful or fixed)> \nCancelled.\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 5\nquantities, up to 6, separated by spaces> 10\ndouble (faithful or fixed)> mock\nType faithful or fixed.\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 5\nquantities, up to 6, separated by spaces> -1 0\ndouble (faithful or fixed)> faithful\nYour suite: checks -1, 0 with the faithful double; 2 of 4 branches run.\n  sign       caught by -1: price 5 instead of 0\n  low edge   survives: no check's price changes\n  high edge  survives: no check's price changes\n  swap       survives: no check's price changes\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 6\nBye.\n",
      "interpreter": "equal"
    },
    {
      "name": "basic",
      "input": "1\n2\n3\n2\n3\n3\n3\n4\n4\n5\n0 10 100\nfaithful\n5\n50\nfixed\n6\n",
      "screen": "== Mutation tester ==\nOne small function, its mutants, and test suites scored by coverage and by the mutants they catch.\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 1\nband(n): invalid below 0, low 0 to 9, mid 10 to 99, high 100 and up; price(n) asks the rate service for the band's rate.\nThe real service answers 5 for low, 8 for mid, 12 for high, 0 for invalid. The mutants, each one small change:\n  sign       a negative quantity is put in low\n  low edge   10 is put in low (n < 11)\n  high edge  100 is put in mid (n < 101)\n  swap       mid and high are swapped\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 2\n  suite                checks                 double    branches  mutants caught\n  happy path           50                     fixed       1 of 4         0 of 4\n  round numbers        -5, 5, 50, 500         faithful    4 of 4         2 of 4\n  round, fixed double  -5, 5, 50, 500         fixed       4 of 4         0 of 4\n  every edge           -1, 0, 9, 10, 99, 100  faithful    4 of 4         4 of 4\n  round numbers runs every branch and catches 2 of 4: full coverage, and a broken function passes.\n  round, fixed double runs every branch and catches 0 of 4: full coverage, and a broken function passes.\n  A mutant that survives names a behaviour no check is watching.\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 3\nsuite (1 to 4)> 2\nround numbers: checks -5, 5, 50, 500 with the faithful double; 4 of 4 branches run.\n  sign       caught by -5: price 5 instead of 0\n  low edge   survives: no check's price changes\n  high edge  survives: no check's price changes\n  swap       caught by 50: price 12 instead of 8\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 3\nsuite (1 to 4)> 3\nround, fixed double: checks -5, 5, 50, 500 with the fixed double; 4 of 4 branches run.\n  sign       survives: no check's price changes\n  low edge   survives: no check's price changes\n  high edge  survives: no check's price changes\n  swap       survives: no check's price changes\nThe fixed double answers 8 whatever band it is asked about, so no band mutant can change a price.\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 3\nsuite (1 to 4)> 4\nevery edge: checks -1, 0, 9, 10, 99, 100 with the faithful double; 4 of 4 branches run.\n  sign       caught by -1: price 5 instead of 0\n  low edge   caught by 10: price 5 instead of 8\n  high edge  caught by 100: price 8 instead of 12\n  swap       caught by 10: price 12 instead of 8\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 4\nIn -3 to 103, the values whose price tells each mutant from the function (faithful service):\n  sign       -3 to -1\n  low edge   10\n  high edge  100\n  swap       10 to 103\nAn edge mutant is told apart by its edge alone: a fixture of round numbers never meets it.\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 5\nquantities, up to 6, separated by spaces> 0 10 100\ndouble (faithful or fixed)> faithful\nYour suite: checks 0, 10, 100 with the faithful double; 3 of 4 branches run.\n  sign       survives: no check's price changes\n  low edge   caught by 10: price 5 instead of 8\n  high edge  caught by 100: price 8 instead of 12\n  swap       caught by 10: price 12 instead of 8\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 5\nquantities, up to 6, separated by spaces> 50\ndouble (faithful or fixed)> fixed\nYour suite: checks 50 with the fixed double; 1 of 4 branches run.\n  sign       survives: no check's price changes\n  low edge   survives: no check's price changes\n  high edge  survives: no check's price changes\n  swap       survives: no check's price changes\nThe fixed double answers 8 whatever band it is asked about, so no band mutant can change a price.\n\n1) the function  2) the suites  3) one suite  4) the values that tell  5) your own suite  6) quit\nchoice> 6\nBye.\n",
      "interpreter": "equal"
    }
  ],
  "builtOn": [
    {
      "slug": "mutation-survival",
      "caseId": "283-mutation-survival",
      "title": "Mutation survival — the test that runs the most lines checks the least"
    },
    {
      "slug": "fixture-avoids-the-boundary",
      "caseId": "279-fixture-avoids-the-boundary",
      "title": "Fixture avoids the boundary — which values can detect an off-by-one"
    },
    {
      "slug": "mock-ignores-input",
      "caseId": "282-mock-ignores-input",
      "title": "A mock that ignores its input — the double agreed with every caller"
    }
  ],
  "updated": "2026-10-18"
}
