diff --git a/exercises/practice/protein-translation/.meta/create_tests.py b/exercises/practice/protein-translation/.meta/create_tests.py new file mode 100644 index 00000000..42f35f9d --- /dev/null +++ b/exercises/practice/protein-translation/.meta/create_tests.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +This script can be used to generate the test file from the canonical data. + +It is currently specific to the protein translation exercise, +but should be easy to modify for other exercises. +""" + +import sys +import json +import tomllib +from string import Template +import re + +#=EXERCISE=SPECIFIC=BITS============================================================================ + +EXTERNAL_FUNCTIONS_STR = "const char **proteins(const char *rna);" +ADDITIONAL_DEFINITIONS_STR = "" + +def write_test_function(test, ignore): + return TEST_FUNCTION_TEMPLATE.substitute( + test_name=make_valid_c_function_name(test['description']), + test_ignore=IGNORE_TEST_STR if ignore else '', + rna_strand='\"' + test['input']['strand'] + '\"', + expected_size=len(test['expected']), + expected_test=EXPECTED_TEST_TEMPALTE.substitute( + expected=', '.join(['\"' + x + '\"' for x in test['expected']])) if len(test['expected']) > 0 else '' + ) + +TEST_FUNCTION_TEMPLATE = Template(""" +void test_${test_name}() {${test_ignore} + const char **names = proteins(${rna_strand}); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(${expected_size}, size);${expected_test} +} +""") + +EXPECTED_TEST_TEMPALTE = Template("""\n + const char *expected[] = {${expected}}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size);""" +) + +#=================================================================================================== + +TEST_FILE_TEMPLATE = Template(""" +// Version: 1.0.0 + +#include "vendor/unity.h" + +${external_functions} +${additional_definitions} + +void setUp(void) { +} + +void tearDown(void) { +} + +${test_defintions} + +int main(void) { + UNITY_BEGIN();${test_calls} + return UNITY_END(); +} + +""") + +TEST_CALL_TEMPLATE = Template(""" + RUN_TEST(test_${test_name});""") + +IGNORE_TEST_STR = "\n TEST_IGNORE();" + +def make_valid_c_function_name(name): + return re.sub("\W", "", name.replace(' ', '_').replace('-', '_')) + +def write_test_call(test): + return TEST_CALL_TEMPLATE.substitute(test_name = make_valid_c_function_name(test['description'])) + +def test_included(test, test_toml): + return test_toml.get(test['uuid'], {}).get('include', True) + + +if __name__ == '__main__': + if len(sys.argv) < 3 or len(sys.argv) > 4: + print('Usage: python create_tests.py [path-to-toml-file]') + sys.exit(1) + + with open(sys.argv[1], 'r') as canonical_data_json: + canonical_data = json.load(canonical_data_json) + + if len(sys.argv) == 4: + with open(sys.argv[3], 'rb') as toml_file: + test_toml = tomllib.load(toml_file) + else: + test_toml = {} + + with open(sys.argv[2], 'w') as test_file: + test_file.write(TEST_FILE_TEMPLATE.substitute( + additional_definitions=ADDITIONAL_DEFINITIONS_STR, + external_functions=EXTERNAL_FUNCTIONS_STR, + test_defintions="".join([write_test_function(test, i != 0) + for i, test in enumerate(canonical_data['cases']) if test_included(test, test_toml)]), + test_calls="".join([write_test_call(test) + for test in canonical_data['cases'] if test_included(test, test_toml)]) + )) + diff --git a/exercises/practice/protein-translation/.meta/tests.toml b/exercises/practice/protein-translation/.meta/tests.toml index 5fb18907..74700842 100644 --- a/exercises/practice/protein-translation/.meta/tests.toml +++ b/exercises/practice/protein-translation/.meta/tests.toml @@ -89,12 +89,15 @@ description = "Translation stops if STOP codon in middle of six-codon sequence" [1e75ea2a-f907-4994-ae5c-118632a1cb0f] description = "Non-existing codon can't translate" +include = false [9eac93f3-627a-4c90-8653-6d0a0595bc6f] description = "Unknown amino acids, not part of a codon, can't translate" +include = false [9d73899f-e68e-4291-b1e2-7bf87c00f024] description = "Incomplete RNA sequence can't translate" +include = false [43945cf7-9968-402d-ab9f-b8a28750b050] description = "Incomplete RNA sequence can translate if valid until a STOP codon" diff --git a/exercises/practice/protein-translation/protein_translation.asm b/exercises/practice/protein-translation/protein_translation.asm new file mode 100644 index 00000000..6c0c06cd --- /dev/null +++ b/exercises/practice/protein-translation/protein_translation.asm @@ -0,0 +1,10 @@ +section .text +global proteins +proteins: + ; Provide your implementation here + ret + +%ifidn __OUTPUT_FORMAT__,elf64 +section .note.GNU-stack noalloc noexec nowrite progbits +%endif + diff --git a/exercises/practice/protein-translation/protein_translation_test.c b/exercises/practice/protein-translation/protein_translation_test.c index ed01e567..e6993327 100644 --- a/exercises/practice/protein-translation/protein_translation_test.c +++ b/exercises/practice/protein-translation/protein_translation_test.c @@ -3,18 +3,8 @@ #include "vendor/unity.h" -extern const char **proteins(const char *rna); +const char **proteins(const char *rna); -void perform_test(const char *rna_strand, const char **expected, int expected_size) { - const char **names = proteins(rna_strand); - int size; - for (size = 0; names[size]; size++) {} - - TEST_ASSERT_EQUAL_INT(expected_size, size); - if (expected_size > 0) { - TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); - } -} void setUp(void) { } @@ -22,163 +12,345 @@ void setUp(void) { void tearDown(void) { } -void test_empty_sequence(void) { - perform_test("", NULL, 0); + +void test_Empty_RNA_sequence_results_in_no_proteins() { + const char **names = proteins(""); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(0, size); +} + +void test_Methionine_RNA_sequence() { + // TEST_IGNORE(); + const char **names = proteins("AUG"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(1, size); + + const char *expected[] = {"Methionine"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_methionine(void) { - TEST_IGNORE(); - perform_test("AUG", (const char *[]){"Methionine"}, 1); +void test_Phenylalanine_RNA_sequence_1() { + // TEST_IGNORE(); + const char **names = proteins("UUU"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(1, size); + + const char *expected[] = {"Phenylalanine"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_phenylalanine(void) { - TEST_IGNORE(); - perform_test("UUU", (const char *[]){"Phenylalanine"}, 1); +void test_Phenylalanine_RNA_sequence_2() { + // TEST_IGNORE(); + const char **names = proteins("UUC"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(1, size); + + const char *expected[] = {"Phenylalanine"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_phenylalanine_2(void) { - TEST_IGNORE(); - perform_test("UUC", (const char *[]){"Phenylalanine"}, 1); +void test_Leucine_RNA_sequence_1() { + // TEST_IGNORE(); + const char **names = proteins("UUA"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(1, size); + + const char *expected[] = {"Leucine"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_leucine(void) { - TEST_IGNORE(); - perform_test("UUA", (const char *[]){"Leucine"}, 1); +void test_Leucine_RNA_sequence_2() { + // TEST_IGNORE(); + const char **names = proteins("UUG"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(1, size); + + const char *expected[] = {"Leucine"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_leucine_2(void) { - TEST_IGNORE(); - perform_test("UUG", (const char *[]){"Leucine"}, 1); +void test_Serine_RNA_sequence_1() { + // TEST_IGNORE(); + const char **names = proteins("UCU"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(1, size); + + const char *expected[] = {"Serine"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_serine(void) { - TEST_IGNORE(); - perform_test("UCU", (const char *[]){"Serine"}, 1); +void test_Serine_RNA_sequence_2() { + // TEST_IGNORE(); + const char **names = proteins("UCC"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(1, size); + + const char *expected[] = {"Serine"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_serine_2(void) { - TEST_IGNORE(); - perform_test("UCC", (const char *[]){"Serine"}, 1); +void test_Serine_RNA_sequence_3() { + // TEST_IGNORE(); + const char **names = proteins("UCA"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(1, size); + + const char *expected[] = {"Serine"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_serine_3(void) { - TEST_IGNORE(); - perform_test("UCA", (const char *[]){"Serine"}, 1); +void test_Serine_RNA_sequence_4() { + // TEST_IGNORE(); + const char **names = proteins("UCG"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(1, size); + + const char *expected[] = {"Serine"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_serine_4(void) { - TEST_IGNORE(); - perform_test("UCG", (const char *[]){"Serine"}, 1); +void test_Tyrosine_RNA_sequence_1() { + // TEST_IGNORE(); + const char **names = proteins("UAU"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(1, size); + + const char *expected[] = {"Tyrosine"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_tyrosine(void) { - TEST_IGNORE(); - perform_test("UAU", (const char *[]){"Tyrosine"}, 1); +void test_Tyrosine_RNA_sequence_2() { + // TEST_IGNORE(); + const char **names = proteins("UAC"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(1, size); + + const char *expected[] = {"Tyrosine"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_tyrosine_2(void) { - TEST_IGNORE(); - perform_test("UAC", (const char *[]){"Tyrosine"}, 1); +void test_Cysteine_RNA_sequence_1() { + // TEST_IGNORE(); + const char **names = proteins("UGU"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(1, size); + + const char *expected[] = {"Cysteine"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_cysteine(void) { - TEST_IGNORE(); - perform_test("UGU", (const char *[]){"Cysteine"}, 1); +void test_Cysteine_RNA_sequence_2() { + // TEST_IGNORE(); + const char **names = proteins("UGC"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(1, size); + + const char *expected[] = {"Cysteine"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_cysteine_2(void) { - TEST_IGNORE(); - perform_test("UGC", (const char *[]){"Cysteine"}, 1); +void test_Tryptophan_RNA_sequence() { + // TEST_IGNORE(); + const char **names = proteins("UGG"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(1, size); + + const char *expected[] = {"Tryptophan"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_tryptophan(void) { - TEST_IGNORE(); - perform_test("UGG", (const char *[]){"Tryptophan"}, 1); +void test_STOP_codon_RNA_sequence_1() { + // TEST_IGNORE(); + const char **names = proteins("UAA"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(0, size); } -void test_stop_codon(void) { - TEST_IGNORE(); - perform_test("UAA", NULL, 0); +void test_STOP_codon_RNA_sequence_2() { + // TEST_IGNORE(); + const char **names = proteins("UAG"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(0, size); } -void test_stop_codon_2(void) { - TEST_IGNORE(); - perform_test("UAG", NULL, 0); +void test_STOP_codon_RNA_sequence_3() { + // TEST_IGNORE(); + const char **names = proteins("UGA"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(0, size); } -void test_stop_codon_3(void) { - TEST_IGNORE(); - perform_test("UGA", NULL, 0); +void test_Sequence_of_two_protein_codons_translates_into_proteins() { + // TEST_IGNORE(); + const char **names = proteins("UUUUUU"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(2, size); + + const char *expected[] = {"Phenylalanine", "Phenylalanine"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_two_identical_codons(void) { - TEST_IGNORE(); - perform_test("UUUUUU", (const char *[]){"Phenylalanine", "Phenylalanine"}, 2); +void test_Sequence_of_two_different_protein_codons_translates_into_proteins() { + // TEST_IGNORE(); + const char **names = proteins("UUAUUG"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(2, size); + + const char *expected[] = {"Leucine", "Leucine"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_two_different_codons(void) { - TEST_IGNORE(); - perform_test("UUAUUG", (const char *[]){"Leucine", "Leucine"}, 2); +void test_Translate_RNA_strand_into_correct_protein_list() { + // TEST_IGNORE(); + const char **names = proteins("AUGUUUUGG"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(3, size); + + const char *expected[] = {"Methionine", "Phenylalanine", "Tryptophan"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_three_codons(void) { - TEST_IGNORE(); - perform_test("AUGUUUUGG", (const char *[]){"Methionine", "Phenylalanine", "Tryptophan"}, 3); +void test_Translation_stops_if_STOP_codon_at_beginning_of_sequence() { + // TEST_IGNORE(); + const char **names = proteins("UAGUGG"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(0, size); } -void test_stop_after_0_of_2(void) { - TEST_IGNORE(); - perform_test("UAGUGG", NULL, 0); +void test_Translation_stops_if_STOP_codon_at_end_of_two_codon_sequence() { + // TEST_IGNORE(); + const char **names = proteins("UGGUAG"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(1, size); + + const char *expected[] = {"Tryptophan"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_stop_after_1_of_2(void) { - TEST_IGNORE(); - perform_test("UGGUAG", (const char *[]){"Tryptophan"}, 1); +void test_Translation_stops_if_STOP_codon_at_end_of_three_codon_sequence() { + // TEST_IGNORE(); + const char **names = proteins("AUGUUUUAA"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(2, size); + + const char *expected[] = {"Methionine", "Phenylalanine"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_stop_after_2_of_3(void) { - TEST_IGNORE(); - perform_test("AUGUUUUAA", (const char *[]){"Methionine", "Phenylalanine"}, 2); +void test_Translation_stops_if_STOP_codon_in_middle_of_three_codon_sequence() { + // TEST_IGNORE(); + const char **names = proteins("UGGUAGUGG"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(1, size); + + const char *expected[] = {"Tryptophan"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_stop_after_1_of_3(void) { - TEST_IGNORE(); - perform_test("UGGUAGUGG", (const char *[]){"Tryptophan"}, 1); +void test_Translation_stops_if_STOP_codon_in_middle_of_six_codon_sequence() { + // TEST_IGNORE(); + const char **names = proteins("UGGUGUUAUUAAUGGUUU"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(3, size); + + const char *expected[] = {"Tryptophan", "Cysteine", "Tyrosine"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } -void test_stop_after_3_of_6(void) { - TEST_IGNORE(); - perform_test("UGGUGUUAUUAAUGGUUU", (const char *[]){"Tryptophan", "Cysteine", "Tyrosine"}, 3); +void test_Incomplete_RNA_sequence_can_translate_if_valid_until_a_STOP_codon() { + // TEST_IGNORE(); + const char **names = proteins("UUCUUCUAAUGGU"); + + int size; + for (size = 0; names[size]; size++) {} + TEST_ASSERT_EQUAL_INT(2, size); + + const char *expected[] = {"Phenylalanine", "Phenylalanine"}; + TEST_ASSERT_EQUAL_STRING_ARRAY(expected, names, size); } + int main(void) { UNITY_BEGIN(); - RUN_TEST(test_empty_sequence); - RUN_TEST(test_empty_sequence); - RUN_TEST(test_methionine); - RUN_TEST(test_phenylalanine); - RUN_TEST(test_phenylalanine_2); - RUN_TEST(test_leucine); - RUN_TEST(test_leucine_2); - RUN_TEST(test_serine); - RUN_TEST(test_serine_2); - RUN_TEST(test_serine_3); - RUN_TEST(test_serine_4); - RUN_TEST(test_tyrosine); - RUN_TEST(test_tyrosine_2); - RUN_TEST(test_cysteine); - RUN_TEST(test_cysteine_2); - RUN_TEST(test_tryptophan); - RUN_TEST(test_stop_codon); - RUN_TEST(test_stop_codon_2); - RUN_TEST(test_stop_codon_3); - RUN_TEST(test_two_identical_codons); - RUN_TEST(test_two_different_codons); - RUN_TEST(test_three_codons); - RUN_TEST(test_stop_after_0_of_2); - RUN_TEST(test_stop_after_1_of_2); - RUN_TEST(test_stop_after_2_of_3); - RUN_TEST(test_stop_after_1_of_3); - RUN_TEST(test_stop_after_3_of_6); + RUN_TEST(test_Empty_RNA_sequence_results_in_no_proteins); + RUN_TEST(test_Methionine_RNA_sequence); + RUN_TEST(test_Phenylalanine_RNA_sequence_1); + RUN_TEST(test_Phenylalanine_RNA_sequence_2); + RUN_TEST(test_Leucine_RNA_sequence_1); + RUN_TEST(test_Leucine_RNA_sequence_2); + RUN_TEST(test_Serine_RNA_sequence_1); + RUN_TEST(test_Serine_RNA_sequence_2); + RUN_TEST(test_Serine_RNA_sequence_3); + RUN_TEST(test_Serine_RNA_sequence_4); + RUN_TEST(test_Tyrosine_RNA_sequence_1); + RUN_TEST(test_Tyrosine_RNA_sequence_2); + RUN_TEST(test_Cysteine_RNA_sequence_1); + RUN_TEST(test_Cysteine_RNA_sequence_2); + RUN_TEST(test_Tryptophan_RNA_sequence); + RUN_TEST(test_STOP_codon_RNA_sequence_1); + RUN_TEST(test_STOP_codon_RNA_sequence_2); + RUN_TEST(test_STOP_codon_RNA_sequence_3); + RUN_TEST(test_Sequence_of_two_protein_codons_translates_into_proteins); + RUN_TEST(test_Sequence_of_two_different_protein_codons_translates_into_proteins); + RUN_TEST(test_Translate_RNA_strand_into_correct_protein_list); + RUN_TEST(test_Translation_stops_if_STOP_codon_at_beginning_of_sequence); + RUN_TEST(test_Translation_stops_if_STOP_codon_at_end_of_two_codon_sequence); + RUN_TEST(test_Translation_stops_if_STOP_codon_at_end_of_three_codon_sequence); + RUN_TEST(test_Translation_stops_if_STOP_codon_in_middle_of_three_codon_sequence); + RUN_TEST(test_Translation_stops_if_STOP_codon_in_middle_of_six_codon_sequence); + RUN_TEST(test_Incomplete_RNA_sequence_can_translate_if_valid_until_a_STOP_codon); return UNITY_END(); } +