From e16612a7cf2d6cd9138aafdec20958452be3b611 Mon Sep 17 00:00:00 2001 From: Simon Gene Gottlieb Date: Thu, 28 Sep 2023 10:23:16 +0200 Subject: [PATCH] tests: add cpp generation tests This adds common code generation cases with a small schema salad description and the expected generated file. --- MANIFEST.in | 1 + .../tests/cpp_tests/01_single_record.h | 169 ++++++++++++++ .../tests/cpp_tests/01_single_record.yml | 5 + schema_salad/tests/cpp_tests/02_two_records.h | 183 +++++++++++++++ .../tests/cpp_tests/02_two_records.yml | 10 + .../tests/cpp_tests/03_simple_inheritance.h | 185 ++++++++++++++++ .../tests/cpp_tests/03_simple_inheritance.yml | 11 + .../tests/cpp_tests/04_abstract_inheritance.h | 187 ++++++++++++++++ .../cpp_tests/04_abstract_inheritance.yml | 12 + .../tests/cpp_tests/05_specialization.h | 209 ++++++++++++++++++ .../tests/cpp_tests/05_specialization.yml | 21 ++ schema_salad/tests/test_cpp_codegen.py | 21 ++ schema_salad/tests/test_subtypes.py | 1 + setup.py | 1 + 14 files changed, 1016 insertions(+) create mode 100644 schema_salad/tests/cpp_tests/01_single_record.h create mode 100644 schema_salad/tests/cpp_tests/01_single_record.yml create mode 100644 schema_salad/tests/cpp_tests/02_two_records.h create mode 100644 schema_salad/tests/cpp_tests/02_two_records.yml create mode 100644 schema_salad/tests/cpp_tests/03_simple_inheritance.h create mode 100644 schema_salad/tests/cpp_tests/03_simple_inheritance.yml create mode 100644 schema_salad/tests/cpp_tests/04_abstract_inheritance.h create mode 100644 schema_salad/tests/cpp_tests/04_abstract_inheritance.yml create mode 100644 schema_salad/tests/cpp_tests/05_specialization.h create mode 100644 schema_salad/tests/cpp_tests/05_specialization.yml diff --git a/MANIFEST.in b/MANIFEST.in index b46f6eeff..b7c170bdf 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -8,6 +8,7 @@ include schema_salad/tests/* include schema_salad/tests/test_schema/*.md include schema_salad/tests/test_schema/*.yml include schema_salad/tests/test_schema/*.cwl +recursive-include schema_salad/tests/cpp_tests *.h *.yml include schema_salad/tests/foreign/*.cwl recursive-include schema_salad/tests/test_real_cwl * include schema_salad/metaschema/* diff --git a/schema_salad/tests/cpp_tests/01_single_record.h b/schema_salad/tests/cpp_tests/01_single_record.h new file mode 100644 index 000000000..4b50c17be --- /dev/null +++ b/schema_salad/tests/cpp_tests/01_single_record.h @@ -0,0 +1,169 @@ +#pragma once + +// Generated by schema-salad code generator + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +inline auto mergeYaml(YAML::Node n1, YAML::Node n2) { + for (auto const& e : n1) { + n2[e.first.as()] = e.second; + } + return n2; +} + +// declaring toYaml +inline auto toYaml(bool v) { + return YAML::Node{v}; +} +inline auto toYaml(float v) { + return YAML::Node{v}; +} +inline auto toYaml(double v) { + return YAML::Node{v}; +} +inline auto toYaml(int32_t v) { + return YAML::Node{v}; +} +inline auto toYaml(int64_t v) { + return YAML::Node{v}; +} +inline auto toYaml(std::any const&) { + return YAML::Node{}; +} +inline auto toYaml(std::monostate const&) { + return YAML::Node(YAML::NodeType::Undefined); +} + +inline auto toYaml(std::string const& v) { + return YAML::Node{v}; +} + +inline void addYamlField(YAML::Node& node, std::string const& key, YAML::Node value) { + if (value.IsDefined()) { + node[key] = value; + } +} + +inline auto convertListToMap(YAML::Node list, std::string const& key_name) { + if (list.size() == 0) return list; + auto map = YAML::Node{}; + for (YAML::Node n : list) { + auto key = n[key_name].as(); + n.remove(key_name); + map[key] = n; + } + return map; +} + +// fwd declaring toYaml +template +auto toYaml(std::vector const& v) -> YAML::Node; +template +auto toYaml(T const& t) -> YAML::Node; +template +auto toYaml(std::variant const& t) -> YAML::Node; + +template +class heap_object { + std::unique_ptr data = std::make_unique(); +public: + heap_object() = default; + heap_object(heap_object const& oth) { + *data = *oth; + } + heap_object(heap_object&& oth) { + *data = *oth; + } + + template + heap_object(T2 const& oth) { + *data = oth; + } + template + heap_object(T2&& oth) { + *data = oth; + } + + auto operator=(heap_object const& oth) -> heap_object& { + *data = *oth; + return *this; + } + auto operator=(heap_object&& oth) -> heap_object& { + *data = std::move(*oth); + return *this; + } + + template + auto operator=(T2 const& oth) -> heap_object& { + *data = oth; + return *this; + } + template + auto operator=(T2&& oth) -> heap_object& { + *data = std::move(oth); + return *this; + } + + auto operator->() -> T* { + return data.get(); + } + auto operator->() const -> T const* { + return data.get(); + } + auto operator*() -> T& { + return *data; + } + auto operator*() const -> T const& { + return *data; + } + +}; + +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_01_single_record_yml { struct MyRecord; } +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_01_single_record_yml { +struct MyRecord { + heap_object name; + virtual auto toYaml() const -> YAML::Node; +}; +} + +inline auto file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_01_single_record_yml::MyRecord::toYaml() const -> YAML::Node { + using ::toYaml; + auto n = YAML::Node{}; + addYamlField(n, "name", toYaml(*name)); + return n; +} + +template +auto toYaml(std::vector const& v) -> YAML::Node { + auto n = YAML::Node(YAML::NodeType::Sequence); + for (auto const& e : v) { + n.push_back(toYaml(e)); + } + return n; +} + +template +auto toYaml(T const& t) -> YAML::Node { + if constexpr (std::is_enum_v) { + return toYaml(t); + } else { + return t.toYaml(); + } +} + +template +auto toYaml(std::variant const& t) -> YAML::Node { + return std::visit([](auto const& e) { + return toYaml(e); + }, t); +} diff --git a/schema_salad/tests/cpp_tests/01_single_record.yml b/schema_salad/tests/cpp_tests/01_single_record.yml new file mode 100644 index 000000000..dd56da5c3 --- /dev/null +++ b/schema_salad/tests/cpp_tests/01_single_record.yml @@ -0,0 +1,5 @@ +- name: MyRecord + doc: A simple record with a single field + type: record + fields: + name: string diff --git a/schema_salad/tests/cpp_tests/02_two_records.h b/schema_salad/tests/cpp_tests/02_two_records.h new file mode 100644 index 000000000..83e6a1899 --- /dev/null +++ b/schema_salad/tests/cpp_tests/02_two_records.h @@ -0,0 +1,183 @@ +#pragma once + +// Generated by schema-salad code generator + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +inline auto mergeYaml(YAML::Node n1, YAML::Node n2) { + for (auto const& e : n1) { + n2[e.first.as()] = e.second; + } + return n2; +} + +// declaring toYaml +inline auto toYaml(bool v) { + return YAML::Node{v}; +} +inline auto toYaml(float v) { + return YAML::Node{v}; +} +inline auto toYaml(double v) { + return YAML::Node{v}; +} +inline auto toYaml(int32_t v) { + return YAML::Node{v}; +} +inline auto toYaml(int64_t v) { + return YAML::Node{v}; +} +inline auto toYaml(std::any const&) { + return YAML::Node{}; +} +inline auto toYaml(std::monostate const&) { + return YAML::Node(YAML::NodeType::Undefined); +} + +inline auto toYaml(std::string const& v) { + return YAML::Node{v}; +} + +inline void addYamlField(YAML::Node& node, std::string const& key, YAML::Node value) { + if (value.IsDefined()) { + node[key] = value; + } +} + +inline auto convertListToMap(YAML::Node list, std::string const& key_name) { + if (list.size() == 0) return list; + auto map = YAML::Node{}; + for (YAML::Node n : list) { + auto key = n[key_name].as(); + n.remove(key_name); + map[key] = n; + } + return map; +} + +// fwd declaring toYaml +template +auto toYaml(std::vector const& v) -> YAML::Node; +template +auto toYaml(T const& t) -> YAML::Node; +template +auto toYaml(std::variant const& t) -> YAML::Node; + +template +class heap_object { + std::unique_ptr data = std::make_unique(); +public: + heap_object() = default; + heap_object(heap_object const& oth) { + *data = *oth; + } + heap_object(heap_object&& oth) { + *data = *oth; + } + + template + heap_object(T2 const& oth) { + *data = oth; + } + template + heap_object(T2&& oth) { + *data = oth; + } + + auto operator=(heap_object const& oth) -> heap_object& { + *data = *oth; + return *this; + } + auto operator=(heap_object&& oth) -> heap_object& { + *data = std::move(*oth); + return *this; + } + + template + auto operator=(T2 const& oth) -> heap_object& { + *data = oth; + return *this; + } + template + auto operator=(T2&& oth) -> heap_object& { + *data = std::move(oth); + return *this; + } + + auto operator->() -> T* { + return data.get(); + } + auto operator->() const -> T const* { + return data.get(); + } + auto operator*() -> T& { + return *data; + } + auto operator*() const -> T const& { + return *data; + } + +}; + +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_02_two_records_yml { struct MyRecordOne; } +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_02_two_records_yml { struct MyRecordTwo; } +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_02_two_records_yml { +struct MyRecordOne { + heap_object name; + virtual auto toYaml() const -> YAML::Node; +}; +} + +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_02_two_records_yml { +struct MyRecordTwo { + heap_object value; + virtual auto toYaml() const -> YAML::Node; +}; +} + +inline auto file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_02_two_records_yml::MyRecordOne::toYaml() const -> YAML::Node { + using ::toYaml; + auto n = YAML::Node{}; + addYamlField(n, "name", toYaml(*name)); + return n; +} +inline auto file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_02_two_records_yml::MyRecordTwo::toYaml() const -> YAML::Node { + using ::toYaml; + auto n = YAML::Node{}; + addYamlField(n, "value", toYaml(*value)); + return n; +} + +template +auto toYaml(std::vector const& v) -> YAML::Node { + auto n = YAML::Node(YAML::NodeType::Sequence); + for (auto const& e : v) { + n.push_back(toYaml(e)); + } + return n; +} + +template +auto toYaml(T const& t) -> YAML::Node { + if constexpr (std::is_enum_v) { + return toYaml(t); + } else { + return t.toYaml(); + } +} + +template +auto toYaml(std::variant const& t) -> YAML::Node { + return std::visit([](auto const& e) { + return toYaml(e); + }, t); +} diff --git a/schema_salad/tests/cpp_tests/02_two_records.yml b/schema_salad/tests/cpp_tests/02_two_records.yml new file mode 100644 index 000000000..a2641b539 --- /dev/null +++ b/schema_salad/tests/cpp_tests/02_two_records.yml @@ -0,0 +1,10 @@ +- name: MyRecordOne + doc: Number One Record + type: record + fields: + name: string +- name: MyRecordTwo + doc: Number Two Record + type: record + fields: + value: int diff --git a/schema_salad/tests/cpp_tests/03_simple_inheritance.h b/schema_salad/tests/cpp_tests/03_simple_inheritance.h new file mode 100644 index 000000000..7d2d9bde5 --- /dev/null +++ b/schema_salad/tests/cpp_tests/03_simple_inheritance.h @@ -0,0 +1,185 @@ +#pragma once + +// Generated by schema-salad code generator + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +inline auto mergeYaml(YAML::Node n1, YAML::Node n2) { + for (auto const& e : n1) { + n2[e.first.as()] = e.second; + } + return n2; +} + +// declaring toYaml +inline auto toYaml(bool v) { + return YAML::Node{v}; +} +inline auto toYaml(float v) { + return YAML::Node{v}; +} +inline auto toYaml(double v) { + return YAML::Node{v}; +} +inline auto toYaml(int32_t v) { + return YAML::Node{v}; +} +inline auto toYaml(int64_t v) { + return YAML::Node{v}; +} +inline auto toYaml(std::any const&) { + return YAML::Node{}; +} +inline auto toYaml(std::monostate const&) { + return YAML::Node(YAML::NodeType::Undefined); +} + +inline auto toYaml(std::string const& v) { + return YAML::Node{v}; +} + +inline void addYamlField(YAML::Node& node, std::string const& key, YAML::Node value) { + if (value.IsDefined()) { + node[key] = value; + } +} + +inline auto convertListToMap(YAML::Node list, std::string const& key_name) { + if (list.size() == 0) return list; + auto map = YAML::Node{}; + for (YAML::Node n : list) { + auto key = n[key_name].as(); + n.remove(key_name); + map[key] = n; + } + return map; +} + +// fwd declaring toYaml +template +auto toYaml(std::vector const& v) -> YAML::Node; +template +auto toYaml(T const& t) -> YAML::Node; +template +auto toYaml(std::variant const& t) -> YAML::Node; + +template +class heap_object { + std::unique_ptr data = std::make_unique(); +public: + heap_object() = default; + heap_object(heap_object const& oth) { + *data = *oth; + } + heap_object(heap_object&& oth) { + *data = *oth; + } + + template + heap_object(T2 const& oth) { + *data = oth; + } + template + heap_object(T2&& oth) { + *data = oth; + } + + auto operator=(heap_object const& oth) -> heap_object& { + *data = *oth; + return *this; + } + auto operator=(heap_object&& oth) -> heap_object& { + *data = std::move(*oth); + return *this; + } + + template + auto operator=(T2 const& oth) -> heap_object& { + *data = oth; + return *this; + } + template + auto operator=(T2&& oth) -> heap_object& { + *data = std::move(oth); + return *this; + } + + auto operator->() -> T* { + return data.get(); + } + auto operator->() const -> T const* { + return data.get(); + } + auto operator*() -> T& { + return *data; + } + auto operator*() const -> T const& { + return *data; + } + +}; + +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_03_simple_inheritance_yml { struct MyRecordOne; } +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_03_simple_inheritance_yml { struct MyRecordTwo; } +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_03_simple_inheritance_yml { +struct MyRecordOne { + heap_object name; + virtual auto toYaml() const -> YAML::Node; +}; +} + +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_03_simple_inheritance_yml { +struct MyRecordTwo + : file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_03_simple_inheritance_yml::MyRecordOne { + heap_object value; + auto toYaml() const -> YAML::Node override; +}; +} + +inline auto file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_03_simple_inheritance_yml::MyRecordOne::toYaml() const -> YAML::Node { + using ::toYaml; + auto n = YAML::Node{}; + addYamlField(n, "name", toYaml(*name)); + return n; +} +inline auto file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_03_simple_inheritance_yml::MyRecordTwo::toYaml() const -> YAML::Node { + using ::toYaml; + auto n = YAML::Node{}; + n = mergeYaml(n, file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_03_simple_inheritance_yml::MyRecordOne::toYaml()); + addYamlField(n, "value", toYaml(*value)); + return n; +} + +template +auto toYaml(std::vector const& v) -> YAML::Node { + auto n = YAML::Node(YAML::NodeType::Sequence); + for (auto const& e : v) { + n.push_back(toYaml(e)); + } + return n; +} + +template +auto toYaml(T const& t) -> YAML::Node { + if constexpr (std::is_enum_v) { + return toYaml(t); + } else { + return t.toYaml(); + } +} + +template +auto toYaml(std::variant const& t) -> YAML::Node { + return std::visit([](auto const& e) { + return toYaml(e); + }, t); +} diff --git a/schema_salad/tests/cpp_tests/03_simple_inheritance.yml b/schema_salad/tests/cpp_tests/03_simple_inheritance.yml new file mode 100644 index 000000000..d14219060 --- /dev/null +++ b/schema_salad/tests/cpp_tests/03_simple_inheritance.yml @@ -0,0 +1,11 @@ +- name: MyRecordOne + doc: Number One Record + type: record + fields: + name: string +- name: MyRecordTwo + extends: [MyRecordOne] + doc: Number Two Record + type: record + fields: + value: int diff --git a/schema_salad/tests/cpp_tests/04_abstract_inheritance.h b/schema_salad/tests/cpp_tests/04_abstract_inheritance.h new file mode 100644 index 000000000..b84d52135 --- /dev/null +++ b/schema_salad/tests/cpp_tests/04_abstract_inheritance.h @@ -0,0 +1,187 @@ +#pragma once + +// Generated by schema-salad code generator + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +inline auto mergeYaml(YAML::Node n1, YAML::Node n2) { + for (auto const& e : n1) { + n2[e.first.as()] = e.second; + } + return n2; +} + +// declaring toYaml +inline auto toYaml(bool v) { + return YAML::Node{v}; +} +inline auto toYaml(float v) { + return YAML::Node{v}; +} +inline auto toYaml(double v) { + return YAML::Node{v}; +} +inline auto toYaml(int32_t v) { + return YAML::Node{v}; +} +inline auto toYaml(int64_t v) { + return YAML::Node{v}; +} +inline auto toYaml(std::any const&) { + return YAML::Node{}; +} +inline auto toYaml(std::monostate const&) { + return YAML::Node(YAML::NodeType::Undefined); +} + +inline auto toYaml(std::string const& v) { + return YAML::Node{v}; +} + +inline void addYamlField(YAML::Node& node, std::string const& key, YAML::Node value) { + if (value.IsDefined()) { + node[key] = value; + } +} + +inline auto convertListToMap(YAML::Node list, std::string const& key_name) { + if (list.size() == 0) return list; + auto map = YAML::Node{}; + for (YAML::Node n : list) { + auto key = n[key_name].as(); + n.remove(key_name); + map[key] = n; + } + return map; +} + +// fwd declaring toYaml +template +auto toYaml(std::vector const& v) -> YAML::Node; +template +auto toYaml(T const& t) -> YAML::Node; +template +auto toYaml(std::variant const& t) -> YAML::Node; + +template +class heap_object { + std::unique_ptr data = std::make_unique(); +public: + heap_object() = default; + heap_object(heap_object const& oth) { + *data = *oth; + } + heap_object(heap_object&& oth) { + *data = *oth; + } + + template + heap_object(T2 const& oth) { + *data = oth; + } + template + heap_object(T2&& oth) { + *data = oth; + } + + auto operator=(heap_object const& oth) -> heap_object& { + *data = *oth; + return *this; + } + auto operator=(heap_object&& oth) -> heap_object& { + *data = std::move(*oth); + return *this; + } + + template + auto operator=(T2 const& oth) -> heap_object& { + *data = oth; + return *this; + } + template + auto operator=(T2&& oth) -> heap_object& { + *data = std::move(oth); + return *this; + } + + auto operator->() -> T* { + return data.get(); + } + auto operator->() const -> T const* { + return data.get(); + } + auto operator*() -> T& { + return *data; + } + auto operator*() const -> T const& { + return *data; + } + +}; + +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_04_abstract_inheritance_yml { struct MyRecordOne; } +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_04_abstract_inheritance_yml { struct MyRecordTwo; } +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_04_abstract_inheritance_yml { +struct MyRecordOne { + heap_object name; + virtual ~MyRecordOne() = 0; + virtual auto toYaml() const -> YAML::Node; +}; +} + +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_04_abstract_inheritance_yml { +struct MyRecordTwo + : file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_04_abstract_inheritance_yml::MyRecordOne { + heap_object value; + auto toYaml() const -> YAML::Node override; +}; +} + +inline file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_04_abstract_inheritance_yml::MyRecordOne::~MyRecordOne() = default; +inline auto file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_04_abstract_inheritance_yml::MyRecordOne::toYaml() const -> YAML::Node { + using ::toYaml; + auto n = YAML::Node{}; + addYamlField(n, "name", toYaml(*name)); + return n; +} +inline auto file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_04_abstract_inheritance_yml::MyRecordTwo::toYaml() const -> YAML::Node { + using ::toYaml; + auto n = YAML::Node{}; + n = mergeYaml(n, file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_04_abstract_inheritance_yml::MyRecordOne::toYaml()); + addYamlField(n, "value", toYaml(*value)); + return n; +} + +template +auto toYaml(std::vector const& v) -> YAML::Node { + auto n = YAML::Node(YAML::NodeType::Sequence); + for (auto const& e : v) { + n.push_back(toYaml(e)); + } + return n; +} + +template +auto toYaml(T const& t) -> YAML::Node { + if constexpr (std::is_enum_v) { + return toYaml(t); + } else { + return t.toYaml(); + } +} + +template +auto toYaml(std::variant const& t) -> YAML::Node { + return std::visit([](auto const& e) { + return toYaml(e); + }, t); +} diff --git a/schema_salad/tests/cpp_tests/04_abstract_inheritance.yml b/schema_salad/tests/cpp_tests/04_abstract_inheritance.yml new file mode 100644 index 000000000..273b86210 --- /dev/null +++ b/schema_salad/tests/cpp_tests/04_abstract_inheritance.yml @@ -0,0 +1,12 @@ +- name: MyRecordOne + doc: Number One Record + abstract: True + type: record + fields: + name: string +- name: MyRecordTwo + extends: [MyRecordOne] + doc: Number Two Record + type: record + fields: + value: int diff --git a/schema_salad/tests/cpp_tests/05_specialization.h b/schema_salad/tests/cpp_tests/05_specialization.h new file mode 100644 index 000000000..93e04bf89 --- /dev/null +++ b/schema_salad/tests/cpp_tests/05_specialization.h @@ -0,0 +1,209 @@ +#pragma once + +// Generated by schema-salad code generator + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +inline auto mergeYaml(YAML::Node n1, YAML::Node n2) { + for (auto const& e : n1) { + n2[e.first.as()] = e.second; + } + return n2; +} + +// declaring toYaml +inline auto toYaml(bool v) { + return YAML::Node{v}; +} +inline auto toYaml(float v) { + return YAML::Node{v}; +} +inline auto toYaml(double v) { + return YAML::Node{v}; +} +inline auto toYaml(int32_t v) { + return YAML::Node{v}; +} +inline auto toYaml(int64_t v) { + return YAML::Node{v}; +} +inline auto toYaml(std::any const&) { + return YAML::Node{}; +} +inline auto toYaml(std::monostate const&) { + return YAML::Node(YAML::NodeType::Undefined); +} + +inline auto toYaml(std::string const& v) { + return YAML::Node{v}; +} + +inline void addYamlField(YAML::Node& node, std::string const& key, YAML::Node value) { + if (value.IsDefined()) { + node[key] = value; + } +} + +inline auto convertListToMap(YAML::Node list, std::string const& key_name) { + if (list.size() == 0) return list; + auto map = YAML::Node{}; + for (YAML::Node n : list) { + auto key = n[key_name].as(); + n.remove(key_name); + map[key] = n; + } + return map; +} + +// fwd declaring toYaml +template +auto toYaml(std::vector const& v) -> YAML::Node; +template +auto toYaml(T const& t) -> YAML::Node; +template +auto toYaml(std::variant const& t) -> YAML::Node; + +template +class heap_object { + std::unique_ptr data = std::make_unique(); +public: + heap_object() = default; + heap_object(heap_object const& oth) { + *data = *oth; + } + heap_object(heap_object&& oth) { + *data = *oth; + } + + template + heap_object(T2 const& oth) { + *data = oth; + } + template + heap_object(T2&& oth) { + *data = oth; + } + + auto operator=(heap_object const& oth) -> heap_object& { + *data = *oth; + return *this; + } + auto operator=(heap_object&& oth) -> heap_object& { + *data = std::move(*oth); + return *this; + } + + template + auto operator=(T2 const& oth) -> heap_object& { + *data = oth; + return *this; + } + template + auto operator=(T2&& oth) -> heap_object& { + *data = std::move(oth); + return *this; + } + + auto operator->() -> T* { + return data.get(); + } + auto operator->() const -> T const* { + return data.get(); + } + auto operator*() -> T& { + return *data; + } + auto operator*() const -> T const& { + return *data; + } + +}; + +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_05_specialization_yml { struct FieldRecordA; } +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_05_specialization_yml { struct FieldRecordB; } +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_05_specialization_yml { struct MyRecordOne; } +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_05_specialization_yml { struct MyRecordTwo; } +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_05_specialization_yml { +struct FieldRecordA { + virtual auto toYaml() const -> YAML::Node; +}; +} + +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_05_specialization_yml { +struct FieldRecordB { + virtual auto toYaml() const -> YAML::Node; +}; +} + +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_05_specialization_yml { +struct MyRecordOne { + heap_object name; + virtual auto toYaml() const -> YAML::Node; +}; +} + +namespace file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_05_specialization_yml { +struct MyRecordTwo { + heap_object name; + heap_object value; + virtual auto toYaml() const -> YAML::Node; +}; +} + +inline auto file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_05_specialization_yml::FieldRecordA::toYaml() const -> YAML::Node { + using ::toYaml; + auto n = YAML::Node{}; + return n; +} +inline auto file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_05_specialization_yml::FieldRecordB::toYaml() const -> YAML::Node { + using ::toYaml; + auto n = YAML::Node{}; + return n; +} +inline auto file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_05_specialization_yml::MyRecordOne::toYaml() const -> YAML::Node { + using ::toYaml; + auto n = YAML::Node{}; + addYamlField(n, "name", toYaml(*name)); + return n; +} +inline auto file____home_gene_Coding_schema_salad_schema_salad_tests_cpp_tests_05_specialization_yml::MyRecordTwo::toYaml() const -> YAML::Node { + using ::toYaml; + auto n = YAML::Node{}; + addYamlField(n, "name", toYaml(*name)); + addYamlField(n, "value", toYaml(*value)); + return n; +} + +template +auto toYaml(std::vector const& v) -> YAML::Node { + auto n = YAML::Node(YAML::NodeType::Sequence); + for (auto const& e : v) { + n.push_back(toYaml(e)); + } + return n; +} + +template +auto toYaml(T const& t) -> YAML::Node { + if constexpr (std::is_enum_v) { + return toYaml(t); + } else { + return t.toYaml(); + } +} + +template +auto toYaml(std::variant const& t) -> YAML::Node { + return std::visit([](auto const& e) { + return toYaml(e); + }, t); +} diff --git a/schema_salad/tests/cpp_tests/05_specialization.yml b/schema_salad/tests/cpp_tests/05_specialization.yml new file mode 100644 index 000000000..f1c5b99e3 --- /dev/null +++ b/schema_salad/tests/cpp_tests/05_specialization.yml @@ -0,0 +1,21 @@ +- name: FieldRecordA + doc: Field Record A + type: record +- name: FieldRecordB + doc: Field Record B + type: record + +- name: MyRecordOne + doc: Number One Record + type: record + fields: + name: FieldRecordA +- name: MyRecordTwo + extends: [MyRecordOne] + specialize: + - specializeFrom: FieldRecordA + specializeTo: FieldRecordB + doc: Number Two Record + type: record + fields: + value: int diff --git a/schema_salad/tests/test_cpp_codegen.py b/schema_salad/tests/test_cpp_codegen.py index 56b63c921..e7f20cf1e 100644 --- a/schema_salad/tests/test_cpp_codegen.py +++ b/schema_salad/tests/test_cpp_codegen.py @@ -1,5 +1,6 @@ """Test C++ code generation.""" +import filecmp import os from pathlib import Path from typing import Any, Dict, List, cast @@ -20,6 +21,26 @@ def test_cwl_cpp_gen(tmp_path: Path) -> None: assert os.path.exists(src_target) +def test_cwl_cpp_generations(tmp_path: Path) -> None: + """End to end test of C++ generator using the CWL v1.0 schema.""" + + test_dir = Path(cast(str, get_data("cpp_tests/01_single_record.yml"))).parents[0] + + # iterate through all cpp_tests YAML files + for file in test_dir.iterdir(): + if file.suffix != ".yaml": + continue + + # file with generated cpp output + src_target = tmp_path / "test.h" + # file with expected cpp output + expected = test_dir.with_suffix(".h") + + cpp_codegen(os.fspath(file), src_target) + + assert filecmp.cmp(expected, src_target, shallow=False) + + def cpp_codegen( file_uri: str, target: Path, diff --git a/schema_salad/tests/test_subtypes.py b/schema_salad/tests/test_subtypes.py index 17b3ca170..2a6b149a3 100644 --- a/schema_salad/tests/test_subtypes.py +++ b/schema_salad/tests/test_subtypes.py @@ -5,6 +5,7 @@ from schema_salad.avro import schema from schema_salad.avro.schema import Names, SchemaParseException from schema_salad.schema import load_schema + from .util import get_data types = [ diff --git a/setup.py b/setup.py index c1778f220..7a9759dc4 100644 --- a/setup.py +++ b/setup.py @@ -134,6 +134,7 @@ "schema_salad.tests": [ "*.json", "*.yml", + "cpp_tests/*", "docimp/*", "*.owl", "*.cwl",