Example #1
0
/*!
 * Create a submessage within a message for a specific tag.
 *
 * \param[in,out] message Message
 * \param[in]     tag     Tag
 * \return                Submessage
 */
extern pb_message_t
pb_message_create_within(pb_message_t *message, pb_tag_t tag) {
  assert(message && tag);
  if (pb_message_valid(message)) {
    const pb_field_descriptor_t *descriptor =
      pb_descriptor_field_by_tag(message->descriptor, tag);
    assert(descriptor &&
      pb_field_descriptor_type(descriptor) == PB_TYPE_MESSAGE &&
      pb_field_descriptor_nested(descriptor));
    pb_message_t submessage = {
      .descriptor = pb_field_descriptor_nested(descriptor),
      .part       = pb_part_create(message, tag)
    };
    return submessage;
  }
  return pb_message_create_invalid();
}

/*!
 * Create a submessage within a nested message for a branch of tags.
 *
 * \warning All messages on the branch of tags except the leaf may not occur
 * repeatedly, but must be defined as optional or required.
 *
 * \param[in,out] message Message
 * \param[in]     tags[]  Tags
 * \param[in]     size    Tag count
 * \return                Submessage
 */
extern pb_message_t
pb_message_create_nested(
    pb_message_t *message, const pb_tag_t tags[], size_t size) {
  assert(message && tags && size);
  pb_message_t prev = pb_message_create_invalid(),
               this = pb_message_copy(message);
  for (size_t t = 0; t < size && pb_message_valid(&this); ++t) {
    pb_message_destroy(&prev);

#ifndef NDEBUG

    /* Assert non-repeated non-leaf messages */
    const pb_field_descriptor_t *descriptor =
      pb_descriptor_field_by_tag(this.descriptor, tags[t]);
    assert(descriptor && (
      pb_field_descriptor_type(descriptor)  == PB_TYPE_MESSAGE && (
      pb_field_descriptor_label(descriptor) != PB_LABEL_REPEATED ||
        t == size - 1)));

#endif /* NDEBUG */

    /* Swap messages and create a new one within */
    prev = this; this = pb_message_create_within(&prev, tags[t]);
  }
  pb_message_destroy(&prev);
  return this;
}
Example #2
0
} END_TEST

/*
 * Create a part from an invalid cursor.
 */
START_TEST(test_create_from_cursor_invalid) {
  pb_binary_t  binary  = pb_binary_create_empty();
  pb_message_t message = pb_message_create(&descriptor, &binary);
  pb_cursor_t  cursor  = pb_cursor_create_invalid();

  /* Assert cursor validity and error */
  fail_if(pb_cursor_valid(&cursor));
  ck_assert_uint_eq(PB_ERROR_INVALID, pb_cursor_error(&cursor));

  /* Create part from cursor */
  pb_part_t part = pb_part_create_from_cursor(&cursor);

  /* Assert part validity and error */
  fail_if(pb_part_valid(&part));
  ck_assert_uint_eq(PB_ERROR_INVALID, pb_part_error(&part));

  /* Free all allocated memory */
  pb_part_destroy(&part);
  pb_cursor_destroy(&cursor);
  pb_message_destroy(&message);
  pb_binary_destroy(&binary);
} END_TEST
Example #3
0
} END_TEST

/*
 * Create a part from an empty message for a specific tag.
 */
START_TEST(test_create_message_empty) {
  pb_binary_t  binary  = pb_binary_create_empty();
  pb_message_t message = pb_message_create(&descriptor, &binary);
  pb_part_t    part    = pb_part_create(&message, 1);

  /* Assert part validity and error */
  fail_unless(pb_part_valid(&part));
  ck_assert_uint_eq(PB_ERROR_NONE, pb_part_error(&part));

  /* Assert part size and version */
  fail_unless(pb_part_empty(&part));
  ck_assert_uint_eq(0, pb_part_size(&part));
  ck_assert_uint_eq(1, pb_part_version(&part));

  /* Assert part offsets */
  ck_assert_uint_eq(1, pb_part_start(&part));
  ck_assert_uint_eq(1, pb_part_end(&part));

  /* Assert binary size */
  fail_if(pb_binary_empty(&binary));
  ck_assert_uint_eq(1, pb_binary_size(&binary));

  /* Free all allocated memory */
  pb_part_destroy(&part);
  pb_message_destroy(&message);
  pb_binary_destroy(&binary);
} END_TEST
Example #4
0
} END_TEST

/*
 * Create a part at the current position of a cursor.
 */
START_TEST(test_create_from_cursor) {
  pb_binary_t  binary  = pb_binary_create_empty();
  pb_message_t message = pb_message_create(&descriptor, &binary);

  /* Create a hundred part siblings and write values to them */
  for (size_t p = 1; p < 101; p++) {
    pb_part_t part = pb_part_create(&message, 10);
    ck_assert_uint_eq(PB_ERROR_NONE,
      pb_part_write(&part, (uint8_t *)&p, 1));

    /* Free all allocated memory */
    pb_part_destroy(&part);
  }

  /* Create cursor */
  pb_cursor_t cursor = pb_cursor_create(&message, 10);

  /* Assert cursor validity and error */
  fail_unless(pb_cursor_valid(&cursor));
  ck_assert_uint_eq(PB_ERROR_NONE, pb_cursor_error(&cursor));

  /* Walk through parts */
  for (size_t p = 1; p < 101; p++, pb_cursor_next(&cursor)) {
    pb_part_t part = pb_part_create_from_cursor(&cursor);

    /* Assert part validity and error */
    fail_unless(pb_part_valid(&part));
    ck_assert_uint_eq(PB_ERROR_NONE, pb_part_error(&part));

    /* Assert part size and version */
    fail_if(pb_part_empty(&part));
    ck_assert_uint_eq(1, pb_part_size(&part));
    ck_assert_uint_eq(200, pb_part_version(&part));

    /* Assert part offsets */
    ck_assert_uint_eq(p * 2 - 1, pb_part_start(&part));
    ck_assert_uint_eq(p * 2, pb_part_end(&part));

    /* Free all allocated memory */
    pb_part_destroy(&part);
  }

  /* Assert cursor validity and error */
  fail_if(pb_cursor_valid(&cursor));
  ck_assert_uint_eq(PB_ERROR_OFFSET, pb_cursor_error(&cursor));

  /* Free all allocated memory */
  pb_cursor_destroy(&cursor);
  pb_message_destroy(&message);
  pb_binary_destroy(&binary);
} END_TEST
Example #5
0
} END_TEST

/*
 * Write a string value to a part.
 */
START_TEST(test_write_string) {
  const uint8_t data[] = { 66, 9, 83, 79, 77, 69, 32, 68, 65, 84, 65 };
  const size_t  size   = 11;

  /* Create binary, message and part */
  pb_binary_t  binary  = pb_binary_create_empty();
  pb_message_t message = pb_message_create(&descriptor, &binary);
  pb_part_t    part    = pb_part_create(&message, 8);

  /* Assert part validity and error */
  fail_unless(pb_part_valid(&part));
  ck_assert_uint_eq(PB_ERROR_NONE, pb_part_error(&part));

  /* Assert part size and version */
  fail_unless(pb_part_empty(&part));
  ck_assert_uint_eq(0, pb_part_size(&part));
  ck_assert_uint_eq(1, pb_part_version(&part));

  /* Write value to part */
  uint8_t value[] = "SOME DATA";
  ck_assert_uint_eq(PB_ERROR_NONE, pb_part_write(&part, value, 9));
  fail_if(memcmp(data, pb_binary_data(&binary), size));

  /* Assert part validity and error again */
  fail_unless(pb_part_valid(&part));
  ck_assert_uint_eq(PB_ERROR_NONE, pb_part_error(&part));

  /* Assert part size and version */
  fail_if(pb_part_empty(&part));
  ck_assert_uint_eq(9, pb_part_size(&part));
  ck_assert_uint_eq(2, pb_part_version(&part));

  /* Assert part offsets */
  ck_assert_uint_eq(2,  pb_part_start(&part));
  ck_assert_uint_eq(11, pb_part_end(&part));

  /* Assert binary size */
  fail_if(pb_binary_empty(&binary));
  ck_assert_uint_eq(11, pb_binary_size(&binary));

  /* Free all allocated memory */
  pb_part_destroy(&part);
  pb_message_destroy(&message);
  pb_binary_destroy(&binary);
} END_TEST
Example #6
0
} END_TEST

/*
 * Write a value to a part.
 */
START_TEST(test_write) {
  uint8_t data[] = { 8, 127 };
  size_t  size   = 2;

  /* Create binary, message and part */
  pb_binary_t  binary  = pb_binary_create_empty();
  pb_message_t message = pb_message_create(&descriptor, &binary);
  pb_part_t    part    = pb_part_create(&message, 1);

  /* Assert part validity and error */
  fail_unless(pb_part_valid(&part));
  ck_assert_uint_eq(PB_ERROR_NONE, pb_part_error(&part));

  /* Assert part size and version */
  fail_unless(pb_part_empty(&part));
  ck_assert_uint_eq(0, pb_part_size(&part));
  ck_assert_uint_eq(1, pb_part_version(&part));

  /* Write value to part */
  uint8_t value[] = { 127 };
  ck_assert_uint_eq(PB_ERROR_NONE, pb_part_write(&part, value, 1));
  fail_if(memcmp(data, pb_binary_data(&binary), size));

  /* Assert part validity and error again */
  fail_unless(pb_part_valid(&part));
  ck_assert_uint_eq(PB_ERROR_NONE, pb_part_error(&part));

  /* Assert part size and version */
  fail_if(pb_part_empty(&part));
  ck_assert_uint_eq(1, pb_part_size(&part));
  ck_assert_uint_eq(2, pb_part_version(&part));

  /* Assert part offsets */
  ck_assert_uint_eq(1, pb_part_start(&part));
  ck_assert_uint_eq(2, pb_part_end(&part));

  /* Assert binary size */
  fail_if(pb_binary_empty(&binary));
  ck_assert_uint_eq(2, pb_binary_size(&binary));

  /* Free all allocated memory */
  pb_part_destroy(&part);
  pb_message_destroy(&message);
  pb_binary_destroy(&binary);
} END_TEST
Example #7
0
} END_TEST

/*
 * Create a part from an invalid message for a specific tag.
 */
START_TEST(test_create_message_invalid) {
  pb_message_t message = pb_message_create_invalid();
  pb_part_t    part    = pb_part_create(&message, 1);

  /* Assert part validity and error */
  fail_if(pb_part_valid(&part));
  ck_assert_uint_eq(PB_ERROR_INVALID, pb_part_error(&part));

  /* Free all allocated memory */
  pb_part_destroy(&part);
  pb_message_destroy(&message);
} END_TEST
Example #8
0
} END_TEST

/*
 * Write a long string value to a part.
 */
START_TEST(test_write_string_long) {
  pb_binary_t  binary  = pb_binary_create_empty();
  pb_message_t message = pb_message_create(&descriptor, &binary);
  pb_part_t    part    = pb_part_create(&message, 8);

  /* Assert part validity and error */
  fail_unless(pb_part_valid(&part));
  ck_assert_uint_eq(PB_ERROR_NONE, pb_part_error(&part));

  /* Assert part size and version */
  fail_unless(pb_part_empty(&part));
  ck_assert_uint_eq(0, pb_part_size(&part));
  ck_assert_uint_eq(1, pb_part_version(&part));

  /* Write value to part */
  pb_string_t value = pb_string_init(
    "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam euismod "
    "vehicula nibh, et egestas erat eleifend quis. Nam hendrerit egestas "
    "quam nec egestas. Donec lacinia vestibulum erat, ac suscipit nisi "
    "vehicula nec. Praesent ullamcorper vitae lorem vel euismod. Quisque "
    "fringilla lobortis convallis. Aliquam accumsan lacus eu viverra dapibus. "
    "Phasellus in adipiscing sem, in congue massa. Vestibulum ullamcorper "
    "orci nec semper pretium.");
  ck_assert_uint_eq(PB_ERROR_NONE,
    pb_part_write(&part, value.data, value.size));

  /* Assert part validity and error again */
  fail_unless(pb_part_valid(&part));
  ck_assert_uint_eq(PB_ERROR_NONE, pb_part_error(&part));

  /* Assert part size and version */
  fail_if(pb_part_empty(&part));
  ck_assert_uint_eq(437, pb_part_size(&part));
  ck_assert_uint_eq(3, pb_part_version(&part));

  /* Free all allocated memory */
  pb_part_destroy(&part);
  pb_message_destroy(&message);
  pb_binary_destroy(&binary);
} END_TEST
Example #9
0
} END_TEST

/*
 * Create a set of repeated parts within a message for a specific tag.
 */
START_TEST(test_create_repeated) {
  pb_binary_t  binary  = pb_binary_create_empty();
  pb_message_t message = pb_message_create(&descriptor, &binary);

  /* Create a hundred parts and write values to them */
  for (size_t p = 1; p < 101; p++) {
    pb_part_t part = pb_part_create(&message, 10);
    ck_assert_uint_eq(PB_ERROR_NONE,
      pb_part_write(&part, (uint8_t *)&p, 1));

    /* Assert part validity and error */
    fail_unless(pb_part_valid(&part));
    ck_assert_uint_eq(PB_ERROR_NONE, pb_part_error(&part));

    /* Assert part size and version */
    fail_if(pb_part_empty(&part));
    ck_assert_uint_eq(1, pb_part_size(&part));
    ck_assert_uint_eq(p * 2, pb_part_version(&part));

    /* Assert part offsets */
    ck_assert_uint_eq(p * 2 - 1, pb_part_start(&part));
    ck_assert_uint_eq(p * 2, pb_part_end(&part));

    /* Assert binary size */
    fail_if(pb_binary_empty(&binary));
    ck_assert_uint_eq(p * 2, pb_binary_size(&binary));

    /* Free all allocated memory */
    pb_part_destroy(&part);
  }

  /* Assert binary contents */
  for (size_t p = 1; p < 101; p++)
    ck_assert_uint_eq(p, pb_binary_data_at(&binary, p * 2 - 1));

  /* Free all allocated memory */
  pb_message_destroy(&message);
  pb_binary_destroy(&binary);
} END_TEST