+enum field_type {
+ FIELD_TYPE_PAYLOAD,
+ FIELD_TYPE_CONTEXT,
+ FIELD_TYPE_APP_CONTEXT,
+ FIELD_TYPE_ARRAY_FIELD,
+};
+
+struct capture_base_field_tuple {
+ char* field_name;
+ enum field_type field_type;
+ bool expected_ust; // Do we expect a capture?
+ bool expected_kernel; // Do we expect a capture?
+ validate_cb validate_ust;
+ validate_cb validate_kernel;
+};
+
+static
+const char *field_value_type_to_str(enum lttng_event_field_value_type type)
+{
+ switch (type) {
+ case LTTNG_EVENT_FIELD_VALUE_TYPE_UNKNOWN:
+ return "UNKNOWN";
+ case LTTNG_EVENT_FIELD_VALUE_TYPE_INVALID:
+ return "INVALID";
+ case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT:
+ return "UNSIGNED INT";
+ case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT:
+ return "SIGNED INT";
+ case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM:
+ return "UNSIGNED ENUM";
+ case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM:
+ return "SIGNED ENUM";
+ case LTTNG_EVENT_FIELD_VALUE_TYPE_REAL:
+ return "REAL";
+ case LTTNG_EVENT_FIELD_VALUE_TYPE_STRING:
+ return "STRING";
+ case LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY:
+ return "ARRAY";
+ default:
+ abort();
+ }
+}
+
+static int validate_type(
+ const struct lttng_event_field_value *event_field,
+ enum lttng_event_field_value_type expect)
+{
+ int ret;
+ enum lttng_event_field_value_type value;
+
+ value = lttng_event_field_value_get_type(event_field);
+ if (value == LTTNG_EVENT_FIELD_VALUE_TYPE_INVALID) {
+ ret = 1;
+ goto end;
+ }
+
+ ret = (expect == value);
+ ok(ret, "Expected field type: %s got %s",
+ field_value_type_to_str(expect),
+ field_value_type_to_str(value));
+
+ ret = !ret;
+
+end:
+ return ret;
+}
+
+/*
+ * Validate unsigned captured field against the iteration number.
+ * The iteration number is always unsigned and will always be compared to value
+ * under MAX_UINT.
+ */
+static int validate_unsigned_int_field(
+ const struct lttng_event_field_value *event_field,
+ unsigned int iteration)
+{
+ int ret;
+ uint64_t value;
+ enum lttng_event_field_value_status status;
+
+ ret = validate_type(event_field, LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT);
+ if (ret) {
+ goto end;
+ }
+
+ status = lttng_event_field_value_unsigned_int_get_value(
+ event_field , &value);
+ if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
+ fail("lttng_event_field_value_unsigned_int_get_value");
+ ret = 1;
+ goto end;
+ }
+
+ ret = (value == (uint64_t) iteration);
+ ok (ret, "Expected unsigned int of value: %u got %" PRIu64, iteration, value);
+
+ ret = !ret;
+
+end:
+
+ return ret;
+}
+
+/*
+ * Validate signed captured field.
+ * Value should be -1.
+ */
+static int validate_signed_int_field(
+ const struct lttng_event_field_value *event_field,
+ unsigned int iteration)
+{
+ int ret;
+ int64_t expected = -1;
+ int64_t value;
+ enum lttng_event_field_value_status status;
+
+ /* Unused */
+ (void) iteration;
+
+ ret = validate_type(event_field, LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT);
+ if (ret) {
+ goto end;
+ }
+
+ status = lttng_event_field_value_signed_int_get_value(
+ event_field , &value);
+ if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
+ fail("lttng_event_field_value_signed_int_get_value");
+ ret = 1;
+ goto end;
+ }
+
+ ret = (value == expected);
+ ok(ret, "Expected signed int of value: %" PRId64 " got %" PRId64, expected, value);
+
+ ret = !ret;
+
+end:
+
+ return ret;
+}
+
+/*
+ * Validate array of unsigned int.
+ */
+static int validate_array_unsigned_int_field(
+ const struct lttng_event_field_value *event_field,
+ unsigned int iteration)
+{
+ int ret;
+ enum lttng_event_field_value_status status;
+ unsigned int expected = 3;
+ unsigned int count;
+
+ /* Unused */
+ (void) iteration;
+
+ ret = validate_type(event_field, LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY);
+ if (ret) {
+ goto end;
+ }
+
+ status = lttng_event_field_value_array_get_length(event_field, &count);
+ if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
+ fail("lttng_event_field_value_array_get_length");
+ ret = 1;
+ goto end;
+ }
+
+ ret = (count == expected);
+ ok(ret, "Expected %d subelements got %d", expected, count);
+ if (!ret) {
+ ret = 1;
+ goto end;
+ }
+
+ for (unsigned int i = 1; i < count + 1; i++) {
+ const struct lttng_event_field_value *value;
+ status = lttng_event_field_value_array_get_element_at_index(
+ event_field, i - 1, &value);
+ if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
+ fail("lttng_event_field_value_array_get_element_at_index");
+ ret = 1;
+ goto end;
+ }
+ ret = validate_unsigned_int_field(value, i);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ ret = 0;
+end:
+
+ return ret;
+}
+static int validate_array_unsigned_int_field_at_index(
+ const struct lttng_event_field_value *event_field,
+ unsigned int iteration)
+{
+ int ret;
+ uint64_t expected_value = 2;
+ enum lttng_event_field_value_status status;
+ uint64_t value;
+
+ /* Unused */
+ (void) iteration;
+
+ ret = validate_type(event_field, LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT);
+ if (ret) {
+ goto end;
+ }
+
+ status = lttng_event_field_value_unsigned_int_get_value(
+ event_field , &value);
+ if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
+ fail("lttng_event_field_value_unsigned_int_get_value");
+ ret = 1;
+ goto end;
+ }
+
+ ret = (value == expected_value);
+ ok (ret, "Expected unsigned int of value: %u got %" PRIu64,
+ expected_value, value);
+
+ ret = 0;
+end:
+ return ret;
+}
+
+/*
+ * Validate sequence for a string (seqfield1):
+ *
+ * Value: "test" in utf8 [116, 101, 115, 116]
+ */
+static int validate_seqfield1(
+ const struct lttng_event_field_value *event_field,
+ unsigned int iteration)
+{
+ int ret;
+ enum lttng_event_field_value_status status;
+ unsigned int count;
+ unsigned int expect[4] = {116, 101, 115, 116};
+
+ /* Unused */
+ (void) iteration;
+
+ ret = validate_type(event_field, LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY);
+ if (ret) {
+ goto end;
+ }
+
+ status = lttng_event_field_value_array_get_length(event_field, &count);
+ if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
+ fail("lttng_event_field_value_array_get_length");
+ ret = 1;
+ goto end;
+ }
+
+ ret = (count == 4);
+ ok(ret, "Expected 4 subelement got %d", count);
+ if (!ret) {
+ ret = 1;
+ goto end;
+ }
+
+ for (unsigned int i = 0; i < count ; i++) {
+ const struct lttng_event_field_value *value;
+ status = lttng_event_field_value_array_get_element_at_index(
+ event_field, i, &value);
+ if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
+ fail("lttng_event_field_value_array_get_element_at_index");
+ ret = 1;
+ goto end;
+ }
+ ret = validate_unsigned_int_field(value, expect[i]);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ ret = 0;
+end:
+
+ return ret;
+}
+
+static int validate_string(
+ const struct lttng_event_field_value *event_field,
+ const char *expect)
+{
+ int ret;
+ const char *value = NULL;
+
+ ret = validate_type(event_field, LTTNG_EVENT_FIELD_VALUE_TYPE_STRING);
+ if (ret) {
+ goto end;
+ }
+
+ value = lttng_event_field_value_string_get_value(event_field);
+ if (!value) {
+ fail("lttng_event_field_value_array_get_length");
+ ret = 1;
+ goto end;
+ }
+
+ ok(!strcmp(value, expect), "Expected string: \"%s\" got \"%s\"", expect, value);
+
+ ret = 0;
+end:
+
+ return ret;
+}
+
+/*
+ * Validate string. Expected value is "test".
+ */
+static int validate_string_test(
+ const struct lttng_event_field_value *event_field,
+ unsigned int iteration)
+{
+ int ret;
+ const char *expect = "test";
+
+ /* Unused */
+ (void) iteration;
+
+ ret = validate_string(event_field, expect);
+ return ret;
+}
+
+/*
+ * Validate escaped string. Expected value is "\*".
+ */
+static int validate_string_escaped(
+ const struct lttng_event_field_value *event_field,
+ unsigned int iteration)
+{
+ int ret;
+ const char *expect = "\\*";
+
+ /* Unused */
+ (void) iteration;
+
+ ret = validate_string(event_field, expect);
+ return ret;
+}
+
+/*
+ * Validate real field.
+ */
+static int validate_real(
+ const struct lttng_event_field_value *event_field,
+ double expect)
+{
+ int ret;
+ double value;
+ enum lttng_event_field_value_status status;
+
+ ret = validate_type(event_field, LTTNG_EVENT_FIELD_VALUE_TYPE_REAL);
+ if (ret) {
+ goto end;
+ }
+
+ status = lttng_event_field_value_real_get_value(event_field, &value);
+ if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
+ fail("lttng_event_field_value_real_get_value");
+ ret = 1;
+ goto end;
+ }
+
+ ret = (value == expect);
+ ok(ret, "Real expected: %f got: %f", expect, value);
+
+ ret = !ret;
+end:
+ return ret;
+}
+
+/*
+ * Validate floatfield.
+ */
+static int validate_floatfield(
+ const struct lttng_event_field_value *event_field,
+ unsigned int iteration)
+{
+ int ret;
+ double expect = 2222.0;
+
+ /* Unused */
+ (void) iteration;
+
+ ret = validate_real(event_field, expect);
+ return ret;
+}
+
+/*
+ * Validate doublefield.
+ */
+static int validate_doublefield(
+ const struct lttng_event_field_value *event_field,
+ unsigned int iteration)
+{
+ int ret;
+ double expect = 2.0;
+
+ /* Unused */
+ (void) iteration;
+
+ ret = validate_real(event_field, expect);
+ return ret;
+}
+
+/*
+ * Validate enum0: enum0 = ( "AUTO: EXPECT 0" : container = 0 )
+ */
+static int validate_enum0(const struct lttng_event_field_value *event_field,
+ unsigned int iteration)
+{
+ int ret;
+ enum lttng_event_field_value_status status;
+ uint64_t value;
+ uint64_t expected_value = 0;
+
+ /* Unused */
+ (void) iteration;
+
+ ret = validate_type(event_field,
+ LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM);
+ if (ret) {
+ goto end;
+ }
+
+ status = lttng_event_field_value_unsigned_int_get_value(
+ event_field, &value);
+ if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
+ fail("lttng_event_field_value_unsigned_int_get_value");
+ ret = 1;
+ goto end;
+ }
+
+ ok(value == expected_value,
+ "Enum value expected: %" PRIu64 " got %" PRIu64,
+ expected_value, value);
+
+end:
+ return ret;
+}
+
+/*
+ * Validate enumnegative: enumnegative = ( "AUTO: EXPECT 0" : container = 0 )
+ *
+ * We expect 2 labels here.
+ */
+static int validate_enumnegative(
+ const struct lttng_event_field_value *event_field,
+ unsigned int iteration)
+{
+ int ret;
+ enum lttng_event_field_value_status status;
+ int64_t value;
+ int64_t expected_value = -1;
+
+ /* Unused */
+ (void) iteration;
+
+ ret = validate_type(
+ event_field, LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM);
+ if (ret) {
+ goto end;
+ }
+
+ status = lttng_event_field_value_signed_int_get_value(
+ event_field, &value);
+ if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
+ fail("lttng_event_field_value_unsigned_int_get_value");
+ ret = 1;
+ goto end;
+ }
+
+ ok(value == expected_value,
+ "Enum value expected: %" PRId64 " got %" PRId64,
+ expected_value, value);
+
+end:
+ return ret;
+}
+
+static int validate_context_procname_ust(
+ const struct lttng_event_field_value *event_field,
+ unsigned int iteration)
+{
+ int ret;
+
+ /* Unused */
+ (void) iteration;
+
+ ret = validate_string(event_field, "gen-ust-events");
+ return ret;
+}
+
+static int validate_context_procname_kernel(
+ const struct lttng_event_field_value *event_field,
+ unsigned int iteration)
+{
+ int ret;
+
+ /* Unused */
+ (void) iteration;
+
+ ret = validate_string(event_field, "echo");
+ return ret;
+}
+
+struct capture_base_field_tuple test_capture_base_fields[] = {
+ {"DOESNOTEXIST", FIELD_TYPE_PAYLOAD, false, false, NULL, NULL},
+ {"intfield", FIELD_TYPE_PAYLOAD, true, true, validate_unsigned_int_field, validate_unsigned_int_field},
+ {"longfield", FIELD_TYPE_PAYLOAD, true, true, validate_unsigned_int_field, validate_unsigned_int_field},
+ {"signedfield", FIELD_TYPE_PAYLOAD, true, true, validate_signed_int_field, validate_signed_int_field},
+ {"arrfield1", FIELD_TYPE_PAYLOAD, true, true, validate_array_unsigned_int_field, validate_array_unsigned_int_field},
+ {"arrfield2", FIELD_TYPE_PAYLOAD, true, true, validate_string_test, validate_string_test},
+ {"arrfield3", FIELD_TYPE_PAYLOAD, true, true, validate_array_unsigned_int_field, validate_array_unsigned_int_field},
+ {"seqfield1", FIELD_TYPE_PAYLOAD, true, true, validate_seqfield1, validate_seqfield1},
+ {"seqfield2", FIELD_TYPE_PAYLOAD, true, true, validate_string_test, validate_string_test},
+ {"seqfield3", FIELD_TYPE_PAYLOAD, true, true, validate_array_unsigned_int_field, validate_array_unsigned_int_field},
+ {"seqfield4", FIELD_TYPE_PAYLOAD, true, true, validate_array_unsigned_int_field, validate_array_unsigned_int_field},
+ {"arrfield1[1]", FIELD_TYPE_ARRAY_FIELD, true, true, validate_array_unsigned_int_field_at_index, validate_array_unsigned_int_field_at_index},
+ {"stringfield", FIELD_TYPE_PAYLOAD, true, true, validate_string_test, validate_string_test},
+ {"stringfield2", FIELD_TYPE_PAYLOAD, true, true, validate_string_escaped, validate_string_escaped},
+ {"floatfield", FIELD_TYPE_PAYLOAD, true, false, validate_floatfield, validate_floatfield},
+ {"doublefield", FIELD_TYPE_PAYLOAD, true, false, validate_doublefield, validate_doublefield},
+ {"enum0", FIELD_TYPE_PAYLOAD, true, true, validate_enum0, validate_enum0},
+ {"enumnegative", FIELD_TYPE_PAYLOAD, true, true, validate_enumnegative, validate_enumnegative},
+ {"$ctx.procname", FIELD_TYPE_CONTEXT, true, true, validate_context_procname_ust, validate_context_procname_kernel},
+};
+