summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArne Juul <arnej@verizonmedia.com>2021-08-05 09:29:42 +0000
committerArne Juul <arnej@verizonmedia.com>2021-08-05 09:31:25 +0000
commit82f5ee6ef74f0d6a2b97ae72cc40a55fab80d737 (patch)
tree083dc53089f403795f40f0ac9de12e089a97d59b
parent138c0bf924b4d4def788d65d418837e0dbd9fbe8 (diff)
add unit test for UnionServiceMap
-rw-r--r--slobrok/CMakeLists.txt1
-rw-r--r--slobrok/src/tests/union_service_map/CMakeLists.txt9
-rw-r--r--slobrok/src/tests/union_service_map/union_service_map_test.cpp180
-rw-r--r--slobrok/src/vespa/slobrok/server/service_mapping.h4
-rw-r--r--slobrok/src/vespa/slobrok/server/union_service_map.cpp1
5 files changed, 195 insertions, 0 deletions
diff --git a/slobrok/CMakeLists.txt b/slobrok/CMakeLists.txt
index 00ddf7296ca..153a029e74d 100644
--- a/slobrok/CMakeLists.txt
+++ b/slobrok/CMakeLists.txt
@@ -25,4 +25,5 @@ vespa_define_module(
src/tests/standalone
src/tests/startsome
src/tests/startup
+ src/tests/union_service_map
)
diff --git a/slobrok/src/tests/union_service_map/CMakeLists.txt b/slobrok/src/tests/union_service_map/CMakeLists.txt
new file mode 100644
index 00000000000..523294742f2
--- /dev/null
+++ b/slobrok/src/tests/union_service_map/CMakeLists.txt
@@ -0,0 +1,9 @@
+# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(slobrok_union_service_map_test_app TEST
+ SOURCES
+ union_service_map_test.cpp
+ DEPENDS
+ slobrok_slobrokserver
+ GTest::GTest
+)
+vespa_add_test(NAME slobrok_union_service_map_test_app COMMAND slobrok_union_service_map_test_app)
diff --git a/slobrok/src/tests/union_service_map/union_service_map_test.cpp b/slobrok/src/tests/union_service_map/union_service_map_test.cpp
new file mode 100644
index 00000000000..5f1f70fb9fb
--- /dev/null
+++ b/slobrok/src/tests/union_service_map/union_service_map_test.cpp
@@ -0,0 +1,180 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include <vespa/slobrok/server/union_service_map.h>
+#include <vespa/vespalib/gtest/gtest.h>
+#include <vespa/vespalib/util/stringfmt.h>
+
+using namespace vespalib;
+using namespace slobrok;
+using vespalib::make_string_short::fmt;
+
+enum class Event { NONE, ADD, REMOVE, UPDATE };
+
+struct MapObserver : public MapListener {
+ MapObserver();
+ virtual ~MapObserver();
+ void add(const ServiceMapping &mapping) override;
+ void remove(const ServiceMapping &mapping) override;
+ void update(const ServiceMapping &old_mapping,
+ const ServiceMapping &new_mapping) override;
+
+ Event last_event = Event::NONE;
+ ServiceMapping last_add = {{}, {}};
+ ServiceMapping last_remove = {{}, {}};
+
+ void clear() { last_event = Event::NONE; }
+};
+
+MapObserver::MapObserver() = default;
+MapObserver::~MapObserver() = default;
+
+void MapObserver::add(const ServiceMapping &mapping) {
+ last_event = Event::ADD;
+ last_add = mapping;
+}
+
+void MapObserver::remove(const ServiceMapping &mapping) {
+ last_event = Event::REMOVE;
+ last_remove = mapping;
+}
+
+void MapObserver::update(const ServiceMapping &old_mapping,
+ const ServiceMapping &new_mapping)
+{
+ last_event = Event::UPDATE;
+ last_remove = old_mapping;
+ last_add = new_mapping;
+}
+
+TEST(UnionServiceMapTest, forwards_simple_requests) {
+ ProxyMapSource source;
+ UnionServiceMap unionizer;
+ MapObserver observer;
+ unionizer.registerListener(observer);
+ source.registerListener(unionizer);
+
+ EXPECT_EQ(observer.last_event, Event::NONE);
+
+ ServiceMapping one{"foo/1", "bar/1"};
+ source.add(one);
+ EXPECT_EQ(observer.last_event, Event::ADD);
+ EXPECT_EQ(observer.last_add, one);
+ ServiceMapping two{"foo/2", "bar/2"};
+ source.add(two);
+ EXPECT_EQ(observer.last_event, Event::ADD);
+ EXPECT_EQ(observer.last_add, two);
+
+ source.remove(one);
+ EXPECT_EQ(observer.last_event, Event::REMOVE);
+ EXPECT_EQ(observer.last_remove, one);
+
+ ServiceMapping two_q{"foo/2", "qux/2"};
+ source.update(two, two_q);
+ // update implemented ass remove+add:
+ EXPECT_EQ(observer.last_event, Event::ADD);
+ EXPECT_EQ(observer.last_remove, two);
+ EXPECT_EQ(observer.last_add, two_q);
+}
+
+TEST(UnionServiceMapTest, handles_refcount) {
+ ProxyMapSource source1;
+ ProxyMapSource source2;
+ ProxyMapSource source3;
+ UnionServiceMap unionizer;
+ MapObserver observer;
+ unionizer.registerListener(observer);
+ source1.registerListener(unionizer);
+ source2.registerListener(unionizer);
+ source3.registerListener(unionizer);
+
+ EXPECT_EQ(observer.last_event, Event::NONE);
+ ServiceMapping one{"foo/1", "bar/1"};
+ source1.add(one);
+ EXPECT_EQ(observer.last_event, Event::ADD);
+ EXPECT_EQ(observer.last_add, one);
+ observer.clear();
+ EXPECT_EQ(observer.last_event, Event::NONE);
+ source2.add(one);
+ EXPECT_EQ(observer.last_event, Event::NONE);
+ source3.add(one);
+ EXPECT_EQ(observer.last_event, Event::NONE);
+ ServiceMapping two{"foo/2", "bar/2"};
+ source1.add(two);
+ EXPECT_EQ(observer.last_event, Event::ADD);
+ EXPECT_EQ(observer.last_add, two);
+ observer.clear();
+ EXPECT_EQ(observer.last_event, Event::NONE);
+ source2.add(two);
+ EXPECT_EQ(observer.last_event, Event::NONE);
+
+ source1.remove(one);
+ EXPECT_EQ(observer.last_event, Event::NONE);
+ source2.remove(one);
+ EXPECT_EQ(observer.last_event, Event::NONE);
+
+ source1.remove(two);
+ EXPECT_EQ(observer.last_event, Event::NONE);
+ source2.remove(two);
+ EXPECT_EQ(observer.last_event, Event::REMOVE);
+ EXPECT_EQ(observer.last_remove, two);
+
+ observer.clear();
+ EXPECT_EQ(observer.last_event, Event::NONE);
+ source3.remove(one);
+ EXPECT_EQ(observer.last_event, Event::REMOVE);
+ EXPECT_EQ(observer.last_remove, one);
+}
+
+TEST(UnionServiceMapTest, handles_conflicts) {
+ ProxyMapSource source1;
+ ProxyMapSource source2;
+ ProxyMapSource source3;
+ UnionServiceMap unionizer;
+ MapObserver observer;
+ unionizer.registerListener(observer);
+ source1.registerListener(unionizer);
+ source2.registerListener(unionizer);
+ source3.registerListener(unionizer);
+
+ EXPECT_EQ(observer.last_event, Event::NONE);
+ ServiceMapping one{"foo/1", "bar/1"};
+ source1.add(one);
+ EXPECT_EQ(observer.last_event, Event::ADD);
+ EXPECT_EQ(observer.last_add, one);
+ observer.clear();
+ source2.add(one);
+ EXPECT_EQ(observer.last_event, Event::NONE);
+
+ ServiceMapping two{"foo/2", "bar/2"};
+ source1.add(two);
+ EXPECT_EQ(observer.last_event, Event::ADD);
+ EXPECT_EQ(observer.last_add, two);
+ observer.clear();
+ source2.add(two);
+ EXPECT_EQ(observer.last_event, Event::NONE);
+
+ ServiceMapping one_q{"foo/1", "qux/1"};
+ source3.add(one_q);
+ EXPECT_EQ(observer.last_event, Event::REMOVE);
+ EXPECT_EQ(observer.last_remove, one);
+
+ ServiceMapping two_q{"foo/2", "qux/2"};
+ source3.add(two_q);
+ EXPECT_EQ(observer.last_event, Event::REMOVE);
+ EXPECT_EQ(observer.last_remove, two);
+
+ source3.remove(one_q);
+ EXPECT_EQ(observer.last_event, Event::ADD);
+ EXPECT_EQ(observer.last_add, one);
+
+ observer.clear();
+ source1.remove(two);
+ EXPECT_EQ(observer.last_event, Event::NONE);
+ source2.remove(two);
+ EXPECT_EQ(observer.last_event, Event::ADD);
+ EXPECT_EQ(observer.last_add, two_q);
+}
+
+
+GTEST_MAIN_RUN_ALL_TESTS()
+
diff --git a/slobrok/src/vespa/slobrok/server/service_mapping.h b/slobrok/src/vespa/slobrok/server/service_mapping.h
index 6561c120284..6c540b8e9b5 100644
--- a/slobrok/src/vespa/slobrok/server/service_mapping.h
+++ b/slobrok/src/vespa/slobrok/server/service_mapping.h
@@ -12,6 +12,10 @@ struct ServiceMapping {
vespalib::string spec;
ServiceMapping(const vespalib::string & name_, const vespalib::string & spec_) noexcept : name(name_), spec(spec_) { }
~ServiceMapping();
+
+ bool operator== (const ServiceMapping &other) const {
+ return name == other.name && spec == other.spec;
+ }
};
typedef std::vector<ServiceMapping> ServiceMappingList;
diff --git a/slobrok/src/vespa/slobrok/server/union_service_map.cpp b/slobrok/src/vespa/slobrok/server/union_service_map.cpp
index 226a0e0fa4b..f3d63f2a087 100644
--- a/slobrok/src/vespa/slobrok/server/union_service_map.cpp
+++ b/slobrok/src/vespa/slobrok/server/union_service_map.cpp
@@ -74,6 +74,7 @@ void UnionServiceMap::remove(const ServiceMapping &mapping)
void UnionServiceMap::update(const ServiceMapping &old_mapping,
const ServiceMapping &new_mapping)
{
+ LOG_ASSERT(old_mapping.name == new_mapping.name);
remove(old_mapping);
add(new_mapping);
}