TEST_F(ContextEnumeratorTest, VerifySimpleEnumeration) {
  // Create a pair of descendant contexts, verify we don't accidentally hit these when enumerating children
  AutoCreateContext outer;
  AutoCreateContext inner;
  CurrentContextPusher pshr(inner);

  // Add a few children to the current context:
  AutoCreateContext c1;
  AutoCreateContext c2;
  AutoCreateContext c3;
  AutoCreateContext c4;

  std::unordered_set<std::shared_ptr<CoreContext>> allCtxts;
  allCtxts.insert(AutoCurrentContext());
  allCtxts.insert(c1);
  allCtxts.insert(c2);
  allCtxts.insert(c3);
  allCtxts.insert(c4);

  // Create the enumerator, verify we get the expected count:
  size_t nContexts = 0;
  for(const std::shared_ptr<CoreContext>& cur : CurrentContextEnumerator()) {
    ASSERT_TRUE(!!allCtxts.count(cur)) << "Context enumerator accidentally enumerated a context not rooted in the specified parent";

    allCtxts.erase(cur);
    nContexts++;
  }

  ASSERT_EQ(5UL, nContexts) << "Context enumerator did not encounter the number of expected children";
  ASSERT_TRUE(allCtxts.empty()) << "Context enumerator did not encounter all children as expected";
}
TEST_F(ContextEnumeratorTest, ComplexRemovalInterference) {
  static const size_t nChildren = 50;

  // This time we use a vector, and we pop from the back of the vector unpredictably:
  std::vector<std::shared_ptr<CoreContext>> children(nChildren);
  for(size_t i = nChildren; i--;)
    children.push_back(AutoCreateContext());

  // Shuffle the collection to prevent the order here from being equivalent to the order in the context
  std::random_shuffle(children.begin(), children.end());

  // These are the elements actually encountered in the enumeration, held here to prevent expiration in the
  // event that we enumerate a context which should have already been evicted
  std::unordered_set<std::shared_ptr<CoreContext>> enumerated;

  // These are the elements eliminated from the vector.  By the time we're done the should all be expired.
  std::vector<std::weak_ptr<CoreContext>> eliminated;

  // Go through the enumeration, the totals should line up by the time we're done:
  for(const auto& cur : CurrentContextEnumerator()) {
    enumerated.insert(cur);
    
    // Pull off the last element:
    auto removed = children.back();
    children.pop_back();

    // If we haven't enumerated this element already, we want to mark it as eliminated-before-enumerated
    if(!enumerated.count(removed))
      eliminated.push_back(removed);
  }

  // Now verify that nothing we eliminated was enumerated:
  for(auto& cur : eliminated)
    ASSERT_TRUE(cur.expired()) << "Found an element that was iterated after it should have been unreachable";
}
Example #3
0
TEST_F(CoreContextTest, TestEnumerateChildren) {
  AutoCurrentContext ctxt;

  // Create a few anonymous children:
  AutoCreateContext child1;
  AutoCreateContext child2;
  AutoCreateContext child3;

  // Enumerate and see what we get back:
  std::set<std::shared_ptr<CoreContext>> allChildren;
  for(const auto& cur : CurrentContextEnumerator())
    allChildren.insert(cur);

  // Verify we get exactly four back:
  ASSERT_EQ(4UL, allChildren.size()) << "Failed to enumerate the correct number of child contexts";

  // Verify full membership:
  ASSERT_EQ(1UL, allChildren.count(ctxt)) << "Failed to find the root context in the returned context collection";

  const char* childMissing = "Failed to find a child context in the set of children";
  ASSERT_EQ(1UL, allChildren.count(child1)) << childMissing;
  ASSERT_EQ(1UL, allChildren.count(child2)) << childMissing;
  ASSERT_EQ(1UL, allChildren.count(child3)) << childMissing;

  //Check if filtering by sigil works
  AutoCreateContextT<Foo> fooCtxt;
  AutoCreateContextT<Bar> barCtxt;
  auto childFoo = barCtxt->Create<Foo>();

  ContextEnumeratorT<Foo> enumerator1(ctxt);
  std::vector<std::shared_ptr<CoreContext>> onlyFoos(enumerator1.begin(), enumerator1.end());
  ASSERT_EQ(2UL, onlyFoos.size()) << "Didn't collect only contexts with 'Foo' sigil";
  ASSERT_NE(std::find(onlyFoos.begin(), onlyFoos.end(), fooCtxt), onlyFoos.end()) << "Context not enumerated";
  ASSERT_NE(std::find(onlyFoos.begin(), onlyFoos.end(), childFoo), onlyFoos.end()) << "Context not enumerated";

  ContextEnumeratorT<Bar> enumerator2(ctxt);
  std::vector<std::shared_ptr<CoreContext>> onlyBars(enumerator2.begin(), enumerator2.end());
  ASSERT_EQ(1UL, onlyBars.size()) << "Didn't collect only contexts with 'Bar' sigil";
  ASSERT_NE(std::find(onlyBars.begin(), onlyBars.end(), barCtxt), onlyBars.end()) << "Context not enumerated";

  ContextEnumeratorT<Baz> enumerator3(ctxt);
  std::vector<std::shared_ptr<CoreContext>> noBaz(enumerator3.begin(), enumerator3.end());
  ASSERT_TRUE(noBaz.empty()) << "Incorrectly collected contexts with 'Baz' sigil";
}
TEST_F(ContextEnumeratorTest, SimpleRemovalInterference) {
  static const size_t nChildren = 5;

  // Create a few contexts which we intend to destroy as we go along:
  std::unordered_set<std::shared_ptr<CoreContext>> contexts;
  for(size_t i = nChildren; i--;)
    contexts.insert(AutoCreateContext());

  // Also add ourselves:
  contexts.insert(AutoCurrentContext());

  // Enumerate contexts, and remove them from the set:
  size_t nRemoved = 0;
  for(const auto& cur : CurrentContextEnumerator()) {
    ASSERT_TRUE(!!contexts.count(cur)) << "Failed to find a context enumerated by the context enumerator";
    contexts.erase(cur);
    nRemoved++;
  }

  // Verify we got the number removed we expected:
  ASSERT_EQ(nChildren + 1UL, nRemoved) << "Context enumerator did not remove the expected number of children";
}
Example #5
0
TEST_F(CoreContextTest, TestEarlyLambdaReturn) {
  AutoCurrentContext ctxt;

  // Create three children:
  AutoCreateContext child1;
  AutoCreateContext child2;
  AutoCreateContext child3;

  // Enumerate, but stop after three:
  std::vector<std::shared_ptr<CoreContext>> allChildren;
  size_t totalSoFar = 0;
  for(const auto& ctxt : CurrentContextEnumerator()) {
    if(totalSoFar++ == 3)
      break;
    allChildren.push_back(ctxt);
  }

  ASSERT_EQ(3UL, allChildren.size()) << "Enumeration routine failed to quit early";

  // Verify that the root context is the first one enumerated--needed to assure that we are executing a depth-first search
  ASSERT_EQ(ctxt, allChildren[0]) << "EnumerateChildContexts did not execute depth-first";
}