Skip to content

Commit

Permalink
Make all type repetition errors explicit about type in AutoPacket.
Browse files Browse the repository at this point in the history
In order to see the output of an error, just remove the corresponding EXPECT_ANY_THROW enclosure in TEST_F(AutoFilterTest, VerifyNoMultiDecorate).
  • Loading branch information
GabrielHare committed Jul 30, 2014
1 parent da232c4 commit 104c6c0
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 7 deletions.
28 changes: 21 additions & 7 deletions autowiring/AutoPacket.h
Expand Up @@ -7,6 +7,8 @@
#include "is_shared_ptr.h"
#include "ObjectPool.h"
#include "is_any.h"
#include <sstream>
#include <typeinfo>
#include MEMORY_HEADER
#include TYPE_INDEX_HEADER
#include STL_UNORDERED_MAP
Expand Down Expand Up @@ -167,8 +169,12 @@ class AutoPacket:
template<class T>
const T& Get(void) const {
const T* retVal;
if(!Get(retVal))
throw_rethrowable autowiring_error("Attempted to obtain a value which was not decorated on this packet");
if(!Get(retVal)) {
std::stringstream ss;
ss << "Attempted to obtain a type " << typeid(retVal).name()
<< " which was not decorated on this packet";
throw std::runtime_error(ss.str());
}
return *retVal;
}

Expand Down Expand Up @@ -243,12 +249,16 @@ class AutoPacket:
auto& entry = m_decorations[typeid(type)];
if (entry.satisfied) {
std::stringstream ss;
ss << "Cannot decorate this packet with type " << typeid(type).name()
ss << "Cannot decorate this packet with type " << typeid(*ptr).name()
<< ", the requested decoration already exists";
throw std::runtime_error(ss.str());
}
if(entry.isCheckedOut)
throw std::runtime_error("Cannot check out this decoration, it's already checked out elsewhere");
if(entry.isCheckedOut) {
std::stringstream ss;
ss << "Cannot check out decoration of type " << typeid(*ptr).name()
<< ", it is already checked out elsewhere";
throw std::runtime_error(ss.str());
}
entry.isCheckedOut = true;
entry.wasCheckedOut = true;
}
Expand Down Expand Up @@ -353,8 +363,12 @@ class AutoPacket:
std::lock_guard<std::mutex> lk(m_lock);
for(size_t i = 0; i < sizeof...(Ts); i++) {
pTypeSubs[i] = &m_decorations[*sc_typeInfo[i]];
if(pTypeSubs[i]->wasCheckedOut)
throw std::runtime_error("Cannot perform immediate decoration with type T, the requested decoration already exists");
if(pTypeSubs[i]->wasCheckedOut) {
std::stringstream ss;
ss << "Cannot perform immediate decoration with type " << sc_typeInfo[i]->name()
<< ", the requested decoration already exists";
throw std::runtime_error(ss.str());
}

// Mark the entry as appropriate:
pTypeSubs[i]->satisfied = true;
Expand Down
18 changes: 18 additions & 0 deletions src/autowiring/test/AutoFilterTest.cpp
Expand Up @@ -158,6 +158,24 @@ TEST_F(AutoFilterTest, VerifyNoMultiDecorate) {
// Now finish saturating the filter and ensure we get a call:
packet->Decorate(Decoration<1>());
EXPECT_LT(0, filterA->m_called) << "Filter was not called after being fully satisfied";

// Verify that DecorateImmedaite also yields an exception
Decoration<0> localDeco0;
EXPECT_ANY_THROW(packet->DecorateImmediate(localDeco0)) << "Redundant immediate decoration did not throw an exception as expected";

//NOTE: A typedef will throw an exception
typedef Decoration<0> isDeco0type;
EXPECT_ANY_THROW(packet->DecorateImmediate(isDeco0type())) << "Typedef failed to throw exception";

//NOTE: Inheritance will not throw an exception
class ofDeco0alias: public Decoration<0> {};
try {
packet->Decorate(ofDeco0alias());
} catch (...) {
FAIL() << "Class with inheritance reinterpreted as child type";
}

EXPECT_ANY_THROW(packet->DecorateImmediate(Decoration<2>(), Decoration<2>())) << "Repeated type in immediate decoration was not identified as an error";
}

TEST_F(AutoFilterTest, VerifyNoNullCheckout) {
Expand Down

0 comments on commit 104c6c0

Please sign in to comment.