diff options
author | Tor Egge <Tor.Egge@yahoo-inc.com> | 2017-03-14 10:15:53 +0000 |
---|---|---|
committer | Tor Egge <Tor.Egge@yahoo-inc.com> | 2017-03-14 10:15:53 +0000 |
commit | a21c368e75bcf996d8a785ad00fdd41d842ac2d2 (patch) | |
tree | 4f36a0b67c5c47b300385924804c53e8cb6054f8 /searchcore/src/tests/proton/proton_config_fetcher | |
parent | 0241dc1d9ca8bb3dd0d6edcb83f3f88131767013 (diff) |
Rename unit test to track rename of tested class.
Diffstat (limited to 'searchcore/src/tests/proton/proton_config_fetcher')
4 files changed, 309 insertions, 0 deletions
diff --git a/searchcore/src/tests/proton/proton_config_fetcher/.cvsignore b/searchcore/src/tests/proton/proton_config_fetcher/.cvsignore new file mode 100644 index 00000000000..13fb04d2a35 --- /dev/null +++ b/searchcore/src/tests/proton/proton_config_fetcher/.cvsignore @@ -0,0 +1,3 @@ +.depend +Makefile +config_test diff --git a/searchcore/src/tests/proton/proton_config_fetcher/.gitignore b/searchcore/src/tests/proton/proton_config_fetcher/.gitignore new file mode 100644 index 00000000000..72c49479fc1 --- /dev/null +++ b/searchcore/src/tests/proton/proton_config_fetcher/.gitignore @@ -0,0 +1 @@ +searchcore_config_test_app diff --git a/searchcore/src/tests/proton/proton_config_fetcher/CMakeLists.txt b/searchcore/src/tests/proton/proton_config_fetcher/CMakeLists.txt new file mode 100644 index 00000000000..bdec36ea2ca --- /dev/null +++ b/searchcore/src/tests/proton/proton_config_fetcher/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +vespa_add_executable(searchcore_proton_config_fetcher_test_app TEST + SOURCES + proton_config_fetcher_test.cpp + DEPENDS + searchcore_server + searchcore_fconfig +) +vespa_add_test(NAME searchcore_proton_config_fetcher_test_app COMMAND searchcore_proton_config_fetcher_test_app) diff --git a/searchcore/src/tests/proton/proton_config_fetcher/proton_config_fetcher_test.cpp b/searchcore/src/tests/proton/proton_config_fetcher/proton_config_fetcher_test.cpp new file mode 100644 index 00000000000..01569cd7ba0 --- /dev/null +++ b/searchcore/src/tests/proton/proton_config_fetcher/proton_config_fetcher_test.cpp @@ -0,0 +1,296 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include <map> +#include <vespa/config-attributes.h> +#include <vespa/config-imported-fields.h> +#include <vespa/config-indexschema.h> +#include <vespa/config-rank-profiles.h> +#include <vespa/config-summary.h> +#include <vespa/config-summarymap.h> +#include <vespa/fileacquirer/config-filedistributorrpc.h> +#include <vespa/searchcore/proton/server/bootstrapconfig.h> +#include <vespa/searchcore/proton/server/bootstrapconfigmanager.h> +#include <vespa/searchcore/proton/server/documentdbconfigmanager.h> +#include <vespa/searchcore/proton/server/proton_config_fetcher.h> +#include <vespa/searchsummary/config/config-juniperrc.h> +#include <vespa/vespalib/testkit/testapp.h> +#include <vespa/vespalib/util/linkedptr.h> +#include <vespa/vespalib/util/varholder.h> + +using namespace config; +using namespace proton; +using namespace vespa::config::search::core; +using namespace vespa::config::search::summary; +using namespace vespa::config::search; +using namespace cloud::config::filedistribution; + +using config::ConfigUri; +using document::DocumentTypeRepo; +using document::DocumenttypesConfig; +using document::DocumenttypesConfigBuilder; +using search::TuneFileDocumentDB; +using std::map; +using vespalib::LinkedPtr; +using vespalib::VarHolder; + +struct DoctypeFixture { + using UP = std::unique_ptr<DoctypeFixture>; + AttributesConfigBuilder attributesBuilder; + RankProfilesConfigBuilder rankProfilesBuilder; + RankingConstantsConfigBuilder rankingConstantsBuilder; + IndexschemaConfigBuilder indexschemaBuilder; + SummaryConfigBuilder summaryBuilder; + SummarymapConfigBuilder summarymapBuilder; + JuniperrcConfigBuilder juniperrcBuilder; + ImportedFieldsConfigBuilder importedFieldsBuilder; +}; + +struct ConfigTestFixture { + const std::string configId; + ProtonConfigBuilder protonBuilder; + DocumenttypesConfigBuilder documenttypesBuilder; + FiledistributorrpcConfigBuilder filedistBuilder; + map<std::string, DoctypeFixture::UP> dbConfig; + ConfigSet set; + IConfigContext::SP context; + int idcounter; + + ConfigTestFixture(const std::string & id) + : configId(id), + protonBuilder(), + documenttypesBuilder(), + filedistBuilder(), + dbConfig(), + set(), + context(new ConfigContext(set)), + idcounter(-1) + { + set.addBuilder(configId, &protonBuilder); + set.addBuilder(configId, &documenttypesBuilder); + set.addBuilder(configId, &filedistBuilder); + addDocType("_alwaysthere_"); + } + + DoctypeFixture *addDocType(const std::string & name) { + DocumenttypesConfigBuilder::Documenttype dt; + dt.bodystruct = -1270491200; + dt.headerstruct = 306916075; + dt.id = idcounter--; + dt.name = name; + dt.version = 0; + documenttypesBuilder.documenttype.push_back(dt); + + ProtonConfigBuilder::Documentdb db; + db.inputdoctypename = name; + db.configid = configId + "/" + name; + protonBuilder.documentdb.push_back(db); + + DoctypeFixture::UP fixture = std::make_unique<DoctypeFixture>(); + set.addBuilder(db.configid, &fixture->attributesBuilder); + set.addBuilder(db.configid, &fixture->rankProfilesBuilder); + set.addBuilder(db.configid, &fixture->rankingConstantsBuilder); + set.addBuilder(db.configid, &fixture->indexschemaBuilder); + set.addBuilder(db.configid, &fixture->summaryBuilder); + set.addBuilder(db.configid, &fixture->summarymapBuilder); + set.addBuilder(db.configid, &fixture->juniperrcBuilder); + set.addBuilder(db.configid, &fixture->importedFieldsBuilder); + return dbConfig.emplace(std::make_pair(name, std::move(fixture))).first->second.get(); + } + + void removeDocType(const std::string & name) + { + for (DocumenttypesConfigBuilder::DocumenttypeVector::iterator it(documenttypesBuilder.documenttype.begin()), + mt(documenttypesBuilder.documenttype.end()); + it != mt; + it++) { + if ((*it).name.compare(name) == 0) { + documenttypesBuilder.documenttype.erase(it); + break; + } + } + + for (ProtonConfigBuilder::DocumentdbVector::iterator it(protonBuilder.documentdb.begin()), + mt(protonBuilder.documentdb.end()); + it != mt; + it++) { + if ((*it).inputdoctypename.compare(name) == 0) { + protonBuilder.documentdb.erase(it); + break; + } + } + } + + bool configEqual(const std::string & name, DocumentDBConfig::SP dbc) { + auto itr = dbConfig.find(name); + ASSERT_TRUE(itr != dbConfig.end()); + const auto *fixture = itr->second.get(); + return (fixture->attributesBuilder == dbc->getAttributesConfig() && + fixture->rankProfilesBuilder == dbc->getRankProfilesConfig() && + fixture->indexschemaBuilder == dbc->getIndexschemaConfig() && + fixture->summaryBuilder == dbc->getSummaryConfig() && + fixture->summarymapBuilder == dbc->getSummarymapConfig() && + fixture->juniperrcBuilder == dbc->getJuniperrcConfig()); + } + + bool configEqual(BootstrapConfig::SP bootstrapConfig) { + return (protonBuilder == bootstrapConfig->getProtonConfig() && + documenttypesBuilder == bootstrapConfig->getDocumenttypesConfig()); + } + + BootstrapConfig::SP getBootstrapConfig(int64_t generation) const { + return BootstrapConfig::SP(new BootstrapConfig(generation, + BootstrapConfig::DocumenttypesConfigSP(new DocumenttypesConfig(documenttypesBuilder)), + DocumentTypeRepo::SP(new DocumentTypeRepo(documenttypesBuilder)), + BootstrapConfig::ProtonConfigSP(new ProtonConfig(protonBuilder)), + std::make_shared<FiledistributorrpcConfig>(), + std::make_shared<TuneFileDocumentDB>())); + } + + void reload() { context->reload(); } +}; + +template <typename ConfigType, typename ConfigOwner> +struct OwnerFixture : public ConfigOwner +{ + volatile bool configured; + VarHolder<ConfigType> config; + + OwnerFixture() : configured(false), config() { } + bool waitUntilConfigured(int timeout) { + FastOS_Time timer; + timer.SetNow(); + while (timer.MilliSecsToNow() < timeout) { + if (configured) + break; + FastOS_Thread::Sleep(100); + } + return configured; + } + void reconfigure(const ConfigType & cfg) { + assert(cfg->valid()); + config.set(cfg); + configured = true; + } +}; + +typedef OwnerFixture<BootstrapConfig::SP, IBootstrapOwner> BootstrapOwner; +typedef OwnerFixture<DocumentDBConfig::SP, IDocumentDBConfigOwner> DBOwner; + +TEST_F("require that bootstrap config manager creats correct key set", BootstrapConfigManager("foo")) { + const ConfigKeySet set(f1.createConfigKeySet()); + ASSERT_EQUAL(3u, set.size()); + ConfigKey protonKey(ConfigKey::create<ProtonConfig>("foo")); + ConfigKey dtKey(ConfigKey::create<DocumenttypesConfig>("foo")); + ASSERT_TRUE(set.find(protonKey) != set.end()); + ASSERT_TRUE(set.find(dtKey) != set.end()); +} + +TEST_FFF("require that bootstrap config manager updates config", ConfigTestFixture("search"), + BootstrapConfigManager(f1.configId), + ConfigRetriever(f2.createConfigKeySet(), f1.context)) { + f2.update(f3.getBootstrapConfigs()); + ASSERT_TRUE(f1.configEqual(f2.getConfig())); + f1.protonBuilder.rpcport = 9010; + ASSERT_FALSE(f1.configEqual(f2.getConfig())); + f1.reload(); + f2.update(f3.getBootstrapConfigs()); + ASSERT_TRUE(f1.configEqual(f2.getConfig())); + + f1.addDocType("foobar"); + ASSERT_FALSE(f1.configEqual(f2.getConfig())); + f1.reload(); + f2.update(f3.getBootstrapConfigs()); + ASSERT_TRUE(f1.configEqual(f2.getConfig())); +} + +TEST_FF("require that documentdb config manager subscribes for config", + ConfigTestFixture("search"), + DocumentDBConfigManager(f1.configId + "/typea", "typea")) { + f1.addDocType("typea"); + const ConfigKeySet keySet(f2.createConfigKeySet()); + ASSERT_EQUAL(8u, keySet.size()); + ConfigRetriever retriever(keySet, f1.context); + f2.forwardConfig(f1.getBootstrapConfig(1)); + f2.update(retriever.getBootstrapConfigs()); // Cheating, but we only need the configs + ASSERT_TRUE(f1.configEqual("typea", f2.getConfig())); +} + +TEST_FF("require that documentdb config manager builds schema with imported attribute fields", + ConfigTestFixture("search"), + DocumentDBConfigManager(f1.configId + "/typea", "typea")) +{ + auto *docType = f1.addDocType("typea"); + docType->importedFieldsBuilder.attribute.resize(1); + docType->importedFieldsBuilder.attribute[0].name = "imported"; + + ConfigRetriever retriever(f2.createConfigKeySet(), f1.context); + f2.forwardConfig(f1.getBootstrapConfig(1)); + f2.update(retriever.getBootstrapConfigs()); // Cheating, but we only need the configs + const auto &schema = f2.getConfig()->getSchemaSP(); + EXPECT_EQUAL(1u, schema->getNumImportedAttributeFields()); + EXPECT_EQUAL("imported", schema->getImportedAttributeFields()[0].getName()); +} + +TEST_FFF("require that proton config fetcher follows changes to bootstrap", + ConfigTestFixture("search"), + BootstrapOwner(), + ProtonConfigFetcher(ConfigUri(f1.configId, f1.context), &f2, 60000)) { + f3.start(); + ASSERT_TRUE(f2.configured); + ASSERT_TRUE(f1.configEqual(f2.config.get())); + f2.configured = false; + f1.protonBuilder.rpcport = 9010; + f1.reload(); + ASSERT_TRUE(f2.waitUntilConfigured(120000)); + ASSERT_TRUE(f1.configEqual(f2.config.get())); + f3.close(); +} + +TEST_FFF("require that proton config fetcher follows changes to doctypes", + ConfigTestFixture("search"), + BootstrapOwner(), + ProtonConfigFetcher(ConfigUri(f1.configId, f1.context), &f2, 60000)) { + f3.start(); + + f2.configured = false; + f1.addDocType("typea"); + f1.reload(); + ASSERT_TRUE(f2.waitUntilConfigured(60000)); + ASSERT_TRUE(f1.configEqual(f2.config.get())); + + f2.configured = false; + f1.removeDocType("typea"); + f1.reload(); + ASSERT_TRUE(f2.waitUntilConfigured(60000)); + ASSERT_TRUE(f1.configEqual(f2.config.get())); + f3.close(); +} + +TEST_FFF("require that proton config fetcher reconfigures dbowners", + ConfigTestFixture("search"), + BootstrapOwner(), + ProtonConfigFetcher(ConfigUri(f1.configId, f1.context), &f2, 60000)) { + f3.start(); + + DBOwner dbA; + f3.registerDocumentDB(DocTypeName("typea"), &dbA); + + // Add db and verify that we get an initial callback + f2.configured = false; + f1.addDocType("typea"); + f1.reload(); + ASSERT_TRUE(f2.waitUntilConfigured(60000)); + ASSERT_TRUE(f1.configEqual(f2.config.get())); + ASSERT_TRUE(dbA.waitUntilConfigured(60000)); + ASSERT_TRUE(f1.configEqual("typea", dbA.config.get())); + + // Remove and verify that we don't get any callback + dbA.configured = false; + f1.removeDocType("typea"); + f1.reload(); + ASSERT_TRUE(f2.waitUntilConfigured(60000)); + ASSERT_FALSE(dbA.waitUntilConfigured(1000)); + f3.close(); +} + +TEST_MAIN() { TEST_RUN_ALL(); } |