diff --git a/services/app/apps/runner/lib/runner/checker_generator.ex b/services/app/apps/runner/lib/runner/checker_generator.ex index e26d76bb0..27b7751f8 100644 --- a/services/app/apps/runner/lib/runner/checker_generator.ex +++ b/services/app/apps/runner/lib/runner/checker_generator.ex @@ -101,21 +101,6 @@ defmodule Runner.CheckerGenerator do ) end - defp get_value_expression( - signature = %{type: %{nested: _nested}}, - value, - lang_meta = %{checker_meta: checker_meta} - ) do - type_name = TypesGenerator.call(signature.type, lang_meta) - type = extract_type(signature) - value = get_value({type, value}, lang_meta) - - EEx.eval_string(checker_meta.nested_value_expression_template, - value: value, - type_name: type_name - ) - end - defp get_value_expression(signature, value, lang_meta) do type = extract_type(signature) get_value({type, value}, lang_meta) @@ -130,21 +115,6 @@ defmodule Runner.CheckerGenerator do defp get_value({%{name: "boolean"}, value}, %{checker_meta: checker_meta}), do: get_boolean_value(checker_meta.type_templates, value) - # Special case for CSharp list of lists - defp get_value( - {%{name: "array", nested: %{name: "array", nested: nested}}, [value]}, - lang_meta = %{slug: "csharp", checker_meta: checker_meta} - ) do - inner_type = TypesGenerator.call(nested, lang_meta) - array_values = Enum.map_join(value, ", ", &get_value({nested, &1}, lang_meta)) - - EEx.eval_string(checker_meta.type_templates.array_of_array, - type: inner_type, - entries: array_values, - inner_type: inner_type - ) - end - defp get_value( {%{name: "array", nested: nested}, value}, lang_meta = %{checker_meta: checker_meta} @@ -158,8 +128,12 @@ defmodule Runner.CheckerGenerator do ) end - defp get_value({signature = %{name: "hash"}, value}, lang_meta = %{checker_meta: checker_meta}) do + defp get_value( + {signature = %{name: "hash", nested: nested}, value}, + lang_meta = %{checker_meta: checker_meta} + ) do list = Map.to_list(value) + inner_type = TypesGenerator.call(nested, lang_meta) if Enum.empty?(list) do checker_meta.type_templates.hash_empty @@ -167,7 +141,10 @@ defmodule Runner.CheckerGenerator do hash_entries = Enum.map_join(list, ", ", fn item -> get_hash_inners(item, signature, lang_meta) end) - EEx.eval_string(checker_meta.type_templates.hash_value, entries: hash_entries) + EEx.eval_string(checker_meta.type_templates.hash_value, + entries: hash_entries, + inner_type: inner_type + ) end end diff --git a/services/app/apps/runner/lib/runner/languages.ex b/services/app/apps/runner/lib/runner/languages.ex index 4f29a0a29..9da5120ae 100644 --- a/services/app/apps/runner/lib/runner/languages.ex +++ b/services/app/apps/runner/lib/runner/languages.ex @@ -395,9 +395,9 @@ defmodule Runner.Languages do "integer" => "0", "float" => "0.1", "string" => "\"value\"", - "array" => "new List<<%= value %>>()", + "array" => "new()", "boolean" => "true", - "hash" => "new Dictionary>(){ {\"key\", <%= value %>} }" + "hash" => "new()" }, expected_template: " <%= type %>", types: %{ @@ -412,10 +412,10 @@ defmodule Runner.Languages do version: :static, type_templates: %{ @type_templates - | array: "{<%= entries %>}", + | array: "new() {<%= entries %>}", array_of_array: "{new List<<%= type %>> {<%= entries %>}}", - hash_empty: "{}", - hash_value: "{<%= entries %>}", + hash_empty: "new()", + hash_value: "new() {<%= entries %>}", hash_inners: "{\"<%= key %>\", <%= value %>}" }, defining_variable_template: "<%= type %> <%= name %>", @@ -437,9 +437,8 @@ defmodule Runner.Languages do // import "fmt" func solution(<%= arguments %>)<%= expected %> { - var ans <%= expected %> - ans = <%= default_value %> - return ans + var ans <%= expected %> + return ans } // <%= comment %> """, @@ -463,7 +462,11 @@ defmodule Runner.Languages do }, checker_meta: %{ version: :static, - type_templates: %{@type_templates | array: "{<%= entries %>}"}, + type_templates: %{ + @type_templates + | array: "[]<%= inner_type %>{<%= entries %>}", + hash_value: "map[string]<%= inner_type %>{<%= entries %>}" + }, defining_variable_template: "<%= name %> <%= type %>", nested_value_expression_template: "<%= type_name %><%= value %>" } diff --git a/services/app/apps/runner/test/runner/solution_generator_test.exs b/services/app/apps/runner/test/runner/solution_generator_test.exs index b7f65e2b2..0f09fa36b 100644 --- a/services/app/apps/runner/test/runner/solution_generator_test.exs +++ b/services/app/apps/runner/test/runner/solution_generator_test.exs @@ -32,7 +32,7 @@ defmodule Runner.SolutionGeneratorTest do { public List solution(int a, string text, double b, bool c, Dictionary nested_hash_of_string, List nested_array_of_string, List> nested_array_of_array_of_strings) { - List ans = new List<"value">(); + List ans = new(); return ans; } } @@ -63,9 +63,8 @@ defmodule Runner.SolutionGeneratorTest do // import "fmt" func solution(a int64, text string, b float64, c bool, nested_hash_of_string map[string]string, nested_array_of_string []string, nested_array_of_array_of_strings [][]string) []string { - var ans []string - ans = []"value"{} - return ans + var ans []string + return ans } // use stdout to debug """ diff --git a/services/app/apps/runner/test/runner/solution_generator_type_tests/cpp_type_test.exs b/services/app/apps/runner/test/runner/solution_generator_type_tests/cpp_type_test.exs new file mode 100644 index 000000000..ace45b8b1 --- /dev/null +++ b/services/app/apps/runner/test/runner/solution_generator_type_tests/cpp_type_test.exs @@ -0,0 +1,228 @@ +defmodule Runner.SolutionGeneratorTypeTests.CppTypeTest do + use ExUnit.Case, async: true + + alias Runner.Languages + alias Runner.SolutionGenerator + + # Test for string input and output + test "cpp with string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: ["hello"], + expected: "world" + } + ], + input_signature: [ + %{ + argument_name: "input_string", + type: %{name: "string"} + } + ], + output_signature: %{ + type: %{name: "string"} + } + } + + expected = """ + #include + + using namespace std; + + string solution(string input_string) { + string ans; + ans = "value"; + return ans; + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("cpp")) + end + + # Test for integer input and output + test "cpp with integer input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [42], + expected: 84 + } + ], + input_signature: [ + %{ + argument_name: "input_integer", + type: %{name: "integer"} + } + ], + output_signature: %{ + type: %{name: "integer"} + } + } + + expected = """ + #include + + using namespace std; + + int solution(int input_integer) { + int ans; + ans = 0; + return ans; + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("cpp")) + end + + # Test for array of string input and output + test "cpp with array of string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [["hello", "world"]], + expected: ["world", "hello"] + } + ], + input_signature: [ + %{ + argument_name: "input_array", + type: %{name: "array", nested: %{name: "string"}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "string"}} + } + } + + expected = """ + #include + + using namespace std; + + vector solution(vector input_array) { + vector ans; + ans = {"value"}; + return ans; + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("cpp")) + end + + # Test for hash of string input and output + test "cpp with hash of string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [%{"key1" => "value1", "key2" => "value2"}], + expected: %{"key1" => "value1", "key2" => "value2"} + } + ], + input_signature: [ + %{ + argument_name: "input_hash", + type: %{name: "hash", nested: %{name: "string"}} + } + ], + output_signature: %{ + type: %{name: "hash", nested: %{name: "string"}} + } + } + + expected = """ + #include + + using namespace std; + + map solution(map input_hash) { + map ans; + ans = {{"key", "value"}}; + return ans; + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("cpp")) + end + + # Test for nested array input and output + test "cpp with nested array input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [[["hello", "world"], ["foo", "bar"]]], + expected: [["world", "hello"], ["bar", "foo"]] + } + ], + input_signature: [ + %{ + argument_name: "input_array", + type: %{name: "array", nested: %{name: "array", nested: %{name: "string"}}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "array", nested: %{name: "string"}}} + } + } + + expected = """ + #include + + using namespace std; + + vector> solution(vector> input_array) { + vector> ans; + ans = {{"value"}}; + return ans; + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("cpp")) + end + + # Test for complex nested type + test "cpp with complex nested type input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [[%{"outer1" => %{"inner1" => ["a", "b"]}}]], + expected: [[%{"outer1" => %{"inner1" => ["A", "B"]}}]] + } + ], + input_signature: [ + %{ + argument_name: "input_complex", + type: %{name: "array", nested: %{name: "hash", nested: %{name: "hash", nested: %{name: "array", nested: %{name: "string"}}}}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "hash", nested: %{name: "hash", nested: %{name: "array", nested: %{name: "string"}}}}} + } + } + + expected = """ + #include + + using namespace std; + + vector>>> solution(vector>>> input_complex) { + vector>>> ans; + ans = {{{"key", {{"key", {"value"}}}}}}; + return ans; + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("cpp")) + end +end diff --git a/services/app/apps/runner/test/runner/solution_generator_type_tests/golang_type_test.exs b/services/app/apps/runner/test/runner/solution_generator_type_tests/golang_type_test.exs new file mode 100644 index 000000000..78fc610a5 --- /dev/null +++ b/services/app/apps/runner/test/runner/solution_generator_type_tests/golang_type_test.exs @@ -0,0 +1,216 @@ +defmodule Runner.SolutionGeneratorTypeTests.GolangTypeTest do + use ExUnit.Case, async: true + + alias Runner.Languages + alias Runner.SolutionGenerator + + # Test for string input and output + test "golang with string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: ["hello"], + expected: "world" + } + ], + input_signature: [ + %{ + argument_name: "inputString", + type: %{name: "string"} + } + ], + output_signature: %{ + type: %{name: "string"} + } + } + + expected = """ + package main + // import "fmt" + + func solution(inputString string) string { + var ans string + return ans + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("golang")) + end + + # Test for integer input and output + test "golang with integer input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [42], + expected: 84 + } + ], + input_signature: [ + %{ + argument_name: "inputInteger", + type: %{name: "integer"} + } + ], + output_signature: %{ + type: %{name: "integer"} + } + } + + expected = """ + package main + // import "fmt" + + func solution(inputInteger int64) int64 { + var ans int64 + return ans + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("golang")) + end + + # Test for array of string input and output + test "golang with array of string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [["hello", "world"]], + expected: ["world", "hello"] + } + ], + input_signature: [ + %{ + argument_name: "inputArray", + type: %{name: "array", nested: %{name: "string"}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "string"}} + } + } + + expected = """ + package main + // import "fmt" + + func solution(inputArray []string) []string { + var ans []string + return ans + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("golang")) + end + + # Test for hash of string input and output + test "golang with hash of string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [%{"key1" => "value1", "key2" => "value2"}], + expected: %{"key1" => "value1", "key2" => "value2"} + } + ], + input_signature: [ + %{ + argument_name: "inputHash", + type: %{name: "hash", nested: %{name: "string"}} + } + ], + output_signature: %{ + type: %{name: "hash", nested: %{name: "string"}} + } + } + + expected = """ + package main + // import "fmt" + + func solution(inputHash map[string]string) map[string]string { + var ans map[string]string + return ans + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("golang")) + end + + # Test for nested array input and output + test "golang with nested array input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [[["hello", "world"], ["foo", "bar"]]], + expected: [["world", "hello"], ["bar", "foo"]] + } + ], + input_signature: [ + %{ + argument_name: "inputArray", + type: %{name: "array", nested: %{name: "array", nested: %{name: "string"}}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "array", nested: %{name: "string"}}} + } + } + + expected = """ + package main + // import "fmt" + + func solution(inputArray [][]string) [][]string { + var ans [][]string + return ans + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("golang")) + end + + # Test for complex nested type + test "golang with complex nested type input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [[%{"outer1" => %{"inner1" => ["a", "b"]}}]], + expected: [[%{"outer1" => %{"inner1" => ["A", "B"]}}]] + } + ], + input_signature: [ + %{ + argument_name: "inputComplex", + type: %{name: "array", nested: %{name: "hash", nested: %{name: "hash", nested: %{name: "array", nested: %{name: "string"}}}}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "hash", nested: %{name: "hash", nested: %{name: "array", nested: %{name: "string"}}}}} + } + } + + expected = """ + package main + // import "fmt" + + func solution(inputComplex []map[string]map[string][]string) []map[string]map[string][]string { + var ans []map[string]map[string][]string + return ans + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("golang")) + end +end diff --git a/services/app/apps/runner/test/runner/solution_generator_type_tests/java_type_test.exs b/services/app/apps/runner/test/runner/solution_generator_type_tests/java_type_test.exs new file mode 100644 index 000000000..9875bf38a --- /dev/null +++ b/services/app/apps/runner/test/runner/solution_generator_type_tests/java_type_test.exs @@ -0,0 +1,240 @@ +defmodule Runner.SolutionGeneratorTypeTests.JavaTypeTest do + use ExUnit.Case, async: true + + alias Runner.Languages + alias Runner.SolutionGenerator + + # Test for string input and output + test "java with string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: ["hello"], + expected: "world" + } + ], + input_signature: [ + %{ + argument_name: "inputString", + type: %{name: "string"} + } + ], + output_signature: %{ + type: %{name: "string"} + } + } + + expected = """ + package solution; + + import java.util.*; + import java.util.stream.*; + + public class Solution { + public String solution(String inputString) { + String ans = "value"; + return ans; + } + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("java")) + end + + # Test for integer input and output + test "java with integer input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [42], + expected: 84 + } + ], + input_signature: [ + %{ + argument_name: "inputInteger", + type: %{name: "integer"} + } + ], + output_signature: %{ + type: %{name: "integer"} + } + } + + expected = """ + package solution; + + import java.util.*; + import java.util.stream.*; + + public class Solution { + public Integer solution(Integer inputInteger) { + Integer ans = 0; + return ans; + } + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("java")) + end + + # Test for array of string input and output + test "java with array of string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [["hello", "world"]], + expected: ["world", "hello"] + } + ], + input_signature: [ + %{ + argument_name: "inputArray", + type: %{name: "array", nested: %{name: "string"}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "string"}} + } + } + + expected = """ + package solution; + + import java.util.*; + import java.util.stream.*; + + public class Solution { + public List solution(List inputArray) { + List ans = List.of("value"); + return ans; + } + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("java")) + end + + # Test for hash of string input and output + test "java with hash of string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [%{"key1" => "value1", "key2" => "value2"}], + expected: %{"key1" => "value1", "key2" => "value2"} + } + ], + input_signature: [ + %{ + argument_name: "inputHash", + type: %{name: "hash", nested: %{name: "string"}} + } + ], + output_signature: %{ + type: %{name: "hash", nested: %{name: "string"}} + } + } + + expected = """ + package solution; + + import java.util.*; + import java.util.stream.*; + + public class Solution { + public Map solution(Map inputHash) { + Map ans = Map.of("key", "value"); + return ans; + } + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("java")) + end + + # Test for nested array input and output + test "java with nested array input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [[["hello", "world"], ["foo", "bar"]]], + expected: [["world", "hello"], ["bar", "foo"]] + } + ], + input_signature: [ + %{ + argument_name: "inputArray", + type: %{name: "array", nested: %{name: "array", nested: %{name: "string"}}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "array", nested: %{name: "string"}}} + } + } + + expected = """ + package solution; + + import java.util.*; + import java.util.stream.*; + + public class Solution { + public List> solution(List> inputArray) { + List> ans = List.of(List.of("value")); + return ans; + } + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("java")) + end + + # Test for complex nested type + test "java with complex nested type input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [[%{"outer1" => %{"inner1" => ["a", "b"]}}]], + expected: [[%{"outer1" => %{"inner1" => ["A", "B"]}}]] + } + ], + input_signature: [ + %{ + argument_name: "inputComplex", + type: %{name: "array", nested: %{name: "hash", nested: %{name: "hash", nested: %{name: "array", nested: %{name: "string"}}}}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "hash", nested: %{name: "hash", nested: %{name: "array", nested: %{name: "string"}}}}} + } + } + + expected = """ + package solution; + + import java.util.*; + import java.util.stream.*; + + public class Solution { + public List>>> solution(List>>> inputComplex) { + List>>> ans = List.of(Map.of("key", Map.of("key", List.of("value")))); + return ans; + } + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("java")) + end +end diff --git a/services/app/apps/runner/test/runner/solution_generator_type_tests/js_type_test.exs b/services/app/apps/runner/test/runner/solution_generator_type_tests/js_type_test.exs new file mode 100644 index 000000000..8a699596f --- /dev/null +++ b/services/app/apps/runner/test/runner/solution_generator_type_tests/js_type_test.exs @@ -0,0 +1,234 @@ +defmodule Runner.SolutionGeneratorTypeTests.JsTypeTest do + use ExUnit.Case, async: true + + alias Runner.Languages + alias Runner.SolutionGenerator + + # Test for string input and output + test "js with string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: ["hello"], + expected: "world" + } + ], + input_signature: [ + %{ + argument_name: "inputString", + type: %{name: "string"} + } + ], + output_signature: %{ + type: %{name: "string"} + } + } + + expected = """ + const _ = require("lodash"); + const R = require("rambda"); + + const solution = (inputString) => { + let ans = "value"; + + return ans; + }; + // use stdout to debug + + module.exports = solution; + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("js")) + end + + # Test for integer input and output + test "js with integer input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [42], + expected: 84 + } + ], + input_signature: [ + %{ + argument_name: "inputInteger", + type: %{name: "integer"} + } + ], + output_signature: %{ + type: %{name: "integer"} + } + } + + expected = """ + const _ = require("lodash"); + const R = require("rambda"); + + const solution = (inputInteger) => { + let ans = 0; + + return ans; + }; + // use stdout to debug + + module.exports = solution; + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("js")) + end + + # Test for array of string input and output + test "js with array of string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [["hello", "world"]], + expected: ["world", "hello"] + } + ], + input_signature: [ + %{ + argument_name: "inputArray", + type: %{name: "array", nested: %{name: "string"}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "string"}} + } + } + + expected = """ + const _ = require("lodash"); + const R = require("rambda"); + + const solution = (inputArray) => { + let ans = ["value"]; + + return ans; + }; + // use stdout to debug + + module.exports = solution; + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("js")) + end + + # Test for hash of string input and output + test "js with hash of string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [%{"key1" => "value1", "key2" => "value2"}], + expected: %{"key1" => "value1", "key2" => "value2"} + } + ], + input_signature: [ + %{ + argument_name: "inputHash", + type: %{name: "hash", nested: %{name: "string"}} + } + ], + output_signature: %{ + type: %{name: "hash", nested: %{name: "string"}} + } + } + + expected = """ + const _ = require("lodash"); + const R = require("rambda"); + + const solution = (inputHash) => { + let ans = {"key": "value"}; + + return ans; + }; + // use stdout to debug + + module.exports = solution; + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("js")) + end + + # Test for nested array input and output + test "js with nested array input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [[["hello", "world"], ["foo", "bar"]]], + expected: [["world", "hello"], ["bar", "foo"]] + } + ], + input_signature: [ + %{ + argument_name: "inputArray", + type: %{name: "array", nested: %{name: "array", nested: %{name: "string"}}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "array", nested: %{name: "string"}}} + } + } + + expected = """ + const _ = require("lodash"); + const R = require("rambda"); + + const solution = (inputArray) => { + let ans = [["value"]]; + + return ans; + }; + // use stdout to debug + + module.exports = solution; + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("js")) + end + + # Test for complex nested type + test "js with complex nested type input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [[%{"outer1" => %{"inner1" => ["a", "b"]}}]], + expected: [[%{"outer1" => %{"inner1" => ["A", "B"]}}]] + } + ], + input_signature: [ + %{ + argument_name: "inputComplex", + type: %{name: "array", nested: %{name: "hash", nested: %{name: "hash", nested: %{name: "array", nested: %{name: "string"}}}}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "hash", nested: %{name: "hash", nested: %{name: "array", nested: %{name: "string"}}}}} + } + } + + expected = """ + const _ = require("lodash"); + const R = require("rambda"); + + const solution = (inputComplex) => { + let ans = [{"key": {"key": ["value"]}}]; + + return ans; + }; + // use stdout to debug + + module.exports = solution; + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("js")) + end +end diff --git a/services/app/apps/runner/test/runner/solution_generator_type_tests/python_type_test.exs b/services/app/apps/runner/test/runner/solution_generator_type_tests/python_type_test.exs new file mode 100644 index 000000000..331974924 --- /dev/null +++ b/services/app/apps/runner/test/runner/solution_generator_type_tests/python_type_test.exs @@ -0,0 +1,204 @@ +defmodule Runner.SolutionGeneratorTypeTests.PythonTypeTest do + use ExUnit.Case, async: true + + alias Runner.Languages + alias Runner.SolutionGenerator + + # Test for string input and output + test "python with string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: ["hello"], + expected: "world" + } + ], + input_signature: [ + %{ + argument_name: "input_string", + type: %{name: "string"} + } + ], + output_signature: %{ + type: %{name: "string"} + } + } + + expected = """ + from typing import List, Dict + + def solution(input_string: str) -> str: + ans = "value" + return ans + # use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("python")) + end + + # Test for integer input and output + test "python with integer input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [42], + expected: 84 + } + ], + input_signature: [ + %{ + argument_name: "input_integer", + type: %{name: "integer"} + } + ], + output_signature: %{ + type: %{name: "integer"} + } + } + + expected = """ + from typing import List, Dict + + def solution(input_integer: int) -> int: + ans = 0 + return ans + # use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("python")) + end + + # Test for array of string input and output + test "python with array of string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [["hello", "world"]], + expected: ["world", "hello"] + } + ], + input_signature: [ + %{ + argument_name: "input_array", + type: %{name: "array", nested: %{name: "string"}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "string"}} + } + } + + expected = """ + from typing import List, Dict + + def solution(input_array: List[str]) -> List[str]: + ans = ["value"] + return ans + # use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("python")) + end + + # Test for hash of string input and output + test "python with hash of string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [%{"key1" => "value1", "key2" => "value2"}], + expected: %{"key1" => "value1", "key2" => "value2"} + } + ], + input_signature: [ + %{ + argument_name: "input_hash", + type: %{name: "hash", nested: %{name: "string"}} + } + ], + output_signature: %{ + type: %{name: "hash", nested: %{name: "string"}} + } + } + + expected = """ + from typing import List, Dict + + def solution(input_hash: Dict[str, str]) -> Dict[str, str]: + ans = {"key": "value"} + return ans + # use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("python")) + end + + # Test for nested array input and output + test "python with nested array input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [[["hello", "world"], ["foo", "bar"]]], + expected: [["world", "hello"], ["bar", "foo"]] + } + ], + input_signature: [ + %{ + argument_name: "input_array", + type: %{name: "array", nested: %{name: "array", nested: %{name: "string"}}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "array", nested: %{name: "string"}}} + } + } + + expected = """ + from typing import List, Dict + + def solution(input_array: List[List[str]]) -> List[List[str]]: + ans = [["value"]] + return ans + # use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("python")) + end + + # Test for complex nested type + test "python with complex nested type input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [[%{"outer1" => %{"inner1" => ["a", "b"]}}]], + expected: [[%{"outer1" => %{"inner1" => ["A", "B"]}}]] + } + ], + input_signature: [ + %{ + argument_name: "input_complex", + type: %{name: "array", nested: %{name: "hash", nested: %{name: "hash", nested: %{name: "array", nested: %{name: "string"}}}}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "hash", nested: %{name: "hash", nested: %{name: "array", nested: %{name: "string"}}}}} + } + } + + expected = """ + from typing import List, Dict + + def solution(input_complex: List[Dict[str, Dict[str, List[str]]]]) -> List[Dict[str, Dict[str, List[str]]]]: + ans = [{"key": {"key": ["value"]}}] + return ans + # use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("python")) + end +end diff --git a/services/app/apps/runner/test/runner/solution_generator_type_tests/ruby_type_test.exs b/services/app/apps/runner/test/runner/solution_generator_type_tests/ruby_type_test.exs new file mode 100644 index 000000000..493f403f6 --- /dev/null +++ b/services/app/apps/runner/test/runner/solution_generator_type_tests/ruby_type_test.exs @@ -0,0 +1,198 @@ +defmodule Runner.SolutionGeneratorTypeTests.RubyTypeTest do + use ExUnit.Case, async: true + + alias Runner.Languages + alias Runner.SolutionGenerator + + # Test for string input and output + test "ruby with string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: ["hello"], + expected: "world" + } + ], + input_signature: [ + %{ + argument_name: "input_string", + type: %{name: "string"} + } + ], + output_signature: %{ + type: %{name: "string"} + } + } + + expected = """ + def solution(input_string) + ans = "value" + return ans + end + # use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("ruby")) + end + + # Test for integer input and output + test "ruby with integer input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [42], + expected: 84 + } + ], + input_signature: [ + %{ + argument_name: "input_integer", + type: %{name: "integer"} + } + ], + output_signature: %{ + type: %{name: "integer"} + } + } + + expected = """ + def solution(input_integer) + ans = 0 + return ans + end + # use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("ruby")) + end + + # Test for array of string input and output + test "ruby with array of string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [["hello", "world"]], + expected: ["world", "hello"] + } + ], + input_signature: [ + %{ + argument_name: "input_array", + type: %{name: "array", nested: %{name: "string"}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "string"}} + } + } + + expected = """ + def solution(input_array) + ans = ["value"] + return ans + end + # use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("ruby")) + end + + # Test for hash of string input and output + test "ruby with hash of string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [%{"key1" => "value1", "key2" => "value2"}], + expected: %{"key1" => "value1", "key2" => "value2"} + } + ], + input_signature: [ + %{ + argument_name: "input_hash", + type: %{name: "hash", nested: %{name: "string"}} + } + ], + output_signature: %{ + type: %{name: "hash", nested: %{name: "string"}} + } + } + + expected = """ + def solution(input_hash) + ans = {"key" => "value"} + return ans + end + # use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("ruby")) + end + + # Test for nested array input and output + test "ruby with nested array input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [[["hello", "world"], ["foo", "bar"]]], + expected: [["world", "hello"], ["bar", "foo"]] + } + ], + input_signature: [ + %{ + argument_name: "input_array", + type: %{name: "array", nested: %{name: "array", nested: %{name: "string"}}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "array", nested: %{name: "string"}}} + } + } + + expected = """ + def solution(input_array) + ans = [["value"]] + return ans + end + # use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("ruby")) + end + + # Test for complex nested type + test "ruby with complex nested type input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [[%{"outer1" => %{"inner1" => ["a", "b"]}}]], + expected: [[%{"outer1" => %{"inner1" => ["A", "B"]}}]] + } + ], + input_signature: [ + %{ + argument_name: "input_complex", + type: %{name: "array", nested: %{name: "hash", nested: %{name: "hash", nested: %{name: "array", nested: %{name: "string"}}}}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "hash", nested: %{name: "hash", nested: %{name: "array", nested: %{name: "string"}}}}} + } + } + + expected = """ + def solution(input_complex) + ans = [{"key" => {"key" => ["value"]}}] + return ans + end + # use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("ruby")) + end +end diff --git a/services/app/apps/runner/test/runner/solution_generator_type_tests/rust_type_test.exs b/services/app/apps/runner/test/runner/solution_generator_type_tests/rust_type_test.exs new file mode 100644 index 000000000..27418272c --- /dev/null +++ b/services/app/apps/runner/test/runner/solution_generator_type_tests/rust_type_test.exs @@ -0,0 +1,210 @@ +defmodule Runner.SolutionGeneratorTypeTests.RustTypeTest do + use ExUnit.Case, async: true + + alias Runner.Languages + alias Runner.SolutionGenerator + + # Test for string input and output + test "rust with string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: ["hello"], + expected: "world" + } + ], + input_signature: [ + %{ + argument_name: "input_string", + type: %{name: "string"} + } + ], + output_signature: %{ + type: %{name: "string"} + } + } + + expected = """ + use std::collections::HashMap; + + pub fn solution(input_string: String) -> String { + let mut ans: String = String::from("value"); + return ans; + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("rust")) + end + + # Test for integer input and output + test "rust with integer input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [42], + expected: 84 + } + ], + input_signature: [ + %{ + argument_name: "input_integer", + type: %{name: "integer"} + } + ], + output_signature: %{ + type: %{name: "integer"} + } + } + + expected = """ + use std::collections::HashMap; + + pub fn solution(input_integer: i64) -> i64 { + let mut ans: i64 = 0; + return ans; + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("rust")) + end + + # Test for array of string input and output + test "rust with array of string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [["hello", "world"]], + expected: ["world", "hello"] + } + ], + input_signature: [ + %{ + argument_name: "input_array", + type: %{name: "array", nested: %{name: "string"}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "string"}} + } + } + + expected = """ + use std::collections::HashMap; + + pub fn solution(input_array: Vec) -> Vec { + let mut ans: Vec = vec![String::from("value")]; + return ans; + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("rust")) + end + + # Test for hash of string input and output + test "rust with hash of string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [%{"key1" => "value1", "key2" => "value2"}], + expected: %{"key1" => "value1", "key2" => "value2"} + } + ], + input_signature: [ + %{ + argument_name: "input_hash", + type: %{name: "hash", nested: %{name: "string"}} + } + ], + output_signature: %{ + type: %{name: "hash", nested: %{name: "string"}} + } + } + + expected = """ + use std::collections::HashMap; + + pub fn solution(input_hash: HashMap) -> HashMap { + let mut ans: HashMap = HashMap::from([(String::from("key"), String::from("value"))]); + return ans; + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("rust")) + end + + # Test for nested array input and output + test "rust with nested array input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [[["hello", "world"], ["foo", "bar"]]], + expected: [["world", "hello"], ["bar", "foo"]] + } + ], + input_signature: [ + %{ + argument_name: "input_array", + type: %{name: "array", nested: %{name: "array", nested: %{name: "string"}}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "array", nested: %{name: "string"}}} + } + } + + expected = """ + use std::collections::HashMap; + + pub fn solution(input_array: Vec>) -> Vec> { + let mut ans: Vec> = vec![vec![String::from("value")]]; + return ans; + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("rust")) + end + + # Test for complex nested type + test "rust with complex nested type input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [[%{"outer1" => %{"inner1" => ["a", "b"]}}]], + expected: [[%{"outer1" => %{"inner1" => ["A", "B"]}}]] + } + ], + input_signature: [ + %{ + argument_name: "input_complex", + type: %{name: "array", nested: %{name: "hash", nested: %{name: "hash", nested: %{name: "array", nested: %{name: "string"}}}}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "hash", nested: %{name: "hash", nested: %{name: "array", nested: %{name: "string"}}}}} + } + } + + expected = """ + use std::collections::HashMap; + + pub fn solution(input_complex: Vec>>>) -> Vec>>> { + let mut ans: Vec>>> = vec![HashMap::from([(String::from("key"), HashMap::from([(String::from("key"), vec![String::from("value")])]))])]; + return ans; + } + // use stdout to debug + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("rust")) + end +end diff --git a/services/app/apps/runner/test/runner/solution_generator_type_tests/typescript_type_test.exs b/services/app/apps/runner/test/runner/solution_generator_type_tests/typescript_type_test.exs new file mode 100644 index 000000000..045db039e --- /dev/null +++ b/services/app/apps/runner/test/runner/solution_generator_type_tests/typescript_type_test.exs @@ -0,0 +1,234 @@ +defmodule Runner.SolutionGeneratorTypeTests.TypescriptTypeTest do + use ExUnit.Case, async: true + + alias Runner.Languages + alias Runner.SolutionGenerator + + # Test for string input and output + test "typescript with string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: ["hello"], + expected: "world" + } + ], + input_signature: [ + %{ + argument_name: "inputString", + type: %{name: "string"} + } + ], + output_signature: %{ + type: %{name: "string"} + } + } + + expected = """ + import * as _ from "lodash"; + import * as R from "rambda"; + + function solution(inputString: string): string { + let ans = "value"; + return ans; + }; + + // use stdout to debug + + export default solution; + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("ts")) + end + + # Test for integer input and output + test "typescript with integer input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [42], + expected: 84 + } + ], + input_signature: [ + %{ + argument_name: "inputInteger", + type: %{name: "integer"} + } + ], + output_signature: %{ + type: %{name: "integer"} + } + } + + expected = """ + import * as _ from "lodash"; + import * as R from "rambda"; + + function solution(inputInteger: number): number { + let ans = 0; + return ans; + }; + + // use stdout to debug + + export default solution; + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("ts")) + end + + # Test for array of string input and output + test "typescript with array of string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [["hello", "world"]], + expected: ["world", "hello"] + } + ], + input_signature: [ + %{ + argument_name: "inputArray", + type: %{name: "array", nested: %{name: "string"}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "string"}} + } + } + + expected = """ + import * as _ from "lodash"; + import * as R from "rambda"; + + function solution(inputArray: Array): Array { + let ans = ["value"]; + return ans; + }; + + // use stdout to debug + + export default solution; + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("ts")) + end + + # Test for hash of string input and output + test "typescript with hash of string input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [%{"key1" => "value1", "key2" => "value2"}], + expected: %{"key1" => "value1", "key2" => "value2"} + } + ], + input_signature: [ + %{ + argument_name: "inputHash", + type: %{name: "hash", nested: %{name: "string"}} + } + ], + output_signature: %{ + type: %{name: "hash", nested: %{name: "string"}} + } + } + + expected = """ + import * as _ from "lodash"; + import * as R from "rambda"; + + function solution(inputHash: any): any { + let ans = { key: "value" }; + return ans; + }; + + // use stdout to debug + + export default solution; + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("ts")) + end + + # Test for nested array input and output + test "typescript with nested array input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [[["hello", "world"], ["foo", "bar"]]], + expected: [["world", "hello"], ["bar", "foo"]] + } + ], + input_signature: [ + %{ + argument_name: "inputArray", + type: %{name: "array", nested: %{name: "array", nested: %{name: "string"}}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "array", nested: %{name: "string"}}} + } + } + + expected = """ + import * as _ from "lodash"; + import * as R from "rambda"; + + function solution(inputArray: Array>): Array> { + let ans = [["value"]]; + return ans; + }; + + // use stdout to debug + + export default solution; + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("ts")) + end + + # Test for complex nested type + test "typescript with complex nested type input and output" do + task = %Runner.Task{ + asserts: [ + %{ + arguments: [[%{"outer1" => %{"inner1" => ["a", "b"]}}]], + expected: [[%{"outer1" => %{"inner1" => ["A", "B"]}}]] + } + ], + input_signature: [ + %{ + argument_name: "inputComplex", + type: %{name: "array", nested: %{name: "hash", nested: %{name: "hash", nested: %{name: "array", nested: %{name: "string"}}}}} + } + ], + output_signature: %{ + type: %{name: "array", nested: %{name: "hash", nested: %{name: "hash", nested: %{name: "array", nested: %{name: "string"}}}}} + } + } + + expected = """ + import * as _ from "lodash"; + import * as R from "rambda"; + + function solution(inputComplex: Array): Array { + let ans = [{ key: { key: ["value"] } }]; + return ans; + }; + + // use stdout to debug + + export default solution; + """ + + assert String.trim_trailing(expected, "\n") == + SolutionGenerator.call(task, Languages.meta("ts")) + end +end