TableIndirectWS() 
    : testHeaderType("test_t", 0), action_fn("actionA", 0) {
    testHeaderType.push_back_field("f16", 16);
    testHeaderType.push_back_field("f48", 48);
    phv_factory.push_back_header("test1", testHeader1, testHeaderType);
    phv_factory.push_back_header("test2", testHeader2, testHeaderType);

    key_builder.push_back_field(testHeader1, 0, 16);

    // with counters, without ageing
    table = MatchTableIndirectWS::create("exact", "test_table", 0,
					 table_size, key_builder,
					 true, false);
    table->set_next_node(0, nullptr);

    BufBuilder builder;
    
    builder.push_back_field(testHeader1, 1, 48); // h1.f48
    builder.push_back_field(testHeader2, 0, 16); // h2.f16
    builder.push_back_field(testHeader2, 1, 48); // h2.f48

    std::unique_ptr<Calculation<hash_t> > calc(new Calculation<hash_t>(builder));
    calc->set_compute_fn(hash::xxh64<hash_t>);

    table->set_hash(std::move(calc));
  }
TEST_F(CalculationTest, WithConstant) {
  BufBuilder builder;

  ByteContainer constant("0x12ab");

  builder.push_back_field(testHeader1, 0); // f16
  builder.push_back_field(testHeader1, 1); // f48
  builder.push_back_constant(constant, 16);
  builder.push_back_field(testHeader1, 3); // f32_2

  Calculation calc(builder, "xxh64");

  unsigned char pkt_buf[2 * header_size];

  for(size_t i = 0; i < sizeof(pkt_buf); i++) {
    pkt_buf[i] = dis(gen);
  }

  Packet pkt = get_pkt((const char *) pkt_buf, sizeof(pkt_buf));
  parser.parse(&pkt);

  /* A bit primitive, I have to  build the buffer myself */
  unsigned char expected_buf[14];
  std::copy(&pkt_buf[0], &pkt_buf[2], &expected_buf[0]);
  std::copy(&pkt_buf[2], &pkt_buf[8], &expected_buf[2]);
  std::copy(constant.begin(), constant.end(), &expected_buf[8]);
  std::copy(&pkt_buf[12], &pkt_buf[16], &expected_buf[10]);

  auto expected = hash::xxh64((const char *) expected_buf, sizeof(expected_buf));
  auto actual = calc.output(pkt);

  ASSERT_EQ(expected, actual);
}
TEST_F(CalculationTest, SimpleTest) {
  BufBuilder builder;

  builder.push_back_field(testHeader1, 0); // f16
  builder.push_back_field(testHeader1, 1); // f48
  builder.push_back_field(testHeader1, 3); // f32_2

  builder.push_back_field(testHeader2, 2); // f32_1

  Calculation calc(builder, "xxh64");

  unsigned char pkt_buf[2 * header_size];

  for(size_t i = 0; i < sizeof(pkt_buf); i++) {
    pkt_buf[i] = dis(gen);
  }

  Packet pkt = get_pkt((const char *) pkt_buf, sizeof(pkt_buf));
  parser.parse(&pkt);

  /* A bit primitive, I have to  build the buffer myself */
  unsigned char expected_buf[16];
  std::copy(&pkt_buf[0], &pkt_buf[2], &expected_buf[0]);
  std::copy(&pkt_buf[2], &pkt_buf[8], &expected_buf[2]);
  std::copy(&pkt_buf[12], &pkt_buf[16], &expected_buf[8]);
  std::copy(&pkt_buf[header_size + 8], &pkt_buf[header_size + 12],
	    &expected_buf[12]);

  auto expected = hash::xxh64((const char *) expected_buf, sizeof(expected_buf));
  auto actual = calc.output(pkt);

  ASSERT_EQ(expected, actual);
}
TEST_F(CalculationTest, NonAlignedTest) {
  BufBuilder builder;

  builder.push_back_field(testHeader1, 4); // f5
  builder.push_back_field(testHeader1, 5); // f19

  Calculation calc(builder, "xxh64");;

  unsigned char pkt_buf[2 * header_size];

  for(size_t i = 0; i < sizeof(pkt_buf); i++) {
    pkt_buf[i] = dis(gen);
  }

  Packet pkt = get_pkt((const char *) pkt_buf, sizeof(pkt_buf));
  parser.parse(&pkt);

  /* A bit primitive, I have to  build the buffer myself */
  unsigned char expected_buf[3];
  std::copy(&pkt_buf[16], &pkt_buf[19], &expected_buf[0]);

  auto expected = hash::xxh64((const char *) expected_buf, sizeof(expected_buf));
  auto actual = calc.output(pkt);

  ASSERT_EQ(expected, actual);
}
TEST_F(ActionsTest, ModifyFieldWithHashBasedOffset) {
  uint64_t base = 100;
  uint64_t size = 65536; // 16 bits

  BufBuilder builder;
  builder.push_back_field(testHeader1, 0);
  builder.push_back_field(testHeader1, 4);
  NamedCalculation calculation("test_calculation", 0, builder, "xxh64");

  ModifyFieldWithHashBasedOffset primitive;
  testActionFn.push_back_primitive(&primitive);
  testActionFn.parameter_push_back_field(testHeader2, 3); // f16
  testActionFn.parameter_push_back_const(Data(base));
  testActionFn.parameter_push_back_calculation(&calculation);
  testActionFn.parameter_push_back_const(Data(size));

  unsigned int expected = (base + calculation.output(*pkt)) % size;

  testActionFnEntry(pkt.get());
  ASSERT_EQ(expected, phv->get_field(testHeader2, 3).get_uint());
}