diff options
author | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
---|---|---|
committer | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
commit | 72231250ed81e10d66bfe70701e64fa5fe50f712 (patch) | |
tree | 2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /searchcore/src/tests/proton/verify_ranksetup |
Publish
Diffstat (limited to 'searchcore/src/tests/proton/verify_ranksetup')
11 files changed, 271 insertions, 0 deletions
diff --git a/searchcore/src/tests/proton/verify_ranksetup/.cvsignore b/searchcore/src/tests/proton/verify_ranksetup/.cvsignore new file mode 100644 index 00000000000..a4848db32f8 --- /dev/null +++ b/searchcore/src/tests/proton/verify_ranksetup/.cvsignore @@ -0,0 +1,3 @@ +.depend +Makefile +verify_ranksetup_test diff --git a/searchcore/src/tests/proton/verify_ranksetup/.gitignore b/searchcore/src/tests/proton/verify_ranksetup/.gitignore new file mode 100644 index 00000000000..1142087d03d --- /dev/null +++ b/searchcore/src/tests/proton/verify_ranksetup/.gitignore @@ -0,0 +1,5 @@ +*_test +.depend +Makefile +generated +searchcore_verify_ranksetup_test_app diff --git a/searchcore/src/tests/proton/verify_ranksetup/CMakeLists.txt b/searchcore/src/tests/proton/verify_ranksetup/CMakeLists.txt new file mode 100644 index 00000000000..2d74c323c1a --- /dev/null +++ b/searchcore/src/tests/proton/verify_ranksetup/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +vespa_add_executable(searchcore_verify_ranksetup_test_app + SOURCES + verify_ranksetup_test.cpp + DEPENDS +) +vespa_add_test(NAME searchcore_verify_ranksetup_test_app COMMAND sh verify_ranksetup_test.sh) diff --git a/searchcore/src/tests/proton/verify_ranksetup/DESC b/searchcore/src/tests/proton/verify_ranksetup/DESC new file mode 100644 index 00000000000..700e2b1c2f9 --- /dev/null +++ b/searchcore/src/tests/proton/verify_ranksetup/DESC @@ -0,0 +1 @@ +verify_ranksetup test. Take a look at verify_ranksetup.cpp for details. diff --git a/searchcore/src/tests/proton/verify_ranksetup/FILES b/searchcore/src/tests/proton/verify_ranksetup/FILES new file mode 100644 index 00000000000..9c4a2ef3776 --- /dev/null +++ b/searchcore/src/tests/proton/verify_ranksetup/FILES @@ -0,0 +1 @@ +verify_ranksetup.cpp diff --git a/searchcore/src/tests/proton/verify_ranksetup/invalid_attr_name/.gitignore b/searchcore/src/tests/proton/verify_ranksetup/invalid_attr_name/.gitignore new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/searchcore/src/tests/proton/verify_ranksetup/invalid_attr_name/.gitignore diff --git a/searchcore/src/tests/proton/verify_ranksetup/invalid_feature_name/.gitignore b/searchcore/src/tests/proton/verify_ranksetup/invalid_feature_name/.gitignore new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/searchcore/src/tests/proton/verify_ranksetup/invalid_feature_name/.gitignore diff --git a/searchcore/src/tests/proton/verify_ranksetup/unsupported_collection_type/.gitignore b/searchcore/src/tests/proton/verify_ranksetup/unsupported_collection_type/.gitignore new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/searchcore/src/tests/proton/verify_ranksetup/unsupported_collection_type/.gitignore diff --git a/searchcore/src/tests/proton/verify_ranksetup/valid/.gitignore b/searchcore/src/tests/proton/verify_ranksetup/valid/.gitignore new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/searchcore/src/tests/proton/verify_ranksetup/valid/.gitignore diff --git a/searchcore/src/tests/proton/verify_ranksetup/verify_ranksetup_test.cpp b/searchcore/src/tests/proton/verify_ranksetup/verify_ranksetup_test.cpp new file mode 100644 index 00000000000..3db23380675 --- /dev/null +++ b/searchcore/src/tests/proton/verify_ranksetup/verify_ranksetup_test.cpp @@ -0,0 +1,250 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#include <vespa/vespalib/testkit/test_kit.h> +#include <vespa/vespalib/util/slaveproc.h> +#include <vespa/vespalib/util/stringfmt.h> +#include <vespa/searchcommon/common/schema.h> +#include <vespa/searchlib/fef/indexproperties.h> +#include <string> +#include <vector> +#include <map> +#include <initializer_list> + +const char *prog = "../../../apps/verify_ranksetup/verify_ranksetup-bin"; +const std::string gen_dir("generated"); + +const char *valid_feature = "value(0)"; +const char *invalid_feature = "invalid_feature_name and format"; + +using search::index::Schema; +using namespace search::fef::indexproperties; + +struct Writer { + FILE *file; + Writer(const std::string &file_name) { + file = fopen(file_name.c_str(), "w"); + ASSERT_TRUE(file != 0); + } + void fmt(const char *format, ...) const +#ifdef __GNUC__ + __attribute__ ((format (printf,2,3))) +#endif + { + va_list ap; + va_start(ap, format); + vfprintf(file, format, ap); + va_end(ap); + } + ~Writer() { fclose(file); } +}; + +void verify_dir() { + std::string pwd(getenv("PWD")); + ASSERT_NOT_EQUAL(pwd.find("searchcore/src/tests/proton/verify_ranksetup"), pwd.npos); +} + +//----------------------------------------------------------------------------- + +struct Model { + std::map<std::string,std::pair<std::string,std::string> > indexes; + std::map<std::string,std::pair<std::string,std::string> > attributes; + std::map<std::string,std::string> properties; + std::vector<bool> extra_profiles; + Model() : indexes(), attributes(), properties(), extra_profiles() { + verify_dir(); + } + void index(const std::string &name, Schema::DataType data_type, + Schema::CollectionType collection_type) + { + indexes[name].first = Schema::getTypeName(data_type); + indexes[name].second = Schema::getTypeName(collection_type); + } + void attribute(const std::string &name, Schema::DataType data_type, + Schema::CollectionType collection_type) + { + attributes[name].first = Schema::getTypeName(data_type); + attributes[name].second = Schema::getTypeName(collection_type); + } + void property(const std::string &name, const std::string &val) { + properties[name] = val; + } + void first_phase(const std::string &feature) { + property(rank::FirstPhase::NAME, feature); + } + void second_phase(const std::string &feature) { + property(rank::SecondPhase::NAME, feature); + } + void summary_feature(const std::string &feature) { + property(summary::Feature::NAME, feature); + } + void dump_feature(const std::string &feature) { + property(dump::Feature::NAME, feature); + } + void good_profile() { + extra_profiles.push_back(true); + } + void bad_profile() { + extra_profiles.push_back(false); + } + void write_attributes(const Writer &out) { + out.fmt("attribute[%zu]\n", attributes.size()); + std::map<std::string,std::pair<std::string,std::string> >::const_iterator pos = attributes.begin(); + for (size_t i = 0; pos != attributes.end(); ++pos, ++i) { + out.fmt("attribute[%zu].name \"%s\"\n", i, pos->first.c_str()); + out.fmt("attribute[%zu].datatype %s\n", i, pos->second.first.c_str()); + out.fmt("attribute[%zu].collectiontype %s\n", i, pos->second.second.c_str()); + } + } + void write_indexschema(const Writer &out) { + out.fmt("indexfield[%zu]\n", indexes.size()); + std::map<std::string,std::pair<std::string,std::string> >::const_iterator pos = indexes.begin(); + for (size_t i = 0; pos != indexes.end(); ++pos, ++i) { + out.fmt("indexfield[%zu].name \"%s\"\n", i, pos->first.c_str()); + out.fmt("indexfield[%zu].datatype %s\n", i, pos->second.first.c_str()); + out.fmt("indexfield[%zu].collectiontype %s\n", i, pos->second.second.c_str()); + } + } + void write_rank_profiles(const Writer &out) { + out.fmt("rankprofile[%zu]\n", extra_profiles.size() + 1); + out.fmt("rankprofile[0].name \"default\"\n"); + std::map<std::string,std::string>::const_iterator pos = properties.begin(); + for (size_t i = 0; pos != properties.end(); ++pos, ++i) { + out.fmt("rankprofile[0].fef.property[%zu]\n", properties.size()); + out.fmt("rankprofile[0].fef.property[%zu].name \"%s\"\n", i, pos->first.c_str()); + out.fmt("rankprofile[0].fef.property[%zu].value \"%s\"\n", i, pos->second.c_str()); + } + for (size_t i = 1; i < (extra_profiles.size() + 1); ++i) { + out.fmt("rankprofile[%zu].name \"extra_%zu\"\n", i, i); + out.fmt("rankprofile[%zu].fef.property[%zu].name \"%s\"\n", i, i, rank::FirstPhase::NAME.c_str()); + out.fmt("rankprofile[%zu].fef.property[%zu].value \"%s\"\n", i, i, extra_profiles[i-1]?valid_feature:invalid_feature); + } + } + void generate() { + write_attributes(Writer(gen_dir + "/attributes.cfg")); + write_indexschema(Writer(gen_dir + "/indexschema.cfg")); + write_rank_profiles(Writer(gen_dir + "/rank-profiles.cfg")); + } + bool verify() { + generate(); + return vespalib::SlaveProc::run(vespalib::make_string("%s dir:%s", prog, gen_dir.c_str()).c_str()); + } + void verify_valid(std::initializer_list<std::string> features) { + for (const std::string &f: features) { + first_phase(f); + if (!EXPECT_TRUE(verify())) { + fprintf(stderr, "--> feature '%s' was invalid (should be valid)\n", f.c_str()); + } + } + } + void verify_invalid(std::initializer_list<std::string> features) { + for (const std::string &f: features) { + first_phase(f); + if (!EXPECT_FALSE(verify())) { + fprintf(stderr, "--> feature '%s' was valid (should be invalid)\n", f.c_str()); + } + } + } +}; + +//----------------------------------------------------------------------------- + +struct EmptyModel : Model {}; + +struct SimpleModel : Model { + SimpleModel() : Model() { + index("title", Schema::STRING, Schema::SINGLE); + index("list", Schema::STRING, Schema::ARRAY); + index("keywords", Schema::STRING, Schema::WEIGHTEDSET); + attribute("date", Schema::INT32, Schema::SINGLE); + } +}; + +struct ShadowModel : Model { + ShadowModel() : Model() { + index("both", Schema::STRING, Schema::SINGLE); + attribute("both", Schema::STRING, Schema::SINGLE); + } +}; + +TEST_F("print usage", Model()) { + EXPECT_FALSE(vespalib::SlaveProc::run(vespalib::make_string("%s", prog).c_str())); +} + +TEST_F("setup output directory", Model()) { + ASSERT_TRUE(vespalib::SlaveProc::run(vespalib::make_string("rm -rf %s", gen_dir.c_str()).c_str())); + ASSERT_TRUE(vespalib::SlaveProc::run(vespalib::make_string("mkdir %s", gen_dir.c_str()).c_str())); +} + +//----------------------------------------------------------------------------- + +TEST_F("require that empty setup passes validation", EmptyModel()) { + EXPECT_TRUE(f.verify()); +} + +TEST_F("require that we can verify multiple rank profiles", SimpleModel()) { + f.first_phase(valid_feature); + f.good_profile(); + EXPECT_TRUE(f.verify()); + f.bad_profile(); + EXPECT_FALSE(f.verify()); +} + +TEST_F("require that first phase can break validation", SimpleModel()) { + f.first_phase(invalid_feature); + EXPECT_FALSE(f.verify()); +} + +TEST_F("require that second phase can break validation", SimpleModel()) { + f.second_phase(invalid_feature); + EXPECT_FALSE(f.verify()); +} + +TEST_F("require that summary features can break validation", SimpleModel()) { + f.summary_feature(invalid_feature); + EXPECT_FALSE(f.verify()); +} + +TEST_F("require that dump features can break validation", SimpleModel()) { + f.dump_feature(invalid_feature); + EXPECT_FALSE(f.verify()); +} + +TEST_F("require that fieldMatch feature requires single value field", SimpleModel()) { + f.first_phase("fieldMatch(keywords)"); + EXPECT_FALSE(f.verify()); + f.first_phase("fieldMatch(list)"); + EXPECT_FALSE(f.verify()); + f.first_phase("fieldMatch(title)"); + EXPECT_TRUE(f.verify()); +} + +TEST_F("require that age feature requires attribute parameter", SimpleModel()) { + f.first_phase("age(unknown)"); + EXPECT_FALSE(f.verify()); + f.first_phase("age(title)"); + EXPECT_FALSE(f.verify()); + f.first_phase("age(date)"); + EXPECT_TRUE(f.verify()); +} + +TEST_F("require that nativeRank can be used on any valid field", SimpleModel()) { + f.verify_invalid({"nativeRank(unknown)"}); + f.verify_valid({"nativeRank", "nativeRank(title)", "nativeRank(date)", "nativeRank(title,date)"}); +} + +TEST_F("require that nativeAttributeMatch requires attribute parameter", SimpleModel()) { + f.verify_invalid({"nativeAttributeMatch(unknown)", "nativeAttributeMatch(title)", "nativeAttributeMatch(title,date)"}); + f.verify_valid({"nativeAttributeMatch", "nativeAttributeMatch(date)"}); +} + +TEST_F("require that shadowed attributes can be used", ShadowModel()) { + f.first_phase("attribute(both)"); + EXPECT_TRUE(f.verify()); +} + +//----------------------------------------------------------------------------- + +TEST_F("cleanup files", Model()) { + ASSERT_TRUE(vespalib::SlaveProc::run(vespalib::make_string("rm -rf %s", gen_dir.c_str()).c_str())); +} + +TEST_MAIN_WITH_PROCESS_PROXY() { TEST_RUN_ALL(); } diff --git a/searchcore/src/tests/proton/verify_ranksetup/verify_ranksetup_test.sh b/searchcore/src/tests/proton/verify_ranksetup/verify_ranksetup_test.sh new file mode 100755 index 00000000000..d03b6309ec9 --- /dev/null +++ b/searchcore/src/tests/proton/verify_ranksetup/verify_ranksetup_test.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +export PWD=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd) +$VALGRIND ./searchcore_verify_ranksetup_test_app |