Пример #1
0
void test_insert_one_then_split_gap()
{
  TransportReassembly tr;
  Gaps gaps;
  SequenceNumber msg_seq(17);
  RepoId pub_id = create_pub_id();
  Sample data(pub_id, msg_seq);

  TEST_ASSERT(!tr.reassemble(1, true, data.sample)); // 1
  TEST_ASSERT(!tr.reassemble(6, true, data.sample)); // 1,6
  CORBA::ULong base = gaps.get(tr, msg_seq, pub_id);

  TEST_ASSERT(2 == base);             // Gap from 2-5
  TEST_ASSERT(4 == gaps.result_bits); // Number of bits
  TEST_ASSERT(gaps.check_gap(2));     // Gap
  TEST_ASSERT(gaps.check_gap(3));     // Gap
  TEST_ASSERT(gaps.check_gap(4));     // Gap
  TEST_ASSERT(gaps.check_gap(5));     // Gap
  TEST_ASSERT(!gaps.check_gap(6));    // No gap

  TEST_ASSERT(!tr.reassemble(4, true, data.sample)); // 1,4,6
  TEST_ASSERT(!tr.reassemble(3, true, data.sample)); // 1,3-4,6
  base = gaps.get(tr, msg_seq, pub_id);

  TEST_ASSERT(2 == base);             // Gap at 2 and 5
  TEST_ASSERT(4 == gaps.result_bits); // Number of bits
  TEST_ASSERT(gaps.check_gap(2));     // Gap
  TEST_ASSERT(!gaps.check_gap(3));    // No gap
  TEST_ASSERT(!gaps.check_gap(4));    // No gap
  TEST_ASSERT(gaps.check_gap(5));     // Gap
  TEST_ASSERT(!gaps.check_gap(6));    // No gap
}
Пример #2
0
void test_empty()
{
  TransportReassembly tr;
  Gaps gaps;
  SequenceNumber seq(1);
  RepoId pub_id = create_pub_id();
  TEST_ASSERT(!tr.has_frags(seq, pub_id));
  TEST_ASSERT(0 == gaps.get(tr, seq, pub_id));
}
Пример #3
0
void test_insert_has_frag()
{
  TransportReassembly tr;
  Gaps gaps;
  SequenceNumber msg_seq(4);
  SequenceNumber frag_seq(1);
  RepoId pub_id = create_pub_id();
  Sample data(pub_id, msg_seq);
  tr.reassemble(frag_seq, true, data.sample);
  TEST_ASSERT(tr.has_frags(msg_seq, pub_id));
}
Пример #4
0
void test_first_insert_has_no_gaps()
{
  TransportReassembly tr;
  Gaps gaps;
  SequenceNumber msg_seq(18);
  SequenceNumber frag_seq(1);
  RepoId pub_id = create_pub_id();
  Sample data(pub_id, msg_seq);

  TEST_ASSERT(!tr.reassemble(frag_seq, true, data.sample));
  CORBA::ULong base = gaps.get(tr, msg_seq, pub_id);

  TEST_ASSERT(tr.has_frags(msg_seq, pub_id));
  TEST_ASSERT(2 == base);             // Now expecting 2
  TEST_ASSERT(1 == gaps.result_bits); // Only one bit
  TEST_ASSERT(gaps.check_gap(2));     // Gap
  TEST_ASSERT(!gaps.check_gap(3));    // No gap
}
Пример #5
0
void test_insert_gaps()
{
  TransportReassembly tr;
  Gaps gaps;
  SequenceNumber msg_seq(9);
  SequenceNumber frag_seq(4);
  RepoId pub_id = create_pub_id();
  Sample data(pub_id, msg_seq);

  tr.reassemble(frag_seq, true, data.sample);
  CORBA::ULong base = gaps.get(tr, msg_seq, pub_id);

  TEST_ASSERT(1 == base);             // Gap from 1-3
  TEST_ASSERT(3 == gaps.result_bits); // Only one bit
  TEST_ASSERT(gaps.check_gap(1));     // Gap
  TEST_ASSERT(gaps.check_gap(2));     // Gap
  TEST_ASSERT(gaps.check_gap(3));     // Gap
  TEST_ASSERT(!gaps.check_gap(4));    // No gap
}
Пример #6
0
void test_fill_rtol()
{
  TransportReassembly tr;
  Gaps gaps;
  SequenceNumber msg_seq(17);
  RepoId pub_id = create_pub_id();
  Sample data(pub_id, msg_seq);

  TEST_ASSERT(!tr.reassemble(1, true, data.sample)); // 1
  TEST_ASSERT(!tr.reassemble(6, true, data.sample)); // 1,6
  CORBA::ULong base = gaps.get(tr, msg_seq, pub_id);

  TEST_ASSERT(2 == base);             // Gap from 2-5
  TEST_ASSERT(4 == gaps.result_bits); // Number of bits
  TEST_ASSERT(gaps.check_gap(2));     // Gap
  TEST_ASSERT(gaps.check_gap(3));     // Gap
  TEST_ASSERT(gaps.check_gap(4));     // Gap
  TEST_ASSERT(gaps.check_gap(5));     // Gap
  TEST_ASSERT(!gaps.check_gap(6));    // No gap

  TEST_ASSERT(!tr.reassemble(5, true, data.sample)); // 1,5-6
  TEST_ASSERT(!tr.reassemble(4, true, data.sample)); // 1,4-6
  base = gaps.get(tr, msg_seq, pub_id);

  TEST_ASSERT(2 == base);             // Gap from 2-3
  TEST_ASSERT(2 == gaps.result_bits); // Number of bits
  TEST_ASSERT(gaps.check_gap(2));     // Gap
  TEST_ASSERT(gaps.check_gap(3));     // Gap
  TEST_ASSERT(!gaps.check_gap(4));    // No gap
  TEST_ASSERT(!gaps.check_gap(5));    // No gap
  TEST_ASSERT(!gaps.check_gap(6));    // No gap

  TEST_ASSERT(!tr.reassemble(3, true, data.sample)); // 1,3-6
  TEST_ASSERT(!tr.reassemble(2, true, data.sample)); // 1-6
  base = gaps.get(tr, msg_seq, pub_id);

  TEST_ASSERT(7 == base);             // Gap from 2-3
  TEST_ASSERT(1 == gaps.result_bits); // Number of bits
  TEST_ASSERT(gaps.check_gap(7));     // Gap
  TEST_ASSERT(!gaps.check_gap(8));    // No gap
}
Пример #7
0
void test_insert_one_then_gap()
{
  TransportReassembly tr;
  Gaps gaps;
  SequenceNumber msg_seq(17);
  SequenceNumber frag_seq1(1);
  SequenceNumber frag_seq2(6);
  RepoId pub_id = create_pub_id();
  Sample data(pub_id, msg_seq);

  tr.reassemble(frag_seq1, true, data.sample);
  tr.reassemble(frag_seq2, true, data.sample);
  CORBA::ULong base = gaps.get(tr, msg_seq, pub_id);

  TEST_ASSERT(2 == base);             // Gap from 2-5
  TEST_ASSERT(4 == gaps.result_bits); // Number of bits
  TEST_ASSERT(gaps.check_gap(2));     // Gap
  TEST_ASSERT(gaps.check_gap(3));     // Gap
  TEST_ASSERT(gaps.check_gap(4));     // Gap
  TEST_ASSERT(gaps.check_gap(5));     // Gap
  TEST_ASSERT(!gaps.check_gap(6));    // No gap
}
Пример #8
0
int ACE_TMAIN(int, ACE_TCHAR*[])
{
  try
  {
    DataSampleHeader dsh;
    const size_t N = 300;
    dsh.message_length_ = N;
    ACE_Message_Block header_mb(DataSampleHeader::max_marshaled_size());
    header_mb << dsh;

    { // simple case: no content-filter, data in a single messageblock
      ACE_Message_Block data(N);
      data.wr_ptr(N);
      header_mb.cont(&data);
      Fragments f;
      DataSampleHeader::split(header_mb, N / 2 + header_mb.length(),
        f.head_, f.tail_);

      DataSampleHeader header1(*f.head_);
      TEST_CHECK(header1.more_fragments_);
      TEST_CHECK(header1.message_length_ == N / 2);
      TEST_CHECK(f.head_->cont());
      TEST_CHECK(f.head_->cont()->length() == N / 2);
      TEST_CHECK(!f.head_->cont()->cont());

      DataSampleHeader header2(*f.tail_);
      TEST_CHECK(!header2.more_fragments_);
      TEST_CHECK(header2.message_length_ == N / 2);
      TEST_CHECK(f.tail_->cont());
      TEST_CHECK(f.tail_->cont()->length() == N / 2);
      TEST_CHECK(!f.tail_->cont()->cont());

      DataSampleHeader reassembled;
      TEST_CHECK(DataSampleHeader::join(header1, header2, reassembled));
      TEST_CHECK(reassembled.sequence_ == header1.sequence_);
      TEST_CHECK(reassembled.sequence_ == header2.sequence_);
      TEST_CHECK(!reassembled.more_fragments_);
      TEST_CHECK(reassembled.message_length_ == N);

      ReceivedDataSample rds1(f.head_->cont()->duplicate()),
        rds2(f.tail_->cont()->duplicate());
      rds1.header_ = header1;
      rds2.header_ = header2;
      TransportReassembly tr;
      TEST_CHECK(!tr.reassemble(4, true, rds1));
      TEST_CHECK(tr.reassemble(5, false, rds2));
      TEST_CHECK(rds2.sample_ && rds2.sample_->total_length() == N);

      ReceivedDataSample rds1b(f.head_->cont()->duplicate()),
        rds2b(f.tail_->cont()->duplicate());
      rds1b.header_ = header1;
      rds2b.header_ = header2;
      TransportReassembly tr2;
      TEST_CHECK(!tr2.reassemble(5, false, rds2b));
      TEST_CHECK(tr2.reassemble(4, true, rds1b));
      TEST_CHECK(rds1b.sample_ && rds1b.sample_->total_length() == N);
    }
    { // data split into 3 messageblocks, fragment in the middle of block #2
      ACE_Message_Block data1(N / 3), data2(N / 3), data3(N / 3);
      data1.wr_ptr(N / 3);
      data2.wr_ptr(N / 3);
      data3.wr_ptr(N / 3);
      header_mb.cont(&data1);
      data1.cont(&data2);
      data2.cont(&data3);
      Fragments f;
      DataSampleHeader::split(header_mb, N / 2 + header_mb.length(),
        f.head_, f.tail_);

      DataSampleHeader header(*f.head_);
      TEST_CHECK(header.more_fragments_);
      TEST_CHECK(header.message_length_ == N / 2);
      TEST_CHECK(f.head_->cont());
      TEST_CHECK(f.head_->cont()->length() == N / 3);
      TEST_CHECK(f.head_->cont()->cont()->length() == N / 6);
      TEST_CHECK(!f.head_->cont()->cont()->cont());

      header = *f.tail_;
      TEST_CHECK(!header.more_fragments_);
      TEST_CHECK(header.message_length_ == N / 2);
      TEST_CHECK(f.tail_->cont());
      TEST_CHECK(f.tail_->cont()->length() == N / 6);
      TEST_CHECK(f.tail_->cont()->cont()->length() == N / 3);
      TEST_CHECK(!f.tail_->cont()->cont()->cont());
    }
    { // data split into 4 messageblocks, fragment at the block division
      ACE_Message_Block data1(N / 4), data2(N / 4), data3(N / 4), data4(N / 4);
      data1.wr_ptr(N / 4);
      data2.wr_ptr(N / 4);
      data3.wr_ptr(N / 4);
      data4.wr_ptr(N / 4);
      header_mb.cont(&data1);
      data1.cont(&data2);
      data2.cont(&data3);
      data3.cont(&data4);
      Fragments f;
      DataSampleHeader::split(header_mb, N / 2 + header_mb.length(),
        f.head_, f.tail_);

      DataSampleHeader header(*f.head_);
      TEST_CHECK(header.more_fragments_);
      TEST_CHECK(header.message_length_ == N / 2);
      TEST_CHECK(f.head_->cont());
      TEST_CHECK(f.head_->cont()->length() == N / 4);
      TEST_CHECK(f.head_->cont()->cont()->length() == N / 4);
      TEST_CHECK(!f.head_->cont()->cont()->cont());

      header = *f.tail_;
      TEST_CHECK(!header.more_fragments_);
      TEST_CHECK(header.message_length_ == N / 2);
      TEST_CHECK(f.tail_->cont());
      TEST_CHECK(f.tail_->cont()->length() == N / 4);
      TEST_CHECK(f.tail_->cont()->cont()->length() == N / 4);
      TEST_CHECK(!f.tail_->cont()->cont()->cont());
    }
    { // 3 fragments needed: first split into 2 and then split the 2nd
      ACE_Message_Block data(N);
      data.wr_ptr(N);
      header_mb.cont(&data);
      Fragments f;
      DataSampleHeader::split(header_mb, N / 3 + header_mb.length(),
        f.head_, f.tail_);

      DataSampleHeader header1(*f.head_);
      TEST_CHECK(header1.more_fragments_);
      TEST_CHECK(header1.message_length_ == N / 3);
      TEST_CHECK(f.head_->cont());
      TEST_CHECK(f.head_->cont()->length() == N / 3);
      TEST_CHECK(!f.head_->cont()->cont());

      DataSampleHeader header2(*f.tail_);
      TEST_CHECK(!header2.more_fragments_);
      TEST_CHECK(header2.message_length_ == 2 * N / 3);
      TEST_CHECK(f.tail_->cont());
      TEST_CHECK(f.tail_->cont()->length() == 2 * N / 3);
      TEST_CHECK(!f.tail_->cont()->cont());

      Fragments f2;
      f.tail_->rd_ptr(f.tail_->base());
      DataSampleHeader::split(*f.tail_, N / 3 + header_mb.length(),
        f2.head_, f2.tail_);

      DataSampleHeader header2a(*f2.head_);
      TEST_CHECK(header2a.more_fragments_);
      TEST_CHECK(header2a.message_length_ == N / 3);
      TEST_CHECK(f2.head_->cont());
      TEST_CHECK(f2.head_->cont()->length() == N / 3);
      TEST_CHECK(!f2.head_->cont()->cont());

      DataSampleHeader header2b(*f2.tail_);
      TEST_CHECK(!header2b.more_fragments_);
      TEST_CHECK(header2b.message_length_ == N / 3);
      TEST_CHECK(f2.tail_->cont());
      TEST_CHECK(f2.tail_->cont()->length() == N / 3);
      TEST_CHECK(!f2.tail_->cont()->cont());

      // Test all permutations of order of reception of the 3 fragments
      {
        ReceivedDataSample rds1(f.head_->cont()->duplicate()),
          rds2(f2.head_->cont()->duplicate()),
          rds3(f2.tail_->cont()->duplicate());
        rds1.header_ = header1;
        rds2.header_ = header2a;
        rds3.header_ = header2b;
        TransportReassembly tr;
        TEST_CHECK(!tr.reassemble(1, true, rds1));
        TEST_CHECK(!tr.reassemble(2, false, rds2));
        TEST_CHECK(tr.reassemble(3, false, rds3));
        TEST_CHECK(rds3.sample_ && rds3.sample_->total_length() == N);
      }
      {
        ReceivedDataSample rds1(f.head_->cont()->duplicate()),
          rds2(f2.head_->cont()->duplicate()),
          rds3(f2.tail_->cont()->duplicate());
        rds1.header_ = header1;
        rds2.header_ = header2a;
        rds3.header_ = header2b;
        TransportReassembly tr;
        TEST_CHECK(!tr.reassemble(1, true, rds1));
        TEST_CHECK(!tr.reassemble(3, false, rds3));
        TEST_CHECK(tr.reassemble(2, false, rds2));
        TEST_CHECK(rds2.sample_ && rds2.sample_->total_length() == N);
      }
      {
        ReceivedDataSample rds1(f.head_->cont()->duplicate()),
          rds2(f2.head_->cont()->duplicate()),
          rds3(f2.tail_->cont()->duplicate());
        rds1.header_ = header1;
        rds2.header_ = header2a;
        rds3.header_ = header2b;
        TransportReassembly tr;
        TEST_CHECK(!tr.reassemble(2, false, rds2));
        TEST_CHECK(!tr.reassemble(1, true, rds1));
        TEST_CHECK(tr.reassemble(3, false, rds3));
        TEST_CHECK(rds3.sample_ && rds3.sample_->total_length() == N);
      }
      {
        ReceivedDataSample rds1(f.head_->cont()->duplicate()),
          rds2(f2.head_->cont()->duplicate()),
          rds3(f2.tail_->cont()->duplicate());
        rds1.header_ = header1;
        rds2.header_ = header2a;
        rds3.header_ = header2b;
        TransportReassembly tr;
        TEST_CHECK(!tr.reassemble(2, false, rds2));
        TEST_CHECK(!tr.reassemble(3, false, rds3));
        TEST_CHECK(tr.reassemble(1, true, rds1));
        TEST_CHECK(rds1.sample_ && rds1.sample_->total_length() == N);
      }
      {
        ReceivedDataSample rds1(f.head_->cont()->duplicate()),
          rds2(f2.head_->cont()->duplicate()),
          rds3(f2.tail_->cont()->duplicate());
        rds1.header_ = header1;
        rds2.header_ = header2a;
        rds3.header_ = header2b;
        TransportReassembly tr;
        TEST_CHECK(!tr.reassemble(3, false, rds3));
        TEST_CHECK(!tr.reassemble(1, true, rds1));
        TEST_CHECK(tr.reassemble(2, false, rds2));
        TEST_CHECK(rds2.sample_ && rds2.sample_->total_length() == N);
      }
      {
        ReceivedDataSample rds1(f.head_->cont()->duplicate()),
          rds2(f2.head_->cont()->duplicate()),
          rds3(f2.tail_->cont()->duplicate());
        rds1.header_ = header1;
        rds2.header_ = header2a;
        rds3.header_ = header2b;
        TransportReassembly tr;
        TEST_CHECK(!tr.reassemble(3, false, rds3));
        TEST_CHECK(!tr.reassemble(2, false, rds2));
        TEST_CHECK(tr.reassemble(1, true, rds1));
        TEST_CHECK(rds1.sample_ && rds1.sample_->total_length() == N);
      }
      // Test data_unavailable() scenarios
      {
        ReceivedDataSample rds1(f.head_->cont()->duplicate()),
          rds3(f2.tail_->cont()->duplicate());
        rds1.header_ = header1;
        rds3.header_ = header2b;
        TransportReassembly tr;
        TEST_CHECK(!tr.reassemble(1, true, rds1));
        tr.data_unavailable(SequenceRange(2, 2));
        TEST_CHECK(!tr.reassemble(3, false, rds3));
      }
      {
        ReceivedDataSample rds1(f.head_->cont()->duplicate()),
          rds3(f2.tail_->cont()->duplicate());
        rds1.header_ = header1;
        rds3.header_ = header2b;
        TransportReassembly tr;
        TEST_CHECK(!tr.reassemble(3, false, rds3));
        tr.data_unavailable(SequenceRange(2, 2));
        TEST_CHECK(!tr.reassemble(1, true, rds1));
      }
      {
        ReceivedDataSample rds1(f.head_->cont()->duplicate()),
          rds2(f2.head_->cont()->duplicate());
        rds1.header_ = header1;
        rds2.header_ = header2a;
        TransportReassembly tr;
        TEST_CHECK(!tr.reassemble(2, false, rds2));
        tr.data_unavailable(SequenceRange(3, 3));
        TEST_CHECK(!tr.reassemble(1, true, rds1));
      }
    }
    { // content filtering flag with no "entries" (adds another MB to the chain)
      ACE_Message_Block data(N);
      data.wr_ptr(N);
      header_mb.cont(&data);
      DataSampleHeader::set_flag(CONTENT_FILTER_FLAG, &header_mb);
      DataSampleHeader::add_cfentries(0, &header_mb);
      Fragments f;
      const size_t FRAG = 100; // arbitrary split at 100 bytes
      DataSampleHeader::split(header_mb, FRAG, f.head_, f.tail_);

      DataSampleHeader header1(*f.head_);
      TEST_CHECK(header1.more_fragments_);
      TEST_CHECK(header1.content_filter_);
      TEST_CHECK(header1.content_filter_entries_.length() == 0);
      const size_t hdr_len = header_mb.length() + header_mb.cont()->length();
      release_cfentries(header_mb);

      TEST_CHECK(header1.message_length_ == FRAG - hdr_len);
      TEST_CHECK(f.head_->length() == 0); // consumed by DataSampleHeader
      TEST_CHECK(f.head_->cont());
      TEST_CHECK(f.head_->cont()->length() == 0); // consumed by DataSampleHeader
      TEST_CHECK(f.head_->cont()->cont());
      TEST_CHECK(f.head_->cont()->cont()->length() == header1.message_length_);
      TEST_CHECK(!f.head_->cont()->cont()->cont());

      DataSampleHeader header2(*f.tail_);
      TEST_CHECK(!header2.more_fragments_);
      TEST_CHECK(!header2.content_filter_);
      TEST_CHECK(header2.message_length_ == N - (FRAG - hdr_len));
      TEST_CHECK(f.tail_->length() == 0); // consumed by DataSampleHeader
      TEST_CHECK(f.tail_->cont());
      TEST_CHECK(f.tail_->cont()->length() == header2.message_length_);
      TEST_CHECK(!f.tail_->cont()->cont());

      DataSampleHeader reassembled;
      TEST_CHECK(DataSampleHeader::join(header1, header2, reassembled));
      TEST_CHECK(reassembled.sequence_ == header1.sequence_);
      TEST_CHECK(reassembled.sequence_ == header2.sequence_);
      TEST_CHECK(!reassembled.more_fragments_);
      TEST_CHECK(reassembled.message_length_ == N);
      TEST_CHECK(reassembled.content_filter_);
    }
    { // content filtering with some "entries" that all fit in the fragment
      ACE_Message_Block data(N);
      data.wr_ptr(N);
      header_mb.cont(&data);
      DataSampleHeader::set_flag(CONTENT_FILTER_FLAG, &header_mb);
      const size_t CF_ENTRIES = 6; // serializes to 100 bytes
      GUIDSeq entries(CF_ENTRIES);
      entries.length(CF_ENTRIES);
      DataSampleHeader::add_cfentries(&entries, &header_mb);
      Fragments f;
      const size_t FRAG = 200;
      DataSampleHeader::split(header_mb, FRAG, f.head_, f.tail_);
      release_cfentries(header_mb);

      DataSampleHeader header1(*f.head_);
      TEST_CHECK(header1.more_fragments_);
      TEST_CHECK(header1.content_filter_);
      TEST_CHECK(header1.content_filter_entries_.length() == CF_ENTRIES);
      TEST_CHECK(header1.message_length_ > 0);
      TEST_CHECK(f.head_->length() == 0); // consumed by DataSampleHeader
      TEST_CHECK(f.head_->cont());
      TEST_CHECK(f.head_->cont()->length() == 0); // consumed by DataSampleHeader
      TEST_CHECK(f.head_->cont()->cont());
      const size_t frag_payload = f.head_->cont()->cont()->length();
      TEST_CHECK(frag_payload > 0);
      TEST_CHECK(!f.head_->cont()->cont()->cont());

      DataSampleHeader header2(*f.tail_);
      TEST_CHECK(!header2.more_fragments_);
      TEST_CHECK(!header2.content_filter_);
      TEST_CHECK(header2.message_length_ + frag_payload == N);
      TEST_CHECK(f.tail_->length() == 0); // consumed by DataSampleHeader
      TEST_CHECK(f.tail_->cont());
      TEST_CHECK(f.tail_->cont()->length() == header2.message_length_);
      TEST_CHECK(!f.tail_->cont()->cont());

      DataSampleHeader reassembled;
      TEST_CHECK(DataSampleHeader::join(header1, header2, reassembled));
      TEST_CHECK(reassembled.sequence_ == header1.sequence_);
      TEST_CHECK(reassembled.sequence_ == header2.sequence_);
      TEST_CHECK(!reassembled.more_fragments_);
      TEST_CHECK(reassembled.message_length_ == N);
      TEST_CHECK(reassembled.content_filter_);
      TEST_CHECK(reassembled.content_filter_entries_.length() == CF_ENTRIES);
    }
    { // content filtering with some "entries", split inside the entires
      ACE_Message_Block data(N);
      data.wr_ptr(N);
      header_mb.cont(&data);
      DataSampleHeader::set_flag(CONTENT_FILTER_FLAG, &header_mb);
      const size_t CF_ENTRIES = 6; // serializes to 100 bytes
      GUIDSeq entries(CF_ENTRIES);
      entries.length(CF_ENTRIES);
      DataSampleHeader::add_cfentries(&entries, &header_mb);
      Fragments f;
      const size_t FRAG = 68;
      DataSampleHeader::split(header_mb, FRAG, f.head_, f.tail_);
      release_cfentries(header_mb);

      DataSampleHeader header1(*f.head_);
      TEST_CHECK(header1.more_fragments_);
      TEST_CHECK(header1.content_filter_);
      const size_t entries_in_header = header1.content_filter_entries_.length();
      TEST_CHECK(entries_in_header > 0);
      TEST_CHECK(header1.message_length_ == 0);
      TEST_CHECK(f.head_->length() == 0); // consumed by DataSampleHeader
      TEST_CHECK(f.head_->cont());
      TEST_CHECK(f.head_->cont()->length() == 0); // consumed by DataSampleHeader
      TEST_CHECK(!f.head_->cont()->cont());

      DataSampleHeader header2(*f.tail_);
      TEST_CHECK(!header2.more_fragments_);
      TEST_CHECK(header2.content_filter_);
      TEST_CHECK(header2.content_filter_entries_.length()
        + entries_in_header == CF_ENTRIES);
      TEST_CHECK(header2.message_length_ == N);
      TEST_CHECK(f.tail_->length() == 0); // consumed by DataSampleHeader
      TEST_CHECK(f.tail_->cont());
      TEST_CHECK(f.tail_->cont()->length() == 0); // consumed by DataSampleHeader
      TEST_CHECK(f.tail_->cont()->cont());
      TEST_CHECK(f.tail_->cont()->cont()->length() == N);
      TEST_CHECK(!f.tail_->cont()->cont()->cont());

      DataSampleHeader reassembled;
      TEST_CHECK(DataSampleHeader::join(header1, header2, reassembled));
      TEST_CHECK(reassembled.sequence_ == header1.sequence_);
      TEST_CHECK(reassembled.sequence_ == header2.sequence_);
      TEST_CHECK(!reassembled.more_fragments_);
      TEST_CHECK(reassembled.message_length_ == N);
      TEST_CHECK(reassembled.content_filter_);
      TEST_CHECK(reassembled.content_filter_entries_.length() == CF_ENTRIES);
    }
  }
  catch (const CORBA::BAD_PARAM& ex)
  {
    ex._tao_print_exception("Exception caught in Fragmentation.cpp:");
    return 1;
  }
  return 0;
}