Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions exercises/practice/affine-cipher/test_affine_cipher.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ const encode = affine_cipher.encode;
const decode = affine_cipher.decode;
const AffineCipherError = affine_cipher.AffineCipherError;

fn testEncodeError(phrase: []const u8, a: u8, b: u8) !void {
const actual = encode(testing.allocator, phrase, a, b);
defer if (actual) |slice| testing.allocator.free(slice) else |_| {};
try testing.expectError(AffineCipherError.NotCoprime, actual);
}

fn testDecodeError(phrase: []const u8, a: u8, b: u8) !void {
const actual = decode(testing.allocator, phrase, a, b);
defer if (actual) |slice| testing.allocator.free(slice) else |_| {};
try testing.expectError(AffineCipherError.NotCoprime, actual);
}

test "encode yes" {
const expected: []const u8 = "xbt";
const actual = try encode(testing.allocator, "yes", 5, 7);
Expand Down Expand Up @@ -63,8 +75,7 @@ test "encode all the letters" {
}

test "encode with a not coprime to m" {
const actual = encode(testing.allocator, "This is a test.", 6, 17);
try testing.expectError(AffineCipherError.NotCoprime, actual);
try testEncodeError("This is a test.", 6, 17);
}

test "decode exercism" {
Expand Down Expand Up @@ -110,8 +121,7 @@ test "decode with too many spaces" {
}

test "decode with a not coprime to m" {
const actual = decode(testing.allocator, "Test", 13, 5);
try testing.expectError(AffineCipherError.NotCoprime, actual);
try testDecodeError("Test", 13, 5);
}

test "encode boundary characters" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ const transmitSequence = intergalactic_transmission.transmitSequence;
const decodeMessage = intergalactic_transmission.decodeMessage;
const TransmissionError = intergalactic_transmission.TransmissionError;

fn testDecodeMessageError(message: []const u8) !void {
const actual = decodeMessage(testing.allocator, message);
defer if (actual) |slice| testing.allocator.free(slice) else |_| {};
try testing.expectError(TransmissionError.WrongParity, actual);
}

test "calculate transmit sequences-empty message" {
const message = [_]u8{};
const expected = [_]u8{};
Expand Down Expand Up @@ -136,12 +142,12 @@ test "decode received messages-0x2881 is decoded to 0x29" {

test "decode received messages-first byte has wrong parity" {
const message = [_]u8{ 0x07, 0x00 };
try testing.expectError(TransmissionError.WrongParity, decodeMessage(testing.allocator, &message));
try testDecodeMessageError(&message);
}

test "decode received messages-second byte has wrong parity" {
const message = [_]u8{ 0x03, 0x68 };
try testing.expectError(TransmissionError.WrongParity, decodeMessage(testing.allocator, &message));
try testDecodeMessageError(&message);
}

test "decode received messages-0xcf4b00 is decoded to 0xce94" {
Expand Down Expand Up @@ -178,7 +184,7 @@ test "decode received messages-seven byte message" {

test "decode received messages-last byte has wrong parity" {
const message = [_]u8{ 0x47, 0xb8, 0x99, 0xac, 0x17, 0xa0, 0xc5, 0x43 };
try testing.expectError(TransmissionError.WrongParity, decodeMessage(testing.allocator, &message));
try testDecodeMessageError(&message);
}

test "decode received messages-eight byte message" {
Expand All @@ -199,5 +205,5 @@ test "decode received messages-twenty byte message" {

test "decode received messages-wrong parity on 16th byte" {
const message = [_]u8{ 0x44, 0xbd, 0x18, 0xaf, 0x27, 0x1b, 0xa5, 0xe7, 0x6c, 0x90, 0x1b, 0x2e, 0x33, 0x03, 0x84, 0xef, 0x65, 0xb8, 0xdb, 0xed, 0xd7, 0x28, 0x84 };
try testing.expectError(TransmissionError.WrongParity, decodeMessage(testing.allocator, &message));
try testDecodeMessageError(&message);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ const proteins = protein_translation.proteins;
const Protein = protein_translation.Protein;
const TranslationError = protein_translation.TranslationError;

fn testProteinsError(strand: []const u8) !void {
const actual = proteins(testing.allocator, strand);
defer if (actual) |slice| testing.allocator.free(slice) else |_| {};
try testing.expectError(TranslationError.InvalidCodon, actual);
}

test "Empty RNA sequence results in no proteins" {
const expected = [_]Protein{};
const actual = try proteins(testing.allocator, "");
Expand Down Expand Up @@ -196,11 +202,11 @@ test "Sequence of two non-STOP codons does not translate to a STOP codon" {
}

test "Unknown amino acids, not part of a codon, can't translate" {
try testing.expectError(TranslationError.InvalidCodon, proteins(testing.allocator, "XYZ"));
try testProteinsError("XYZ");
}

test "Incomplete RNA sequence can't translate" {
try testing.expectError(TranslationError.InvalidCodon, proteins(testing.allocator, "AUGU"));
try testProteinsError("AUGU");
}

test "Incomplete RNA sequence can translate if valid until a STOP codon" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ const encode = variable_length_quantity.encode;
const decode = variable_length_quantity.decode;
const DecodeError = variable_length_quantity.DecodeError;

fn testDecodeError(integers: []const u8) !void {
const actual = decode(testing.allocator, integers);
defer if (actual) |slice| testing.allocator.free(slice) else |_| {};
try testing.expectError(DecodeError.IncompleteSequence, actual);
}

test "encode - zero" {
const expected = [_]u8{0};
const integers = [_]u32{0};
Expand Down Expand Up @@ -232,14 +238,12 @@ test "decode - maximum 32-bit integer" {

test "decode - incomplete sequence causes error" {
const integers = [_]u8{255};
const actual = decode(testing.allocator, &integers);
try testing.expectError(DecodeError.IncompleteSequence, actual);
try testDecodeError(&integers);
}

test "decode - incomplete sequence causes error, even if value is zero" {
const integers = [_]u8{128};
const actual = decode(testing.allocator, &integers);
try testing.expectError(DecodeError.IncompleteSequence, actual);
try testDecodeError(&integers);
}

test "decode - multiple values" {
Expand Down
27 changes: 18 additions & 9 deletions generators/exercises/affine_cipher.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
from lib import zstr, is_error

HEADER = (
"const encode = affine_cipher.encode;\n"
"const decode = affine_cipher.decode;\n"
"const AffineCipherError = affine_cipher.AffineCipherError;"
)
HEADER = """const encode = affine_cipher.encode;
const decode = affine_cipher.decode;
const AffineCipherError = affine_cipher.AffineCipherError;

fn testEncodeError(phrase: []const u8, a: u8, b: u8) !void {
const actual = encode(testing.allocator, phrase, a, b);
defer if (actual) |slice| testing.allocator.free(slice) else |_| {};
try testing.expectError(AffineCipherError.NotCoprime, actual);
}

fn testDecodeError(phrase: []const u8, a: u8, b: u8) !void {
const actual = decode(testing.allocator, phrase, a, b);
defer if (actual) |slice| testing.allocator.free(slice) else |_| {};
try testing.expectError(AffineCipherError.NotCoprime, actual);
}
"""


def describe(case, parent):
Expand All @@ -21,10 +32,8 @@ def gen_case(case):
e = case["expected"]

if is_error(e):
return (
f" const actual = {prop}(testing.allocator, {phrase}, {a}, {b});\n"
f" try testing.expectError(AffineCipherError.NotCoprime, actual);\n"
)
helper = {"encode": "testEncodeError", "decode": "testDecodeError"}[prop]
return f" try {helper}({phrase}, {a}, {b});\n"

return (
f" const expected: []const u8 = {zstr(e)};\n"
Expand Down
18 changes: 12 additions & 6 deletions generators/exercises/intergalactic_transmission.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
from lib import is_error

HEADER = (
"const transmitSequence = intergalactic_transmission.transmitSequence;\n"
"const decodeMessage = intergalactic_transmission.decodeMessage;\n"
"const TransmissionError = intergalactic_transmission.TransmissionError;\n"
)
HEADER = """const transmitSequence = intergalactic_transmission.transmitSequence;
const decodeMessage = intergalactic_transmission.decodeMessage;
const TransmissionError = intergalactic_transmission.TransmissionError;

fn testDecodeMessageError(message: []const u8) !void {
const actual = decodeMessage(testing.allocator, message);
defer if (actual) |slice| testing.allocator.free(slice) else |_| {};
try testing.expectError(TransmissionError.WrongParity, actual);
}
"""


def _bytes_lit(values):
Expand All @@ -20,9 +25,10 @@ def gen_case(case):
msg_lit = _bytes_lit(message)

if is_error(expected):
assert prop == "decodeMessage", f"unexpected error case for {prop}"
return (
f" const message = [_]u8{msg_lit};\n"
f" try testing.expectError(TransmissionError.WrongParity, {prop}(testing.allocator, &message));\n"
" try testDecodeMessageError(&message);\n"
)

exp_lit = _bytes_lit(expected)
Expand Down
11 changes: 7 additions & 4 deletions generators/exercises/protein_translation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@
HEADER = """const proteins = protein_translation.proteins;
const Protein = protein_translation.Protein;
const TranslationError = protein_translation.TranslationError;

fn testProteinsError(strand: []const u8) !void {
const actual = proteins(testing.allocator, strand);
defer if (actual) |slice| testing.allocator.free(slice) else |_| {};
try testing.expectError(TranslationError.InvalidCodon, actual);
}
"""


def gen_case(case):
strand = zstr(case["input"]["strand"])
expected = case["expected"]
if is_error(expected):
return (
" try testing.expectError("
f"TranslationError.InvalidCodon, proteins(testing.allocator, {strand}));\n"
)
return f" try testProteinsError({strand});\n"
tags = ", ".join("." + p.lower() for p in expected)
arr = f"[_]Protein{{{tags}}}" if not tags else f"[_]Protein{{ {tags} }}"
return (
Expand Down
19 changes: 12 additions & 7 deletions generators/exercises/variable_length_quantity.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
from lib import zint, is_error

HEADER = (
"const encode = variable_length_quantity.encode;\n"
"const decode = variable_length_quantity.decode;\n"
"const DecodeError = variable_length_quantity.DecodeError;\n"
)
HEADER = """const encode = variable_length_quantity.encode;
const decode = variable_length_quantity.decode;
const DecodeError = variable_length_quantity.DecodeError;

fn testDecodeError(integers: []const u8) !void {
const actual = decode(testing.allocator, integers);
defer if (actual) |slice| testing.allocator.free(slice) else |_| {};
try testing.expectError(DecodeError.IncompleteSequence, actual);
}
"""


def describe(case, parent):
Expand All @@ -26,10 +31,10 @@ def gen_case(case):
)

if is_error(expected):
assert prop == "decode", f"unexpected error case for {prop}"
return (
f" const integers = [_]{in_ty}{integers_lit};\n"
f" const actual = {prop}(testing.allocator, &integers);\n"
f" try testing.expectError(DecodeError.IncompleteSequence, actual);\n"
" try testDecodeError(&integers);\n"
)

out_ty = "u8" if prop == "encode" else "u32"
Expand Down
Loading