+}
+
+static void create_writer_user_full(struct writer_user *user)
+{
+ gchar *trace_path;
+ struct bt_ctf_field_type *ft;
+ struct bt_ctf_field *field;
+ struct bt_ctf_clock *clock;
+ int ret;
+
+ trace_path = g_build_filename(g_get_tmp_dir(), "ctfwriter_XXXXXX", NULL);
+ if (!bt_mkdtemp(trace_path)) {
+ perror("# perror");
+ }
+
+ user->writer = bt_ctf_writer_create(trace_path);
+ BT_ASSERT(user->writer);
+ ret = bt_ctf_writer_set_byte_order(user->writer,
+ BT_CTF_BYTE_ORDER_LITTLE_ENDIAN);
+ BT_ASSERT(ret == 0);
+ user->tc = bt_ctf_writer_get_trace(user->writer);
+ BT_ASSERT(user->tc);
+ user->sc = bt_ctf_stream_class_create("sc");
+ BT_ASSERT(user->sc);
+ clock = bt_ctf_clock_create("the_clock");
+ BT_ASSERT(clock);
+ ret = bt_ctf_writer_add_clock(user->writer, clock);
+ BT_ASSERT(!ret);
+ ret = bt_ctf_stream_class_set_clock(user->sc, clock);
+ BT_ASSERT(!ret);
+ BT_PUT(clock);
+ user->stream = bt_ctf_writer_create_stream(user->writer, user->sc);
+ BT_ASSERT(user->stream);
+ user->ec = bt_ctf_event_class_create("ec");
+ BT_ASSERT(user->ec);
+ ft = create_writer_integer_struct();
+ BT_ASSERT(ft);
+ ret = bt_ctf_event_class_set_payload_field_type(user->ec, ft);
+ BT_PUT(ft);
+ BT_ASSERT(!ret);
+ ret = bt_ctf_stream_class_add_event_class(user->sc, user->ec);
+ BT_ASSERT(!ret);
+ user->event = bt_ctf_event_create(user->ec);
+ BT_ASSERT(user->event);
+ field = bt_ctf_event_get_payload(user->event, "payload_8");
+ BT_ASSERT(field);
+ ret = bt_ctf_field_integer_unsigned_set_value(field, 10);
+ BT_ASSERT(!ret);
+ BT_PUT(field);
+ field = bt_ctf_event_get_payload(user->event, "payload_16");
+ BT_ASSERT(field);
+ ret = bt_ctf_field_integer_unsigned_set_value(field, 20);
+ BT_ASSERT(!ret);
+ BT_PUT(field);
+ field = bt_ctf_event_get_payload(user->event, "payload_32");
+ BT_ASSERT(field);
+ ret = bt_ctf_field_integer_unsigned_set_value(field, 30);
+ BT_ASSERT(!ret);
+ BT_PUT(field);
+ ret = bt_ctf_stream_append_event(user->stream, user->event);
+ BT_ASSERT(!ret);
+ recursive_rmdir(trace_path);
+ g_free(trace_path);
+}
+
+static void test_put_order_swap(size_t *array, size_t a, size_t b)
+{
+ size_t temp = array[a];
+
+ array[a] = array[b];
+ array[b] = temp;
+}
+
+static void test_put_order_put_objects(size_t *array, size_t size)
+{
+ size_t i;
+ struct writer_user user = { 0 };
+ void **objects = (void *) &user;
+
+ create_writer_user_full(&user);
+ printf("# ");
+
+ for (i = 0; i < size; ++i) {
+ void *obj = objects[array[i]];
+
+ printf("%s", writer_user_names[array[i]]);
+ BT_PUT(obj);
+
+ if (i < size - 1) {
+ printf(" -> ");
+ }
+ }
+
+ puts("");
+}
+
+static void test_put_order_permute(size_t *array, int k, size_t size)
+{
+ if (k == 0) {
+ test_put_order_put_objects(array, size);
+ } else {
+ int i;
+
+ for (i = k - 1; i >= 0; i--) {
+ size_t next_k = k - 1;
+
+ test_put_order_swap(array, i, next_k);
+ test_put_order_permute(array, next_k, size);
+ test_put_order_swap(array, i, next_k);
+ }
+ }
+}
+
+static void test_put_order(void)
+{
+ size_t i;
+ size_t array[WRITER_USER_NR_ELEMENTS];
+
+ /* Initialize array of indexes */
+ for (i = 0; i < WRITER_USER_NR_ELEMENTS; ++i) {
+ array[i] = i;
+ }
+
+ test_put_order_permute(array, WRITER_USER_NR_ELEMENTS,
+ WRITER_USER_NR_ELEMENTS);
+}
+
+/**
+ * The objective of this test is to implement and expand upon the scenario
+ * described in the reference counting documentation and ensure that any node of
+ * the Trace, Stream Class, Event Class, Stream and Event hiearchy keeps all
+ * other "alive" and reachable.
+ *
+ * External tools (e.g. valgrind) should be used to confirm that this
+ * known-good test does not leak memory.
+ */
+int main(int argc, char **argv)
+{
+ /* Initialize tap harness before any tests */
+ plan_tests(NR_TESTS);
+
+ test_example_scenario();
+ test_put_order();
+