aboutsummaryrefslogtreecommitdiffstats
path: root/searchcore/src/tests/proton/config/config.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'searchcore/src/tests/proton/config/config.cpp')
-rw-r--r--searchcore/src/tests/proton/config/config.cpp268
1 files changed, 268 insertions, 0 deletions
diff --git a/searchcore/src/tests/proton/config/config.cpp b/searchcore/src/tests/proton/config/config.cpp
new file mode 100644
index 00000000000..24cf4cec4cc
--- /dev/null
+++ b/searchcore/src/tests/proton/config/config.cpp
@@ -0,0 +1,268 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("config_test");
+#include <vespa/vespalib/testkit/testapp.h>
+#include <vespa/vespalib/util/linkedptr.h>
+#include <map>
+#include <vespa/searchcore/proton/server/bootstrapconfigmanager.h>
+#include <vespa/searchcore/proton/server/bootstrapconfig.h>
+#include <vespa/searchcore/proton/server/documentdbconfigmanager.h>
+#include <vespa/searchcore/proton/server/protonconfigurer.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 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 {
+ typedef vespalib::LinkedPtr<DoctypeFixture> LP;
+ AttributesConfigBuilder attributesBuilder;
+ RankProfilesConfigBuilder rankProfilesBuilder;
+ IndexschemaConfigBuilder indexschemaBuilder;
+ SummaryConfigBuilder summaryBuilder;
+ SummarymapConfigBuilder summarymapBuilder;
+ JuniperrcConfigBuilder juniperrcBuilder;
+};
+
+struct ConfigTestFixture {
+ const std::string configId;
+ ProtonConfigBuilder protonBuilder;
+ DocumenttypesConfigBuilder documenttypesBuilder;
+ map<std::string, DoctypeFixture::LP> dbConfig;
+ ConfigSet set;
+ IConfigContext::SP context;
+ int idcounter;
+
+ ConfigTestFixture(const std::string & id)
+ : configId(id),
+ protonBuilder(),
+ documenttypesBuilder(),
+ dbConfig(),
+ set(),
+ context(new ConfigContext(set)),
+ idcounter(-1)
+ {
+ set.addBuilder(configId, &protonBuilder);
+ set.addBuilder(configId, &documenttypesBuilder);
+ addDocType("_alwaysthere_");
+ }
+
+ void 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::LP fixture(new DoctypeFixture());
+ set.addBuilder(db.configid, &fixture->attributesBuilder);
+ set.addBuilder(db.configid, &fixture->rankProfilesBuilder);
+ set.addBuilder(db.configid, &fixture->indexschemaBuilder);
+ set.addBuilder(db.configid, &fixture->summaryBuilder);
+ set.addBuilder(db.configid, &fixture->summarymapBuilder);
+ set.addBuilder(db.configid, &fixture->juniperrcBuilder);
+ dbConfig[name] = fixture;
+ }
+
+ 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) {
+ DoctypeFixture::LP fixture(dbConfig[name]);
+ 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)),
+ TuneFileDocumentDB::SP(new 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;
+ }
+ bool addExtraConfigs(DocumentDBConfigManager & dbCfgMan) {
+ (void) dbCfgMan;
+ return false;
+ }
+};
+
+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(2u, 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(6u, 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_FFF("require_that_protonconfigurer_follows_changes_to_bootstrap",
+ ConfigTestFixture("search"),
+ BootstrapOwner(),
+ ProtonConfigurer(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_protonconfigurer_follows_changes_to_doctypes",
+ ConfigTestFixture("search"),
+ BootstrapOwner(),
+ ProtonConfigurer(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_protonconfigurer_reconfigures_dbowners",
+ ConfigTestFixture("search"),
+ BootstrapOwner(),
+ ProtonConfigurer(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(60000));
+ f3.close();
+}
+
+TEST_MAIN() { TEST_RUN_ALL(); }