Refactoring RtpFormatVp8Test

This is the first change in a series of changes to get new functionality
into the VP8 packetizer.

This first refactors the RtpFormatVp8Test class, without changing the
operation of the tested RtpFormatVp8 class. A test helper class
RtpFormatVp8TestHelper is introduced to reduce code duplication.

Review URL: http://webrtc-codereview.appspot.com/304009

git-svn-id: http://webrtc.googlecode.com/svn/trunk@1258 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/src/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.cc b/src/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.cc
new file mode 100644
index 0000000..4c9e386
--- /dev/null
+++ b/src/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.cc
@@ -0,0 +1,248 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h"
+
+#include "gtest/gtest.h"
+
+namespace webrtc {
+
+namespace test {
+
+RtpFormatVp8TestHelper::RtpFormatVp8TestHelper(const RTPVideoHeaderVP8* hdr)
+    : payload_data_(NULL),
+      buffer_(NULL),
+      fragmentation_(NULL),
+      hdr_info_(hdr),
+      sloppy_partitioning_(false),
+      inited_(false) {}
+
+RtpFormatVp8TestHelper::~RtpFormatVp8TestHelper() {
+  delete fragmentation_;
+  delete [] payload_data_;
+  delete [] buffer_;
+}
+
+bool RtpFormatVp8TestHelper::Init(const int* partition_sizes,
+                                  int num_partitions) {
+  if (inited_) return false;
+  fragmentation_ = new RTPFragmentationHeader;
+  fragmentation_->VerifyAndAllocateFragmentationHeader(num_partitions);
+  payload_size_ = 0;
+  // Calculate sum payload size.
+  for (int p = 0; p < num_partitions; ++p) {
+    payload_size_ += partition_sizes[p];
+  }
+  buffer_size_ = payload_size_ + 6;  // Add space for payload descriptor.
+  payload_data_ = new WebRtc_UWord8[payload_size_];
+  buffer_ = new WebRtc_UWord8[buffer_size_];
+  int j = 0;
+  // Loop through the partitions again.
+  for (int p = 0; p < num_partitions; ++p) {
+    fragmentation_->fragmentationLength[p] = partition_sizes[p];
+    fragmentation_->fragmentationOffset[p] = j;
+    for (int i = 0; i < partition_sizes[p]; ++i) {
+      assert(j < payload_size_);
+      payload_data_[j++] = p;  // Set the payload value to the partition index.
+    }
+  }
+  data_ptr_ = payload_data_;
+  inited_ = true;
+  return true;
+}
+
+void RtpFormatVp8TestHelper::GetAllPacketsAndCheck(
+    RtpFormatVp8* packetizer,
+    const int* expected_sizes,
+    const int* expected_part,
+    const bool* expected_frag_start,
+    const int* max_size,
+    int expected_num_packets) {
+  ASSERT_TRUE(inited_);
+  int send_bytes = 0;
+  bool last;
+  for (int i = 0; i < expected_num_packets; ++i) {
+    std::ostringstream ss;
+    ss << "Checking packet " << i;
+    SCOPED_TRACE(ss.str());
+    EXPECT_EQ(expected_part[i],
+              packetizer->NextPacket(max_size[i], buffer_, &send_bytes, &last));
+    CheckPacket(send_bytes, expected_sizes[i], last,
+                expected_frag_start[i]);
+  }
+}
+
+// Payload descriptor
+//       0 1 2 3 4 5 6 7
+//      +-+-+-+-+-+-+-+-+
+//      |X|R|N|S|PartID | (REQUIRED)
+//      +-+-+-+-+-+-+-+-+
+// X:   |I|L|T|K|  RSV  | (OPTIONAL)
+//      +-+-+-+-+-+-+-+-+
+// I:   |   PictureID   | (OPTIONAL)
+//      +-+-+-+-+-+-+-+-+
+// L:   |   TL0PICIDX   | (OPTIONAL)
+//      +-+-+-+-+-+-+-+-+
+// T/K: | TID | KEYIDX  | (OPTIONAL)
+//      +-+-+-+-+-+-+-+-+
+
+// First octet tests.
+#define EXPECT_BIT_EQ(x, n, a) EXPECT_EQ((((x) >> (n)) & 0x1), a)
+
+#define EXPECT_RSV_ZERO(x) EXPECT_EQ(((x) & 0xE0), 0)
+
+#define EXPECT_BIT_X_EQ(x, a) EXPECT_BIT_EQ(x, 7, a)
+
+#define EXPECT_BIT_N_EQ(x, a) EXPECT_BIT_EQ(x, 5, a)
+
+#define EXPECT_BIT_S_EQ(x, a) EXPECT_BIT_EQ(x, 4, a)
+
+#define EXPECT_PART_ID_EQ(x, a) EXPECT_EQ(((x) & 0x0F), a)
+
+// Extension fields tests
+#define EXPECT_BIT_I_EQ(x, a) EXPECT_BIT_EQ(x, 7, a)
+
+#define EXPECT_BIT_L_EQ(x, a) EXPECT_BIT_EQ(x, 6, a)
+
+#define EXPECT_BIT_T_EQ(x, a) EXPECT_BIT_EQ(x, 5, a)
+
+#define EXPECT_BIT_K_EQ(x, a) EXPECT_BIT_EQ(x, 4, a)
+
+#define EXPECT_TID_EQ(x, a) EXPECT_EQ((((x) & 0xC0) >> 6), a)
+
+#define EXPECT_BIT_Y_EQ(x, a) EXPECT_BIT_EQ(x, 5, a)
+
+#define EXPECT_KEYIDX_EQ(x, a) EXPECT_EQ(((x) & 0x1F), a)
+
+void RtpFormatVp8TestHelper::CheckHeader(bool frag_start) {
+  payload_start_ = 1;
+  EXPECT_BIT_EQ(buffer_[0], 6, 0);  // Check reserved bit.
+
+  if (hdr_info_->pictureId != kNoPictureId ||
+      hdr_info_->temporalIdx != kNoTemporalIdx ||
+      hdr_info_->tl0PicIdx != kNoTl0PicIdx ||
+      hdr_info_->keyIdx != kNoKeyIdx) {
+    EXPECT_BIT_X_EQ(buffer_[0], 1);
+    ++payload_start_;
+    CheckPictureID();
+    CheckTl0PicIdx();
+    CheckTIDAndKeyIdx();
+  } else {
+    EXPECT_BIT_X_EQ(buffer_[0], 0);
+  }
+
+  EXPECT_BIT_N_EQ(buffer_[0], hdr_info_->nonReference);
+  EXPECT_BIT_S_EQ(buffer_[0], frag_start);
+
+  // Check partition index.
+  if (!sloppy_partitioning_) {
+    // The test payload data is constructed such that the payload value is the
+    // same as the partition index.
+    EXPECT_EQ(buffer_[0] & 0x0F, buffer_[payload_start_]);
+  } else {
+    // Partition should be set to 0.
+    EXPECT_EQ(buffer_[0] & 0x0F, 0);
+  }
+}
+
+// Verify that the I bit and the PictureID field are both set in accordance
+// with the information in hdr_info_->pictureId.
+void RtpFormatVp8TestHelper::CheckPictureID() {
+  if (hdr_info_->pictureId != kNoPictureId) {
+    EXPECT_BIT_I_EQ(buffer_[1], 1);
+    if (hdr_info_->pictureId > 0x7F) {
+      EXPECT_BIT_EQ(buffer_[payload_start_], 7, 1);
+      EXPECT_EQ(buffer_[payload_start_] & 0x7F,
+                (hdr_info_->pictureId >> 8) & 0x7F);
+      EXPECT_EQ(buffer_[payload_start_ + 1],
+                hdr_info_->pictureId & 0xFF);
+      payload_start_ += 2;
+    } else {
+      EXPECT_BIT_EQ(buffer_[payload_start_], 7, 0);
+      EXPECT_EQ(buffer_[payload_start_] & 0x7F,
+                (hdr_info_->pictureId) & 0x7F);
+      payload_start_ += 1;
+    }
+  } else {
+    EXPECT_BIT_I_EQ(buffer_[1], 0);
+  }
+}
+
+// Verify that the L bit and the TL0PICIDX field are both set in accordance
+// with the information in hdr_info_->tl0PicIdx.
+void RtpFormatVp8TestHelper::CheckTl0PicIdx() {
+  if (hdr_info_->tl0PicIdx != kNoTl0PicIdx) {
+    EXPECT_BIT_L_EQ(buffer_[1], 1);
+    EXPECT_EQ(buffer_[payload_start_], hdr_info_->tl0PicIdx);
+    ++payload_start_;
+  } else {
+    EXPECT_BIT_L_EQ(buffer_[1], 0);
+  }
+}
+
+// Verify that the T bit and the TL0PICIDX field, and the K bit and KEYIDX
+// field are all set in accordance with the information in
+// hdr_info_->temporalIdx and hdr_info_->keyIdx, respectively.
+void RtpFormatVp8TestHelper::CheckTIDAndKeyIdx() {
+  if (hdr_info_->temporalIdx == kNoTemporalIdx &&
+      hdr_info_->keyIdx == kNoKeyIdx) {
+    EXPECT_BIT_T_EQ(buffer_[1], 0);
+    EXPECT_BIT_K_EQ(buffer_[1], 0);
+    return;
+  }
+  if (hdr_info_->temporalIdx != kNoTemporalIdx) {
+    EXPECT_BIT_T_EQ(buffer_[1], 1);
+    EXPECT_TID_EQ(buffer_[payload_start_], hdr_info_->temporalIdx);
+    EXPECT_BIT_Y_EQ(buffer_[payload_start_], hdr_info_->layerSync);
+  } else {
+    EXPECT_BIT_T_EQ(buffer_[1], 0);
+    EXPECT_TID_EQ(buffer_[payload_start_], 0);
+    EXPECT_BIT_Y_EQ(buffer_[payload_start_], false);
+  }
+  if (hdr_info_->keyIdx != kNoKeyIdx) {
+    EXPECT_BIT_K_EQ(buffer_[1], 1);
+    EXPECT_KEYIDX_EQ(buffer_[payload_start_], hdr_info_->keyIdx);
+  } else {
+    EXPECT_BIT_K_EQ(buffer_[1], 0);
+    EXPECT_KEYIDX_EQ(buffer_[payload_start_], 0);
+  }
+  ++payload_start_;
+}
+
+// Verify that the payload (i.e., after the headers) of the packet stored in
+// buffer_ is identical to the expected (as found in data_ptr_).
+void RtpFormatVp8TestHelper::CheckPayload(int payload_end) {
+  for (int i = payload_start_; i < payload_end; ++i, ++data_ptr_)
+    EXPECT_EQ(buffer_[i], *data_ptr_);
+}
+
+// Verify that the input variable "last" agrees with the position of data_ptr_.
+// If data_ptr_ has advanced payload_size_ bytes from the start (payload_data_)
+// we are at the end and last should be true. Otherwise, it should be false.
+void RtpFormatVp8TestHelper::CheckLast(bool last) const {
+  EXPECT_EQ(last, data_ptr_ == payload_data_ + payload_size_);
+}
+
+// Verify the contents of a packet. Check the length versus expected_bytes,
+// the header, payload, and "last" flag.
+void RtpFormatVp8TestHelper::CheckPacket(int send_bytes,
+                                         int expect_bytes,
+                                         bool last,
+                                         bool frag_start) {
+  EXPECT_EQ(send_bytes, expect_bytes);
+  CheckHeader(frag_start);
+  CheckPayload(send_bytes);
+  CheckLast(last);
+}
+
+}  // namespace test
+
+}  // namespace webrtc
diff --git a/src/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h b/src/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h
new file mode 100644
index 0000000..8e8fad1
--- /dev/null
+++ b/src/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h
@@ -0,0 +1,76 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+// This file contains the class RtpFormatVp8TestHelper. The class is
+// responsible for setting up a fake VP8 bitstream according to the
+// RTPVideoHeaderVP8 header, and partition information. After initialization,
+// an RTPFragmentationHeader is provided so that the tester can create a
+// packetizer. The packetizer can then be provided to this helper class, which
+// will then extract all packets and compare to the expected outcome.
+
+#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_TEST_HELPER_H_
+#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_TEST_HELPER_H_
+
+#include "modules/interface/module_common_types.h"
+#include "modules/rtp_rtcp/source/rtp_format_vp8.h"
+#include "system_wrappers/interface/constructor_magic.h"
+#include "typedefs.h"
+
+namespace webrtc {
+
+namespace test {
+
+class RtpFormatVp8TestHelper {
+ public:
+  explicit RtpFormatVp8TestHelper(const RTPVideoHeaderVP8* hdr);
+  ~RtpFormatVp8TestHelper();
+  bool Init(const int* partition_sizes, int num_partitions);
+  void GetAllPacketsAndCheck(RtpFormatVp8* packetizer,
+                             const int* expected_sizes,
+                             const int* expected_part,
+                             const bool* expected_frag_start,
+                             const int* max_size,
+                             int expected_num_packets);
+
+  uint8_t* payload_data() const { return payload_data_; }
+  int payload_size() const { return payload_size_; }
+  RTPFragmentationHeader* fragmentation() const { return fragmentation_; }
+  int buffer_size() const { return buffer_size_; }
+  void set_sloppy_partitioning(bool value) { sloppy_partitioning_ = value; }
+
+ private:
+  void CheckHeader(bool frag_start);
+  void CheckPictureID();
+  void CheckTl0PicIdx();
+  void CheckTIDAndKeyIdx();
+  void CheckPayload(int payload_end);
+  void CheckLast(bool last) const;
+  void CheckPacket(int send_bytes, int expect_bytes, bool last,
+                   bool frag_start);
+
+  uint8_t* payload_data_;
+  uint8_t* buffer_;
+  uint8_t* data_ptr_;
+  RTPFragmentationHeader* fragmentation_;
+  const RTPVideoHeaderVP8* hdr_info_;
+  int payload_start_;
+  int payload_size_;
+  int buffer_size_;
+  bool sloppy_partitioning_;
+  bool inited_;
+
+  DISALLOW_COPY_AND_ASSIGN(RtpFormatVp8TestHelper);
+};
+
+}  // namespace test
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_TEST_HELPER_H_
diff --git a/src/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc b/src/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc
index b2e0cf1..f2c028c 100644
--- a/src/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc
+++ b/src/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc
@@ -16,457 +16,286 @@
 #include <gtest/gtest.h>
 
 #include "modules/rtp_rtcp/source/rtp_format_vp8.h"
-#include "typedefs.h"  // NOLINT(build/include)
+#include "modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h"
+#include "typedefs.h"
 
 namespace webrtc {
 
-const int kPayloadSize = 30;
-const int kBufferSize = kPayloadSize + 6;  // Add space for payload descriptor.
+template <bool>
+struct CompileAssert {
+};
+
+#undef COMPILE_ASSERT
+#define COMPILE_ASSERT(expr, msg) \
+  typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
 
 class RtpFormatVp8Test : public ::testing::Test {
  protected:
-  RtpFormatVp8Test() {}
-  virtual void SetUp();
-  virtual void TearDown();
-  void CheckHeader(bool first_in_frame, bool frag_start, int part_id);
-  void CheckPictureID();
-  void CheckTl0PicIdx();
-  void CheckTIDAndKeyIdx();
-  void CheckPayload(int payload_end);
-  void CheckLast(bool last) const;
-  void CheckPacket(int send_bytes, int expect_bytes, bool last,
-                   bool first_in_frame, bool frag_start);
-  void CheckPacketZeroPartId(int send_bytes, int expect_bytes, bool last,
-                             bool first_in_frame, bool frag_start);
-  WebRtc_UWord8 payload_data_[kPayloadSize];
-  WebRtc_UWord8 buffer_[kBufferSize];
-  WebRtc_UWord8 *data_ptr_;
-  RTPFragmentationHeader* fragmentation_;
+  RtpFormatVp8Test() : helper_(NULL) {}
+  virtual void TearDown() { delete helper_; }
+  bool Init() {
+    const int kSizeVector[] = {10, 10, 10};
+    const int kNumPartitions = sizeof(kSizeVector) / sizeof(kSizeVector[0]);
+    return Init(kSizeVector, kNumPartitions);
+  }
+  bool Init(const int* partition_sizes, int num_partitions) {
+    hdr_info_.pictureId = kNoPictureId;
+    hdr_info_.nonReference = false;
+    hdr_info_.temporalIdx = kNoTemporalIdx;
+    hdr_info_.layerSync = false;
+    hdr_info_.tl0PicIdx = kNoTl0PicIdx;
+    hdr_info_.keyIdx = kNoKeyIdx;
+    if (helper_ != NULL) return false;
+    helper_ = new test::RtpFormatVp8TestHelper(&hdr_info_);
+    return helper_->Init(partition_sizes, num_partitions);
+  }
+
   RTPVideoHeaderVP8 hdr_info_;
-  int payload_start_;
+  test::RtpFormatVp8TestHelper* helper_;
 };
 
-void RtpFormatVp8Test::SetUp() {
-  for (int i = 0; i < kPayloadSize; i++) {
-    payload_data_[i] = i / 10;  // Integer division.
-  }
-  data_ptr_ = payload_data_;
-
-  fragmentation_ = new RTPFragmentationHeader;
-  fragmentation_->VerifyAndAllocateFragmentationHeader(3);
-  fragmentation_->fragmentationLength[0] = 10;
-  fragmentation_->fragmentationLength[1] = 10;
-  fragmentation_->fragmentationLength[2] = 10;
-  fragmentation_->fragmentationOffset[0] = 0;
-  fragmentation_->fragmentationOffset[1] = 10;
-  fragmentation_->fragmentationOffset[2] = 20;
-
-  hdr_info_.pictureId = kNoPictureId;
-  hdr_info_.nonReference = false;
-  hdr_info_.temporalIdx = kNoTemporalIdx;
-  hdr_info_.layerSync = false;
-  hdr_info_.tl0PicIdx = kNoTl0PicIdx;
-  hdr_info_.keyIdx = kNoKeyIdx;
-}
-
-void RtpFormatVp8Test::TearDown() {
-  delete fragmentation_;
-}
-
-// First octet tests.
-#define EXPECT_BIT_EQ(x, n, a) EXPECT_EQ((((x) >> (n)) & 0x1), a)
-
-#define EXPECT_RSV_ZERO(x) EXPECT_EQ(((x) & 0xE0), 0)
-
-#define EXPECT_BIT_X_EQ(x, a) EXPECT_BIT_EQ(x, 7, a)
-
-#define EXPECT_BIT_N_EQ(x, a) EXPECT_BIT_EQ(x, 5, a)
-
-#define EXPECT_BIT_S_EQ(x, a) EXPECT_BIT_EQ(x, 4, a)
-
-#define EXPECT_PART_ID_EQ(x, a) EXPECT_EQ(((x) & 0x0F), a)
-
-// Extension fields tests
-#define EXPECT_BIT_I_EQ(x, a) EXPECT_BIT_EQ(x, 7, a)
-
-#define EXPECT_BIT_L_EQ(x, a) EXPECT_BIT_EQ(x, 6, a)
-
-#define EXPECT_BIT_T_EQ(x, a) EXPECT_BIT_EQ(x, 5, a)
-
-#define EXPECT_BIT_K_EQ(x, a) EXPECT_BIT_EQ(x, 4, a)
-
-#define EXPECT_TID_EQ(x, a) EXPECT_EQ((((x) & 0xC0) >> 6), a)
-
-#define EXPECT_BIT_Y_EQ(x, a) EXPECT_BIT_EQ(x, 5, a)
-
-#define EXPECT_KEYIDX_EQ(x, a) EXPECT_EQ(((x) & 0x1F), a)
-
-void RtpFormatVp8Test::CheckHeader(bool first_in_frame, bool frag_start,
-                                   int part_id) {
-  payload_start_ = 1;
-  EXPECT_BIT_EQ(buffer_[0], 6, 0);  // Check reserved bit.
-
-
-  if (hdr_info_.pictureId != kNoPictureId ||
-      hdr_info_.temporalIdx != kNoTemporalIdx ||
-      hdr_info_.tl0PicIdx != kNoTl0PicIdx ||
-      hdr_info_.keyIdx != kNoKeyIdx) {
-    EXPECT_BIT_X_EQ(buffer_[0], 1);
-    ++payload_start_;
-    CheckPictureID();
-    CheckTl0PicIdx();
-    CheckTIDAndKeyIdx();
-  } else {
-    EXPECT_BIT_X_EQ(buffer_[0], 0);
-  }
-
-  EXPECT_BIT_N_EQ(buffer_[0], 0);
-  EXPECT_BIT_S_EQ(buffer_[0], frag_start);
-
-  // Check partition index.
-  if (part_id < 0) {
-    // (Payload data is the same as the partition index.)
-    EXPECT_EQ(buffer_[0] & 0x0F, buffer_[payload_start_]);
-  } else {
-    EXPECT_EQ(buffer_[0] & 0x0F, part_id);
-  }
-}
-
-void RtpFormatVp8Test::CheckPictureID() {
-  if (hdr_info_.pictureId != kNoPictureId) {
-    EXPECT_BIT_I_EQ(buffer_[1], 1);
-    if (hdr_info_.pictureId > 0x7F) {
-      EXPECT_BIT_EQ(buffer_[payload_start_], 7, 1);
-      EXPECT_EQ(buffer_[payload_start_] & 0x7F,
-                (hdr_info_.pictureId >> 8) & 0x7F);
-      EXPECT_EQ(buffer_[payload_start_ + 1],
-                hdr_info_.pictureId & 0xFF);
-      payload_start_ += 2;
-    } else {
-      EXPECT_BIT_EQ(buffer_[payload_start_], 7, 0);
-      EXPECT_EQ(buffer_[payload_start_] & 0x7F,
-                (hdr_info_.pictureId) & 0x7F);
-      payload_start_ += 1;
-    }
-  } else {
-    EXPECT_BIT_I_EQ(buffer_[1], 0);
-  }
-}
-
-void RtpFormatVp8Test::CheckTl0PicIdx() {
-  if (hdr_info_.tl0PicIdx != kNoTl0PicIdx) {
-    EXPECT_BIT_L_EQ(buffer_[1], 1);
-    EXPECT_EQ(buffer_[payload_start_], hdr_info_.tl0PicIdx);
-    ++payload_start_;
-  } else {
-    EXPECT_BIT_L_EQ(buffer_[1], 0);
-  }
-}
-
-void RtpFormatVp8Test::CheckTIDAndKeyIdx() {
-  if (hdr_info_.temporalIdx == kNoTemporalIdx &&
-      hdr_info_.keyIdx == kNoKeyIdx) {
-    EXPECT_BIT_T_EQ(buffer_[1], 0);
-    EXPECT_BIT_K_EQ(buffer_[1], 0);
-    return;
-  }
-  if (hdr_info_.temporalIdx != kNoTemporalIdx) {
-    EXPECT_BIT_T_EQ(buffer_[1], 1);
-    EXPECT_TID_EQ(buffer_[payload_start_], hdr_info_.temporalIdx);
-    EXPECT_BIT_Y_EQ(buffer_[payload_start_], hdr_info_.layerSync);
-  } else {
-    EXPECT_BIT_T_EQ(buffer_[1], 0);
-    EXPECT_TID_EQ(buffer_[payload_start_], 0);
-    EXPECT_BIT_Y_EQ(buffer_[payload_start_], false);
-  }
-  if (hdr_info_.keyIdx != kNoKeyIdx) {
-    EXPECT_BIT_K_EQ(buffer_[1], 1);
-    EXPECT_KEYIDX_EQ(buffer_[payload_start_], hdr_info_.keyIdx);
-  } else {
-    EXPECT_BIT_K_EQ(buffer_[1], 0);
-    EXPECT_KEYIDX_EQ(buffer_[payload_start_], 0);
-  }
-  ++payload_start_;
-}
-
-void RtpFormatVp8Test::CheckPayload(int payload_end) {
-  for (int i = payload_start_; i < payload_end; i++, data_ptr_++)
-    EXPECT_EQ(buffer_[i], *data_ptr_);
-}
-
-void RtpFormatVp8Test::CheckLast(bool last) const {
-  EXPECT_EQ(last, data_ptr_ == payload_data_ + kPayloadSize);
-}
-
-void RtpFormatVp8Test::CheckPacket(int send_bytes, int expect_bytes, bool last,
-                                   bool first_in_frame, bool frag_start) {
-  EXPECT_EQ(send_bytes, expect_bytes);
-  CheckHeader(first_in_frame, frag_start, -1);
-  CheckPayload(send_bytes);
-  CheckLast(last);
-}
-
-void RtpFormatVp8Test::CheckPacketZeroPartId(int send_bytes,
-                                             int expect_bytes,
-                                             bool last,
-                                             bool first_in_frame,
-                                             bool frag_start) {
-  EXPECT_EQ(send_bytes, expect_bytes);
-  CheckHeader(first_in_frame, frag_start, 0);
-  CheckPayload(send_bytes);
-  CheckLast(last);
-}
-
 TEST_F(RtpFormatVp8Test, TestStrictMode) {
-  int send_bytes = 0;
-  bool last;
-  bool first_in_frame = true;
+  ASSERT_TRUE(Init());
 
   hdr_info_.pictureId = 200;  // > 0x7F should produce 2-byte PictureID.
-  RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize,
-                                         hdr_info_, *fragmentation_, kStrict);
+  RtpFormatVp8 packetizer = RtpFormatVp8(helper_->payload_data(),
+                                         helper_->payload_size(),
+                                         hdr_info_,
+                                         *(helper_->fragmentation()),
+                                         kStrict);
 
-  // Get first packet, expect balanced size ~= same as second packet.
-  EXPECT_EQ(0, packetizer.NextPacket(13, buffer_, &send_bytes, &last));
-  CheckPacket(send_bytes, 8, last,
-              first_in_frame,
-              /* frag_start */ true);
-  first_in_frame = false;
+  // The expected sizes are obtained by running a verified good implementation.
+  const int kExpectedSizes[] = {8, 10, 14, 5, 5, 7, 5};
+  const int kExpectedPart[] = {0, 0, 1, 2, 2, 2, 2};
+  const bool kExpectedFragStart[] =
+      {true, false, true, true, false, false, false};
+  const int kMaxSize[] = {13, 13, 20, 7, 7, 7, 7};
+  const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]);
+  COMPILE_ASSERT(kExpectedNum ==
+      sizeof(kExpectedPart) / sizeof(kExpectedPart[0]),
+      kExpectedPart_wrong_size);
+  COMPILE_ASSERT(kExpectedNum ==
+      sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0]),
+      kExpectedFragStart_wrong_size);
+  COMPILE_ASSERT(kExpectedNum == sizeof(kMaxSize) / sizeof(kMaxSize[0]),
+                 kMaxSize_wrong_size);
 
-  // Get second packet.
-  EXPECT_EQ(0, packetizer.NextPacket(13, buffer_, &send_bytes, &last));
-  CheckPacket(send_bytes, 10, last,
-              first_in_frame,
-              /* frag_start */ false);
-
-  // Second partition.
-  // Get first (and only) packet.
-  EXPECT_EQ(1, packetizer.NextPacket(20, buffer_, &send_bytes, &last));
-  CheckPacket(send_bytes, 14, last,
-              first_in_frame,
-              /* frag_start */ true);
-
-  // Third partition.
-  // Get first packet (of four).
-  EXPECT_EQ(2, packetizer.NextPacket(7, buffer_, &send_bytes, &last));
-  CheckPacket(send_bytes, 5, last,
-              first_in_frame,
-              /* frag_start */ true);
-
-  // Get second packet (of four).
-  EXPECT_EQ(2, packetizer.NextPacket(7, buffer_, &send_bytes, &last));
-  CheckPacket(send_bytes, 5, last,
-              first_in_frame,
-              /* frag_start */ false);
-
-  // Get third packet (of four).
-  EXPECT_EQ(2, packetizer.NextPacket(7, buffer_, &send_bytes, &last));
-  CheckPacket(send_bytes, 7, last,
-              first_in_frame,
-              /* frag_start */ false);
-
-  // Get fourth and last packet.
-  EXPECT_EQ(2, packetizer.NextPacket(7, buffer_, &send_bytes, &last));
-  CheckPacket(send_bytes, 5, last,
-              first_in_frame,
-              /* frag_start */ false);
+  helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart,
+                                 kExpectedFragStart, kMaxSize, kExpectedNum);
 }
 
 TEST_F(RtpFormatVp8Test, TestAggregateMode) {
-  int send_bytes = 0;
-  bool last;
-  bool first_in_frame = true;
+  ASSERT_TRUE(Init());
 
   hdr_info_.pictureId = 20;  // <= 0x7F should produce 1-byte PictureID.
-  RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize,
-                                         hdr_info_, *fragmentation_,
+  RtpFormatVp8 packetizer = RtpFormatVp8(helper_->payload_data(),
+                                         helper_->payload_size(),
+                                         hdr_info_,
+                                         *(helper_->fragmentation()),
                                          kAggregate);
 
-  // Get first packet.
-  // First part of first partition (balanced fragments are expected).
-  EXPECT_EQ(0, packetizer.NextPacket(8, buffer_, &send_bytes, &last));
-  CheckPacket(send_bytes, 7, last,
-              first_in_frame,
-              /* frag_start */ true);
-  first_in_frame = false;
+  // The expected sizes are obtained by running a verified good implementation.
+  const int kExpectedSizes[] = {7, 5, 7, 23};
+  const int kExpectedPart[] = {0, 0, 0, 1};
+  const bool kExpectedFragStart[] = {true, false, false, true};
+  const int kMaxSize[] = {8, 8, 8, 25};
+  const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]);
+  COMPILE_ASSERT(kExpectedNum ==
+      sizeof(kExpectedPart) / sizeof(kExpectedPart[0]),
+      kExpectedPart_wrong_size);
+  COMPILE_ASSERT(kExpectedNum ==
+      sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0]),
+      kExpectedFragStart_wrong_size);
+  COMPILE_ASSERT(kExpectedNum == sizeof(kMaxSize) / sizeof(kMaxSize[0]),
+                 kMaxSize_wrong_size);
 
-  // Get second packet.
-  // Second fragment of first partition.
-  EXPECT_EQ(0, packetizer.NextPacket(8, buffer_, &send_bytes, &last));
-  CheckPacket(send_bytes, 5, last,
-              first_in_frame,
-              /* frag_start */ false);
-
-  // Get third packet.
-  // Third fragment of first partition.
-  EXPECT_EQ(0, packetizer.NextPacket(8, buffer_, &send_bytes, &last));
-  CheckPacket(send_bytes, 7, last,
-              first_in_frame,
-              /* frag_start */ false);
-
-  // Get fourth packet.
-  // Last two partitions aggregated.
-  EXPECT_EQ(1, packetizer.NextPacket(25, buffer_, &send_bytes, &last));
-  CheckPacket(send_bytes, 23, last,
-              first_in_frame,
-              /* frag_start */ true);
+  helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart,
+                                 kExpectedFragStart, kMaxSize, kExpectedNum);
 }
 
 TEST_F(RtpFormatVp8Test, TestSloppyMode) {
-  int send_bytes = 0;
-  bool last;
-  bool first_in_frame = true;
+  ASSERT_TRUE(Init());
 
   hdr_info_.pictureId = kNoPictureId;  // No PictureID.
-  RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize,
-                                         hdr_info_, *fragmentation_, kSloppy);
+  RtpFormatVp8 packetizer = RtpFormatVp8(helper_->payload_data(),
+                                         helper_->payload_size(),
+                                         hdr_info_,
+                                         *(helper_->fragmentation()),
+                                         kSloppy);
 
-  // Get first packet.
-  EXPECT_EQ(0, packetizer.NextPacket(9, buffer_, &send_bytes, &last));
-  CheckPacket(send_bytes, 9, last,
-              first_in_frame,
-              /* frag_start */ true);
-  first_in_frame = false;
+  // The expected sizes are obtained by running a verified good implementation.
+  const int kExpectedSizes[] = {9, 9, 9, 7};
+  const int kExpectedPart[] = {0, 0, 1, 2};
+  const bool kExpectedFragStart[] = {true, false, false, false};
+  const int kMaxSize[] = {9, 9, 9, 9};
+  const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]);
+  COMPILE_ASSERT(kExpectedNum ==
+      sizeof(kExpectedPart) / sizeof(kExpectedPart[0]),
+      kExpectedPart_wrong_size);
+  COMPILE_ASSERT(kExpectedNum ==
+      sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0]),
+      kExpectedFragStart_wrong_size);
+  COMPILE_ASSERT(kExpectedNum == sizeof(kMaxSize) / sizeof(kMaxSize[0]),
+                 kMaxSize_wrong_size);
 
-  // Get second packet.
-  // Fragments of first and second partitions.
-  EXPECT_EQ(0, packetizer.NextPacket(9, buffer_, &send_bytes, &last));
-  CheckPacket(send_bytes, 9, last,
-              first_in_frame,
-              /* frag_start */ false);
-
-  // Get third packet.
-  // Fragments of second and third partitions.
-  EXPECT_EQ(1, packetizer.NextPacket(9, buffer_, &send_bytes, &last));
-  CheckPacket(send_bytes, 9, last,
-              first_in_frame,
-              /* frag_start */ false);
-
-  // Get fourth packet.
-  // Second half of last partition.
-  EXPECT_EQ(2, packetizer.NextPacket(9, buffer_, &send_bytes, &last));
-  CheckPacket(send_bytes, 7, last,
-              first_in_frame,
-              /* frag_start */ false);
+  helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart,
+                                 kExpectedFragStart, kMaxSize, kExpectedNum);
 }
 
 // Verify that sloppy mode is forced if fragmentation info is missing.
 TEST_F(RtpFormatVp8Test, TestSloppyModeFallback) {
-  int send_bytes = 0;
-  bool last;
-  bool first_in_frame = true;
+  ASSERT_TRUE(Init());
 
   hdr_info_.pictureId = 200;  // > 0x7F should produce 2-byte PictureID
-  RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize,
+  RtpFormatVp8 packetizer = RtpFormatVp8(helper_->payload_data(),
+                                         helper_->payload_size(),
                                          hdr_info_);
 
-  // Get first packet.
-  EXPECT_EQ(0, packetizer.NextPacket(10, buffer_, &send_bytes, &last));
-  CheckPacketZeroPartId(send_bytes, 10, last,
-                        first_in_frame,
-                        /* frag_start */ true);
-  first_in_frame = false;
+  // Expecting three full packets, and one with the remainder.
+  const int kExpectedSizes[] = {10, 10, 10, 7};
+  const int kExpectedPart[] = {0, 0, 0, 0};  // Always 0 for sloppy mode.
+  // Frag start only true for first packet in sloppy mode.
+  const bool kExpectedFragStart[] = {true, false, false, false};
+  const int kMaxSize[] = {10, 10, 10, 7};  // Small enough to produce 4 packets.
+  const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]);
+  COMPILE_ASSERT(kExpectedNum ==
+      sizeof(kExpectedPart) / sizeof(kExpectedPart[0]),
+      kExpectedPart_wrong_size);
+  COMPILE_ASSERT(kExpectedNum ==
+      sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0]),
+      kExpectedFragStart_wrong_size);
+  COMPILE_ASSERT(kExpectedNum == sizeof(kMaxSize) / sizeof(kMaxSize[0]),
+                 kMaxSize_wrong_size);
 
-  // Get second packet.
-  // Fragments of first and second partitions.
-  EXPECT_EQ(0, packetizer.NextPacket(10, buffer_, &send_bytes, &last));
-  CheckPacketZeroPartId(send_bytes, 10, last,
-                        first_in_frame,
-                        /* frag_start */ false);
-
-  // Get third packet.
-  // Fragments of second and third partitions.
-  EXPECT_EQ(0, packetizer.NextPacket(10, buffer_, &send_bytes, &last));
-  CheckPacketZeroPartId(send_bytes, 10, last,
-                        first_in_frame,
-                        /* frag_start */ false);
-
-  // Get fourth packet.
-  // Second half of last partition.
-  EXPECT_EQ(0, packetizer.NextPacket(7, buffer_, &send_bytes, &last));
-  CheckPacketZeroPartId(send_bytes, 7, last,
-                        first_in_frame,
-                        /* frag_start */ false);
+  helper_->set_sloppy_partitioning(true);
+  helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart,
+                                 kExpectedFragStart, kMaxSize, kExpectedNum);
 }
 
-// Verify that non-reference bit is set.
+// Verify that non-reference bit is set. Sloppy mode fallback is expected.
 TEST_F(RtpFormatVp8Test, TestNonReferenceBit) {
-  int send_bytes = 0;
-  bool last;
+  ASSERT_TRUE(Init());
 
   hdr_info_.nonReference = true;
-  RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize,
+  RtpFormatVp8 packetizer = RtpFormatVp8(helper_->payload_data(),
+                                         helper_->payload_size(),
                                          hdr_info_);
 
-  // Get first packet.
-  ASSERT_EQ(0, packetizer.NextPacket(25, buffer_, &send_bytes, &last));
-  ASSERT_FALSE(last);
-  EXPECT_BIT_N_EQ(buffer_[0], 1);
+  // Sloppy mode => First packet full; other not.
+  const int kExpectedSizes[] = {25, 7};
+  const int kExpectedPart[] = {0, 0};  // Always 0 for sloppy mode.
+  // Frag start only true for first packet in sloppy mode.
+  const bool kExpectedFragStart[] = {true, false};
+  const int kMaxSize[] = {25, 25};  // Small enough to produce two packets.
+  const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]);
+  COMPILE_ASSERT(kExpectedNum ==
+      sizeof(kExpectedPart) / sizeof(kExpectedPart[0]),
+      kExpectedPart_wrong_size);
+  COMPILE_ASSERT(kExpectedNum ==
+      sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0]),
+      kExpectedFragStart_wrong_size);
+  COMPILE_ASSERT(kExpectedNum == sizeof(kMaxSize) / sizeof(kMaxSize[0]),
+                 kMaxSize_wrong_size);
 
-  // Get second packet.
-  ASSERT_EQ(0, packetizer.NextPacket(25, buffer_, &send_bytes, &last));
-  ASSERT_TRUE(last);
-  EXPECT_BIT_N_EQ(buffer_[0], 1);
+  helper_->set_sloppy_partitioning(true);
+  helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart,
+                                 kExpectedFragStart, kMaxSize, kExpectedNum);
 }
 
 // Verify Tl0PicIdx and TID fields, and layerSync bit.
 TEST_F(RtpFormatVp8Test, TestTl0PicIdxAndTID) {
-  int send_bytes = 0;
-  bool last;
+  ASSERT_TRUE(Init());
 
   hdr_info_.tl0PicIdx = 117;
   hdr_info_.temporalIdx = 2;
   hdr_info_.layerSync = true;
-  RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize,
-                                         hdr_info_, *fragmentation_,
+  RtpFormatVp8 packetizer = RtpFormatVp8(helper_->payload_data(),
+                                         helper_->payload_size(),
+                                         hdr_info_,
+                                         *(helper_->fragmentation()),
                                          kAggregate);
 
-  // Get first and only packet.
-  EXPECT_EQ(0, packetizer.NextPacket(kBufferSize, buffer_, &send_bytes,
-                                     &last));
-  bool first_in_frame = true;
-  CheckPacket(send_bytes, kPayloadSize + 4, last,
-              first_in_frame,
-              /* frag_start */ true);
+  // Expect one single packet of payload_size() + 4 bytes header.
+  const int kExpectedSizes[1] = {helper_->payload_size() + 4};
+  const int kExpectedPart[1] = {0};  // Packet starts with partition 0.
+  const bool kExpectedFragStart[1] = {true};
+  // kMaxSize is only limited by allocated buffer size.
+  const int kMaxSize[1] = {helper_->buffer_size()};
+  const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]);
+  COMPILE_ASSERT(kExpectedNum ==
+      sizeof(kExpectedPart) / sizeof(kExpectedPart[0]),
+      kExpectedPart_wrong_size);
+  COMPILE_ASSERT(kExpectedNum ==
+      sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0]),
+      kExpectedFragStart_wrong_size);
+  COMPILE_ASSERT(kExpectedNum == sizeof(kMaxSize) / sizeof(kMaxSize[0]),
+                 kMaxSize_wrong_size);
+
+  helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart,
+                                 kExpectedFragStart, kMaxSize, kExpectedNum);
 }
 
 // Verify KeyIdx field.
 TEST_F(RtpFormatVp8Test, TestKeyIdx) {
-  int send_bytes = 0;
-  bool last;
+  ASSERT_TRUE(Init());
 
   hdr_info_.keyIdx = 17;
-  RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize,
-                                         hdr_info_, *fragmentation_,
+  RtpFormatVp8 packetizer = RtpFormatVp8(helper_->payload_data(),
+                                         helper_->payload_size(),
+                                         hdr_info_,
+                                         *(helper_->fragmentation()),
                                          kAggregate);
 
-  // Get first and only packet.
-  EXPECT_EQ(0, packetizer.NextPacket(kBufferSize, buffer_, &send_bytes,
-                                     &last));
-  bool first_in_frame = true;
-  CheckPacket(send_bytes, kPayloadSize + 3, last,
-              first_in_frame,
-              /* frag_start */ true);
+  // Expect one single packet of payload_size() + 3 bytes header.
+  const int kExpectedSizes[1] = {helper_->payload_size() + 3};
+  const int kExpectedPart[1] = {0};  // Packet starts with partition 0.
+  const bool kExpectedFragStart[1] = {true};
+  // kMaxSize is only limited by allocated buffer size.
+  const int kMaxSize[1] = {helper_->buffer_size()};
+  const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]);
+  COMPILE_ASSERT(kExpectedNum ==
+      sizeof(kExpectedPart) / sizeof(kExpectedPart[0]),
+      kExpectedPart_wrong_size);
+  COMPILE_ASSERT(kExpectedNum ==
+      sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0]),
+      kExpectedFragStart_wrong_size);
+  COMPILE_ASSERT(kExpectedNum == sizeof(kMaxSize) / sizeof(kMaxSize[0]),
+                 kMaxSize_wrong_size);
+
+  helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart,
+                                 kExpectedFragStart, kMaxSize, kExpectedNum);
 }
 
 // Verify TID field and KeyIdx field in combination.
 TEST_F(RtpFormatVp8Test, TestTIDAndKeyIdx) {
-  int send_bytes = 0;
-  bool last;
+  ASSERT_TRUE(Init());
 
   hdr_info_.temporalIdx = 1;
   hdr_info_.keyIdx = 5;
-  RtpFormatVp8 packetizer = RtpFormatVp8(payload_data_, kPayloadSize,
-                                         hdr_info_, *fragmentation_,
+  RtpFormatVp8 packetizer = RtpFormatVp8(helper_->payload_data(),
+                                         helper_->payload_size(),
+                                         hdr_info_,
+                                         *(helper_->fragmentation()),
                                          kAggregate);
 
-  // Get first and only packet.
-  EXPECT_EQ(0, packetizer.NextPacket(kBufferSize, buffer_, &send_bytes,
-                                     &last));
-  bool first_in_frame = true;
-  CheckPacket(send_bytes, kPayloadSize + 3, last,
-              first_in_frame,
-              /* frag_start */ true);
+  // Expect one single packet of payload_size() + 3 bytes header.
+  const int kExpectedSizes[1] = {helper_->payload_size() + 3};
+  const int kExpectedPart[1] = {0};  // Packet starts with partition 0.
+  const bool kExpectedFragStart[1] = {true};
+  // kMaxSize is only limited by allocated buffer size.
+  const int kMaxSize[1] = {helper_->buffer_size()};
+  const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]);
+  COMPILE_ASSERT(kExpectedNum ==
+      sizeof(kExpectedPart) / sizeof(kExpectedPart[0]),
+      kExpectedPart_wrong_size);
+  COMPILE_ASSERT(kExpectedNum ==
+      sizeof(kExpectedFragStart) / sizeof(kExpectedFragStart[0]),
+      kExpectedFragStart_wrong_size);
+  COMPILE_ASSERT(kExpectedNum == sizeof(kMaxSize) / sizeof(kMaxSize[0]),
+                 kMaxSize_wrong_size);
+
+  helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart,
+                                 kExpectedFragStart, kMaxSize, kExpectedNum);
 }
 
 }  // namespace
diff --git a/src/modules/rtp_rtcp/source/rtp_rtcp_tests.gypi b/src/modules/rtp_rtcp/source/rtp_rtcp_tests.gypi
index ec11396..8619f6c 100644
--- a/src/modules/rtp_rtcp/source/rtp_rtcp_tests.gypi
+++ b/src/modules/rtp_rtcp/source/rtp_rtcp_tests.gypi
@@ -22,6 +22,8 @@
       ],
       'sources': [
         'rtp_format_vp8_unittest.cc',
+        'rtp_format_vp8_test_helper.cc',
+        'rtp_format_vp8_test_helper.h',
         'rtcp_format_remb_unittest.cc',
         'rtp_utility_test.cc',
         'rtp_header_extension_test.cc',