Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a test of multi-in with single-in decoration #734

Merged
merged 5 commits into from
Sep 25, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions autowiring/AutoPacket.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,16 @@ class AutoPacket:
/// </remarks>
t_decorationMap GetDecorations(void) const;

/// <returns>
/// True if the specified type is unsatisfiable
/// </returns>
bool IsUnsatisfiable(const auto_id& id) const;

template<typename T>
bool IsUnsatisfiable(void) const {
return IsUnsatisfiable(auto_id_t<T>{});
}

/// <returns>
/// True if this packet posesses one or more instances of a decoration of the specified type
/// </returns>
Expand Down
22 changes: 19 additions & 3 deletions src/autowiring/AutoPacket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,11 @@ void AutoPacket::UpdateSatisfactionUnsafe(std::unique_lock<std::mutex> 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;
Expand Down Expand Up @@ -412,13 +416,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
Expand All @@ -433,6 +437,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<AutoPacket>& 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
Expand Down
56 changes: 56 additions & 0 deletions src/autowiring/test/AutoFilterMultiDecorateTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,62 @@ TEST_F(AutoFilterMultiDecorateTest, MultiDecorateTest) {
ASSERT_EQ(3, called) << "Not all lambda functions were called as expected";
}

TEST_F(AutoFilterMultiDecorateTest, MultiWithSingleDecorateTest) {
int called = 0;
int f_called = 0;

*factory += [&called](AutoPacket& packet, Decoration<0>& out) {
ASSERT_FALSE(packet.IsUnsatisfiable<Decoration<0>>());
ASSERT_FALSE(packet.IsUnsatisfiable<Decoration<1>>());
out.i = called++;
};

*factory += [&called](AutoPacket& packet, Decoration<0>& out) {
ASSERT_FALSE(packet.IsUnsatisfiable<Decoration<0>>());
ASSERT_FALSE(packet.IsUnsatisfiable<Decoration<1>>());
out.i = called++;
};

*factory += [&f_called](AutoPacket& packet, Decoration<1>& out) {
ASSERT_FALSE(packet.IsUnsatisfiable<Decoration<0>>());
ASSERT_FALSE(packet.IsUnsatisfiable<Decoration<1>>());
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]->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, 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";
}

TEST_F(AutoFilterMultiDecorateTest, MultiPostHocIntroductionTest) {
int called = 0;

Expand Down