From ab7434e2721fdc858d26429ebb7916d1fa3511a5 Mon Sep 17 00:00:00 2001 From: Hyoung Ham Date: Fri, 21 Aug 2015 19:16:07 -0700 Subject: [PATCH 1/4] Add a test of multi-in with single-in decoration --- .../test/AutoFilterMultiDecorateTest.cpp | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/autowiring/test/AutoFilterMultiDecorateTest.cpp b/src/autowiring/test/AutoFilterMultiDecorateTest.cpp index c4e85ea2b..7e10daa78 100644 --- a/src/autowiring/test/AutoFilterMultiDecorateTest.cpp +++ b/src/autowiring/test/AutoFilterMultiDecorateTest.cpp @@ -50,6 +50,32 @@ TEST_F(AutoFilterMultiDecorateTest, MultiDecorateTest) { ASSERT_EQ(3, called) << "Not all lambda functions were called as expected"; } +TEST_F(AutoFilterMultiDecorateTest, MultiWithSingleDecorateTest) { + int called = 0; + float f_called = 0.0f; + + *factory += [&called](int& out) { out = called++; }; + *factory += [&called](int& out) { out = called++; }; + *factory += [&f_called](float& out) { out = ++f_called; }; + *factory += [&called](const int* vals [], const float& val) { + ASSERT_NE(nullptr, vals); + called++; + + // Guarantee that values were added in the expected order + int i; + for (i = 0; vals[i]; i++) + ASSERT_EQ(i, *(vals[i])) << "Incorrect values were added to the packet"; + + // Verify we got the number of values out that we wanted to get out + ASSERT_EQ(2, i) << "The wrong number of values were added to the packet"; + ASSERT_EQ(1.0f, val) << "The wrong number of val were added to the packet"; + }; + ASSERT_EQ(0, called) << "Lambda functions were called before expected"; + + auto packet = factory->NewPacket(); + ASSERT_EQ(3, called) << "Not all lambda functions were called as expected"; +} + TEST_F(AutoFilterMultiDecorateTest, MultiPostHocIntroductionTest) { int called = 0; From f23d118786c76a4541ce77b8f556c65e3aa40405 Mon Sep 17 00:00:00 2001 From: Jason Lokerson Date: Thu, 24 Sep 2015 19:33:57 -0700 Subject: [PATCH 2/4] Add AutoPacket::IsUnsatisfiable --- autowiring/AutoPacket.h | 10 ++++++++++ src/autowiring/AutoPacket.cpp | 16 ++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/autowiring/AutoPacket.h b/autowiring/AutoPacket.h index d6c7013a0..2608b682c 100644 --- a/autowiring/AutoPacket.h +++ b/autowiring/AutoPacket.h @@ -215,6 +215,16 @@ class AutoPacket: /// t_decorationMap GetDecorations(void) const; + /// + /// True if the specified type is unsatisfiable + /// + bool IsUnsatisfiable(const auto_id& id) const; + + template + bool IsUnsatisfiable(void) const { + return IsUnsatisfiable(auto_id_t{}); + } + /// /// True if this packet posesses one or more instances of a decoration of the specified type /// diff --git a/src/autowiring/AutoPacket.cpp b/src/autowiring/AutoPacket.cpp index 1aa4a16a6..1ce273776 100644 --- a/src/autowiring/AutoPacket.cpp +++ b/src/autowiring/AutoPacket.cpp @@ -412,13 +412,13 @@ const SatCounter& AutoPacket::GetSatisfaction(auto_id subscriber) const { void AutoPacket::ThrowNotDecoratedException(const DecorationKey& key) { std::stringstream ss; ss << "Attempted to obtain a type " << autowiring::demangle(key.id) << " which was not decorated on this packet"; - throw std::runtime_error(ss.str()); + throw autowiring_error(ss.str()); } void AutoPacket::ThrowMultiplyDecoratedException(const DecorationKey& key) { std::stringstream ss; ss << "Attempted to obtain a type " << autowiring::demangle(key.id) << " which was decorated more than once on this packet"; - throw std::runtime_error(ss.str()); + throw autowiring_error(ss.str()); } size_t AutoPacket::GetDecorationTypeCount(void) const @@ -433,6 +433,18 @@ AutoPacket::t_decorationMap AutoPacket::GetDecorations(void) const return m_decoration_map; } +bool AutoPacket::IsUnsatisfiable(const auto_id& id) const +{ + const DecorationDisposition* pDisposition = GetDisposition(DecorationKey{ id, 0 }); + if (!pDisposition) + return false; + if (!pDisposition->m_decorations.empty()) + return false; + if (pDisposition->m_nProducersRun == pDisposition->m_publishers.size()) + return false; + return true; +} + void AutoPacket::ForwardAll(const std::shared_ptr& recipient) const { // Copy decorations into an internal decorations maintenance collection. The values // in this collection are guaranteed to be stable in memory, and there are stable states From b79c70d613817c84bd28f1605bca54060caa3609 Mon Sep 17 00:00:00 2001 From: Jason Lokerson Date: Thu, 24 Sep 2015 19:40:21 -0700 Subject: [PATCH 3/4] Adding more checks in the multidecorate unit tests --- .../test/AutoFilterMultiDecorateTest.cpp | 44 ++++++++++++++++--- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/src/autowiring/test/AutoFilterMultiDecorateTest.cpp b/src/autowiring/test/AutoFilterMultiDecorateTest.cpp index 7e10daa78..d7ccb71c8 100644 --- a/src/autowiring/test/AutoFilterMultiDecorateTest.cpp +++ b/src/autowiring/test/AutoFilterMultiDecorateTest.cpp @@ -52,26 +52,56 @@ TEST_F(AutoFilterMultiDecorateTest, MultiDecorateTest) { TEST_F(AutoFilterMultiDecorateTest, MultiWithSingleDecorateTest) { int called = 0; - float f_called = 0.0f; + int f_called = 0; - *factory += [&called](int& out) { out = called++; }; - *factory += [&called](int& out) { out = called++; }; - *factory += [&f_called](float& out) { out = ++f_called; }; - *factory += [&called](const int* vals [], const float& val) { + *factory += [&called](AutoPacket& packet, Decoration<0>& out) { + ASSERT_FALSE(packet.IsUnsatisfiable>()); + ASSERT_FALSE(packet.IsUnsatisfiable>()); + out.i = called++; + }; + + *factory += [&called](AutoPacket& packet, Decoration<0>& out) { + ASSERT_FALSE(packet.IsUnsatisfiable>()); + ASSERT_FALSE(packet.IsUnsatisfiable>()); + out.i = called++; + }; + + *factory += [&f_called](AutoPacket& packet, Decoration<1>& out) { + ASSERT_FALSE(packet.IsUnsatisfiable>()); + ASSERT_FALSE(packet.IsUnsatisfiable>()); + out.i = ++f_called; + }; + + *factory += [&called](const Decoration<1>& val, const Decoration<0>* vals []) { ASSERT_NE(nullptr, vals); called++; // Guarantee that values were added in the expected order int i; for (i = 0; vals[i]; i++) - ASSERT_EQ(i, *(vals[i])) << "Incorrect values were added to the packet"; + ASSERT_EQ(i, vals[i]->i) << "Incorrect values were added to the packet"; // Verify we got the number of values out that we wanted to get out ASSERT_EQ(2, i) << "The wrong number of values were added to the packet"; - ASSERT_EQ(1.0f, val) << "The wrong number of val were added to the packet"; + ASSERT_EQ(1, val.i) << "The wrong number of val were added to the packet"; }; ASSERT_EQ(0, called) << "Lambda functions were called before expected"; + // Verify internal integrity of the factory using reflection: + int nOutputDec0 = 0; + int nOutputDec1 = 0; + for (auto& filter : factory->GetAutoFilters()) + for (auto arg = filter.GetAutoFilterArguments(); *arg; arg++) + if(arg->is_output) { + if (*arg->id.block->ti == typeid(Decoration<0>)) + nOutputDec0++; + else if (*arg->id.block->ti == typeid(Decoration<1>)) + nOutputDec1++; + } + + ASSERT_EQ(2UL, nOutputDec0) << "Counted an incorrect number of Decoration<0> publishers"; + ASSERT_EQ(1UL, nOutputDec1) << "Counted an incorrect number of Decoration<1> publishers"; + auto packet = factory->NewPacket(); ASSERT_EQ(3, called) << "Not all lambda functions were called as expected"; } From 6e9c857bbe9a085a2ed3a6edcfece6e4eb7cb773 Mon Sep 17 00:00:00 2001 From: Jason Lokerson Date: Thu, 24 Sep 2015 20:10:43 -0700 Subject: [PATCH 4/4] Fix the bug --- src/autowiring/AutoPacket.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/autowiring/AutoPacket.cpp b/src/autowiring/AutoPacket.cpp index 1ce273776..9f49d3ed7 100644 --- a/src/autowiring/AutoPacket.cpp +++ b/src/autowiring/AutoPacket.cpp @@ -225,7 +225,11 @@ void AutoPacket::UpdateSatisfactionUnsafe(std::unique_lock lk, const // Multiple decorations. Single-input types should never be encountered, but if they are, // we can't call them. Always call multi-input entries. for (auto subscriber : disposition.m_subscribers) { - if (subscriber.type == DecorationDisposition::Subscriber::Type::Multi) + if (subscriber.type != DecorationDisposition::Subscriber::Type::Multi) + throw autowiring_error("An AutoFilter was detected which has single-decorate inputs in a graph with multi-decorate outputs"); + + // One more entry for this input to consider + if(subscriber.satCounter->Decrement()) callQueue.push_back(subscriber.satCounter); } break;