aboutsummaryrefslogtreecommitdiffstats
path: root/engine/atf_list_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engine/atf_list_test.cpp')
-rw-r--r--engine/atf_list_test.cpp278
1 files changed, 278 insertions, 0 deletions
diff --git a/engine/atf_list_test.cpp b/engine/atf_list_test.cpp
new file mode 100644
index 000000000000..7f19ca8fbec5
--- /dev/null
+++ b/engine/atf_list_test.cpp
@@ -0,0 +1,278 @@
+// Copyright 2015 The Kyua Authors.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "engine/atf_list.hpp"
+
+#include <sstream>
+#include <string>
+
+#include <atf-c++.hpp>
+
+#include "engine/exceptions.hpp"
+#include "model/metadata.hpp"
+#include "model/test_case.hpp"
+#include "model/types.hpp"
+#include "utils/datetime.hpp"
+#include "utils/format/containers.ipp"
+#include "utils/fs/path.hpp"
+#include "utils/units.hpp"
+
+namespace datetime = utils::datetime;
+namespace fs = utils::fs;
+namespace units = utils::units;
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_metadata__defaults)
+ATF_TEST_CASE_BODY(parse_atf_metadata__defaults)
+{
+ const model::properties_map properties;
+ const model::metadata md = engine::parse_atf_metadata(properties);
+
+ const model::metadata exp_md = model::metadata_builder().build();
+ ATF_REQUIRE_EQ(exp_md, md);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_metadata__override_all)
+ATF_TEST_CASE_BODY(parse_atf_metadata__override_all)
+{
+ model::properties_map properties;
+ properties["descr"] = "Some text";
+ properties["has.cleanup"] = "true";
+ properties["require.arch"] = "i386 x86_64";
+ properties["require.config"] = "var1 var2 var3";
+ properties["require.files"] = "/file1 /dir/file2";
+ properties["require.machine"] = "amd64";
+ properties["require.memory"] = "1m";
+ properties["require.progs"] = "/bin/ls svn";
+ properties["require.user"] = "root";
+ properties["timeout"] = "123";
+ properties["X-foo"] = "value1";
+ properties["X-bar"] = "value2";
+ properties["X-baz-www"] = "value3";
+ const model::metadata md = engine::parse_atf_metadata(properties);
+
+ const model::metadata exp_md = model::metadata_builder()
+ .add_allowed_architecture("i386")
+ .add_allowed_architecture("x86_64")
+ .add_allowed_platform("amd64")
+ .add_custom("foo", "value1")
+ .add_custom("bar", "value2")
+ .add_custom("baz-www", "value3")
+ .add_required_config("var1")
+ .add_required_config("var2")
+ .add_required_config("var3")
+ .add_required_file(fs::path("/file1"))
+ .add_required_file(fs::path("/dir/file2"))
+ .add_required_program(fs::path("/bin/ls"))
+ .add_required_program(fs::path("svn"))
+ .set_description("Some text")
+ .set_has_cleanup(true)
+ .set_required_memory(units::bytes::parse("1m"))
+ .set_required_user("root")
+ .set_timeout(datetime::delta(123, 0))
+ .build();
+ ATF_REQUIRE_EQ(exp_md, md);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_metadata__unknown)
+ATF_TEST_CASE_BODY(parse_atf_metadata__unknown)
+{
+ model::properties_map properties;
+ properties["foobar"] = "Some text";
+
+ ATF_REQUIRE_THROW_RE(engine::format_error, "Unknown.*property.*'foobar'",
+ engine::parse_atf_metadata(properties));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__empty);
+ATF_TEST_CASE_BODY(parse_atf_list__empty)
+{
+ const std::string text = "";
+ std::istringstream input(text);
+ ATF_REQUIRE_THROW_RE(engine::format_error, "expecting Content-Type",
+ engine::parse_atf_list(input));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__invalid_header);
+ATF_TEST_CASE_BODY(parse_atf_list__invalid_header)
+{
+ {
+ const std::string text =
+ "Content-Type: application/X-atf-tp; version=\"1\"\n";
+ std::istringstream input(text);
+ ATF_REQUIRE_THROW_RE(engine::format_error, "expecting.*blank line",
+ engine::parse_atf_list(input));
+ }
+
+ {
+ const std::string text =
+ "Content-Type: application/X-atf-tp; version=\"1\"\nfoo\n";
+ std::istringstream input(text);
+ ATF_REQUIRE_THROW_RE(engine::format_error, "expecting.*blank line",
+ engine::parse_atf_list(input));
+ }
+
+ {
+ const std::string text =
+ "Content-Type: application/X-atf-tp; version=\"2\"\n\n";
+ std::istringstream input(text);
+ ATF_REQUIRE_THROW_RE(engine::format_error, "expecting Content-Type",
+ engine::parse_atf_list(input));
+ }
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__no_test_cases);
+ATF_TEST_CASE_BODY(parse_atf_list__no_test_cases)
+{
+ const std::string text =
+ "Content-Type: application/X-atf-tp; version=\"1\"\n\n";
+ std::istringstream input(text);
+ ATF_REQUIRE_THROW_RE(engine::format_error, "No test cases",
+ engine::parse_atf_list(input));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__one_test_case_simple);
+ATF_TEST_CASE_BODY(parse_atf_list__one_test_case_simple)
+{
+ const std::string text =
+ "Content-Type: application/X-atf-tp; version=\"1\"\n"
+ "\n"
+ "ident: test-case\n";
+ std::istringstream input(text);
+ const model::test_cases_map tests = engine::parse_atf_list(input);
+
+ const model::test_cases_map exp_tests = model::test_cases_map_builder()
+ .add("test-case").build();
+ ATF_REQUIRE_EQ(exp_tests, tests);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__one_test_case_complex);
+ATF_TEST_CASE_BODY(parse_atf_list__one_test_case_complex)
+{
+ const std::string text =
+ "Content-Type: application/X-atf-tp; version=\"1\"\n"
+ "\n"
+ "ident: first\n"
+ "descr: This is the description\n"
+ "timeout: 500\n";
+ std::istringstream input(text);
+ const model::test_cases_map tests = engine::parse_atf_list(input);
+
+ const model::test_cases_map exp_tests = model::test_cases_map_builder()
+ .add("first", model::metadata_builder()
+ .set_description("This is the description")
+ .set_timeout(datetime::delta(500, 0))
+ .build())
+ .build();
+ ATF_REQUIRE_EQ(exp_tests, tests);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__one_test_case_invalid_syntax);
+ATF_TEST_CASE_BODY(parse_atf_list__one_test_case_invalid_syntax)
+{
+ const std::string text =
+ "Content-Type: application/X-atf-tp; version=\"1\"\n\n"
+ "descr: This is the description\n"
+ "ident: first\n";
+ std::istringstream input(text);
+ ATF_REQUIRE_THROW_RE(engine::format_error, "preceeded.*identifier",
+ engine::parse_atf_list(input));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__one_test_case_invalid_properties);
+ATF_TEST_CASE_BODY(parse_atf_list__one_test_case_invalid_properties)
+{
+ // Inject a single invalid property that makes test_case::from_properties()
+ // raise a particular error message so that we can validate that such
+ // function was called. We do intensive testing separately, so it is not
+ // necessary to redo it here.
+ const std::string text =
+ "Content-Type: application/X-atf-tp; version=\"1\"\n\n"
+ "ident: first\n"
+ "require.progs: bin/ls\n";
+ std::istringstream input(text);
+ ATF_REQUIRE_THROW_RE(engine::format_error, "Relative path 'bin/ls'",
+ engine::parse_atf_list(input));
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__many_test_cases);
+ATF_TEST_CASE_BODY(parse_atf_list__many_test_cases)
+{
+ const std::string text =
+ "Content-Type: application/X-atf-tp; version=\"1\"\n"
+ "\n"
+ "ident: first\n"
+ "descr: This is the description\n"
+ "\n"
+ "ident: second\n"
+ "timeout: 500\n"
+ "descr: Some text\n"
+ "\n"
+ "ident: third\n";
+ std::istringstream input(text);
+ const model::test_cases_map tests = engine::parse_atf_list(input);
+
+ const model::test_cases_map exp_tests = model::test_cases_map_builder()
+ .add("first", model::metadata_builder()
+ .set_description("This is the description")
+ .build())
+ .add("second", model::metadata_builder()
+ .set_description("Some text")
+ .set_timeout(datetime::delta(500, 0))
+ .build())
+ .add("third")
+ .build();
+ ATF_REQUIRE_EQ(exp_tests, tests);
+}
+
+
+ATF_INIT_TEST_CASES(tcs)
+{
+ ATF_ADD_TEST_CASE(tcs, parse_atf_metadata__defaults);
+ ATF_ADD_TEST_CASE(tcs, parse_atf_metadata__override_all);
+ ATF_ADD_TEST_CASE(tcs, parse_atf_metadata__unknown);
+
+ ATF_ADD_TEST_CASE(tcs, parse_atf_list__empty);
+ ATF_ADD_TEST_CASE(tcs, parse_atf_list__invalid_header);
+ ATF_ADD_TEST_CASE(tcs, parse_atf_list__no_test_cases);
+ ATF_ADD_TEST_CASE(tcs, parse_atf_list__one_test_case_simple);
+ ATF_ADD_TEST_CASE(tcs, parse_atf_list__one_test_case_complex);
+ ATF_ADD_TEST_CASE(tcs, parse_atf_list__one_test_case_invalid_syntax);
+ ATF_ADD_TEST_CASE(tcs, parse_atf_list__one_test_case_invalid_properties);
+ ATF_ADD_TEST_CASE(tcs, parse_atf_list__many_test_cases);
+}