13ef7ff83SDavid Woodhouse /* 23ef7ff83SDavid Woodhouse * QEMU XenStore XsNode testing 33ef7ff83SDavid Woodhouse * 43ef7ff83SDavid Woodhouse * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 53ef7ff83SDavid Woodhouse 63ef7ff83SDavid Woodhouse * This work is licensed under the terms of the GNU GPL, version 2 or later. 73ef7ff83SDavid Woodhouse * See the COPYING file in the top-level directory. 83ef7ff83SDavid Woodhouse */ 93ef7ff83SDavid Woodhouse 103ef7ff83SDavid Woodhouse #include "qemu/osdep.h" 113ef7ff83SDavid Woodhouse #include "qapi/error.h" 123ef7ff83SDavid Woodhouse #include "qemu/module.h" 133ef7ff83SDavid Woodhouse 143ef7ff83SDavid Woodhouse static int nr_xs_nodes; 153ef7ff83SDavid Woodhouse static GList *xs_node_list; 163ef7ff83SDavid Woodhouse 173ef7ff83SDavid Woodhouse #define XS_NODE_UNIT_TEST 183ef7ff83SDavid Woodhouse 193ef7ff83SDavid Woodhouse /* 203ef7ff83SDavid Woodhouse * We don't need the core Xen definitions. And we *do* want to be able 213ef7ff83SDavid Woodhouse * to run the unit tests even on architectures that Xen doesn't support 223ef7ff83SDavid Woodhouse * (because life's too short to bother doing otherwise, and test coverage 233ef7ff83SDavid Woodhouse * doesn't hurt). 243ef7ff83SDavid Woodhouse */ 253ef7ff83SDavid Woodhouse #define __XEN_PUBLIC_XEN_H__ 263ef7ff83SDavid Woodhouse 273ef7ff83SDavid Woodhouse #include "hw/i386/kvm/xenstore_impl.c" 283ef7ff83SDavid Woodhouse 293ef7ff83SDavid Woodhouse #define DOMID_QEMU 0 303ef7ff83SDavid Woodhouse #define DOMID_GUEST 1 313ef7ff83SDavid Woodhouse 323ef7ff83SDavid Woodhouse /* This doesn't happen in qemu but we want to make valgrind happy */ 333ef7ff83SDavid Woodhouse static void xs_impl_delete(XenstoreImplState *s) 343ef7ff83SDavid Woodhouse { 353ef7ff83SDavid Woodhouse int err; 363ef7ff83SDavid Woodhouse 376e133009SDavid Woodhouse xs_impl_reset_watches(s, DOMID_GUEST); 386e133009SDavid Woodhouse g_assert(!s->nr_domu_watches); 396e133009SDavid Woodhouse 403ef7ff83SDavid Woodhouse err = xs_impl_rm(s, DOMID_QEMU, XBT_NULL, "/local"); 413ef7ff83SDavid Woodhouse g_assert(!err); 423ef7ff83SDavid Woodhouse g_assert(s->nr_nodes == 1); 433ef7ff83SDavid Woodhouse 446e133009SDavid Woodhouse g_hash_table_unref(s->watches); 45*7248b87cSDavid Woodhouse g_hash_table_unref(s->transactions); 463ef7ff83SDavid Woodhouse xs_node_unref(s->root); 473ef7ff83SDavid Woodhouse g_free(s); 483ef7ff83SDavid Woodhouse 493ef7ff83SDavid Woodhouse if (xs_node_list) { 503ef7ff83SDavid Woodhouse GList *l; 513ef7ff83SDavid Woodhouse for (l = xs_node_list; l; l = l->next) { 523ef7ff83SDavid Woodhouse XsNode *n = l->data; 533ef7ff83SDavid Woodhouse printf("Remaining node at %p name %s ref %u\n", n, n->name, 543ef7ff83SDavid Woodhouse n->ref); 553ef7ff83SDavid Woodhouse } 563ef7ff83SDavid Woodhouse } 573ef7ff83SDavid Woodhouse g_assert(!nr_xs_nodes); 583ef7ff83SDavid Woodhouse } 593ef7ff83SDavid Woodhouse 603ef7ff83SDavid Woodhouse static int write_str(XenstoreImplState *s, unsigned int dom_id, 613ef7ff83SDavid Woodhouse unsigned int tx_id, const char *path, 623ef7ff83SDavid Woodhouse const char *content) 633ef7ff83SDavid Woodhouse { 643ef7ff83SDavid Woodhouse GByteArray *d = g_byte_array_new(); 653ef7ff83SDavid Woodhouse int err; 663ef7ff83SDavid Woodhouse 673ef7ff83SDavid Woodhouse g_byte_array_append(d, (void *)content, strlen(content)); 683ef7ff83SDavid Woodhouse err = xs_impl_write(s, dom_id, tx_id, path, d); 693ef7ff83SDavid Woodhouse g_byte_array_unref(d); 703ef7ff83SDavid Woodhouse return err; 713ef7ff83SDavid Woodhouse } 723ef7ff83SDavid Woodhouse 736e133009SDavid Woodhouse static void watch_cb(void *_str, const char *path, const char *token) 746e133009SDavid Woodhouse { 756e133009SDavid Woodhouse GString *str = _str; 766e133009SDavid Woodhouse 776e133009SDavid Woodhouse g_string_append(str, path); 786e133009SDavid Woodhouse g_string_append(str, token); 796e133009SDavid Woodhouse } 806e133009SDavid Woodhouse 813ef7ff83SDavid Woodhouse static XenstoreImplState *setup(void) 823ef7ff83SDavid Woodhouse { 833ef7ff83SDavid Woodhouse XenstoreImplState *s = xs_impl_create(); 843ef7ff83SDavid Woodhouse char *abspath; 853ef7ff83SDavid Woodhouse int err; 863ef7ff83SDavid Woodhouse 873ef7ff83SDavid Woodhouse abspath = g_strdup_printf("/local/domain/%u", DOMID_GUEST); 883ef7ff83SDavid Woodhouse 893ef7ff83SDavid Woodhouse err = write_str(s, DOMID_QEMU, XBT_NULL, abspath, ""); 903ef7ff83SDavid Woodhouse g_assert(!err); 916e133009SDavid Woodhouse g_assert(s->nr_nodes == 4); 923ef7ff83SDavid Woodhouse 933ef7ff83SDavid Woodhouse g_free(abspath); 943ef7ff83SDavid Woodhouse 953ef7ff83SDavid Woodhouse abspath = g_strdup_printf("/local/domain/%u/some", DOMID_GUEST); 963ef7ff83SDavid Woodhouse 973ef7ff83SDavid Woodhouse err = write_str(s, DOMID_QEMU, XBT_NULL, abspath, ""); 983ef7ff83SDavid Woodhouse g_assert(!err); 993ef7ff83SDavid Woodhouse g_assert(s->nr_nodes == 5); 1003ef7ff83SDavid Woodhouse 1013ef7ff83SDavid Woodhouse g_free(abspath); 1023ef7ff83SDavid Woodhouse 1033ef7ff83SDavid Woodhouse return s; 1043ef7ff83SDavid Woodhouse } 1053ef7ff83SDavid Woodhouse 1063ef7ff83SDavid Woodhouse static void test_xs_node_simple(void) 1073ef7ff83SDavid Woodhouse { 1083ef7ff83SDavid Woodhouse GByteArray *data = g_byte_array_new(); 1093ef7ff83SDavid Woodhouse XenstoreImplState *s = setup(); 1106e133009SDavid Woodhouse GString *guest_watches = g_string_new(NULL); 1116e133009SDavid Woodhouse GString *qemu_watches = g_string_new(NULL); 1123ef7ff83SDavid Woodhouse GList *items = NULL; 1133ef7ff83SDavid Woodhouse XsNode *old_root; 1143ef7ff83SDavid Woodhouse uint64_t gencnt; 1153ef7ff83SDavid Woodhouse int err; 1163ef7ff83SDavid Woodhouse 1173ef7ff83SDavid Woodhouse g_assert(s); 1183ef7ff83SDavid Woodhouse 1196e133009SDavid Woodhouse err = xs_impl_watch(s, DOMID_GUEST, "some", "guestwatch", 1206e133009SDavid Woodhouse watch_cb, guest_watches); 1216e133009SDavid Woodhouse g_assert(!err); 1226e133009SDavid Woodhouse g_assert(guest_watches->len == strlen("someguestwatch")); 1236e133009SDavid Woodhouse g_assert(!strcmp(guest_watches->str, "someguestwatch")); 1246e133009SDavid Woodhouse g_string_truncate(guest_watches, 0); 1256e133009SDavid Woodhouse 1266e133009SDavid Woodhouse err = xs_impl_watch(s, 0, "/local/domain/1/some", "qemuwatch", 1276e133009SDavid Woodhouse watch_cb, qemu_watches); 1286e133009SDavid Woodhouse g_assert(!err); 1296e133009SDavid Woodhouse g_assert(qemu_watches->len == strlen("/local/domain/1/someqemuwatch")); 1306e133009SDavid Woodhouse g_assert(!strcmp(qemu_watches->str, "/local/domain/1/someqemuwatch")); 1316e133009SDavid Woodhouse g_string_truncate(qemu_watches, 0); 1326e133009SDavid Woodhouse 1333ef7ff83SDavid Woodhouse /* Read gives ENOENT when it should */ 1343ef7ff83SDavid Woodhouse err = xs_impl_read(s, DOMID_GUEST, XBT_NULL, "foo", data); 1353ef7ff83SDavid Woodhouse g_assert(err == ENOENT); 1363ef7ff83SDavid Woodhouse 1373ef7ff83SDavid Woodhouse /* Write works */ 1383ef7ff83SDavid Woodhouse err = write_str(s, DOMID_GUEST, XBT_NULL, "some/relative/path", 1393ef7ff83SDavid Woodhouse "something"); 1403ef7ff83SDavid Woodhouse g_assert(s->nr_nodes == 7); 1413ef7ff83SDavid Woodhouse g_assert(!err); 1426e133009SDavid Woodhouse g_assert(!strcmp(guest_watches->str, 1436e133009SDavid Woodhouse "some/relative/pathguestwatch")); 1446e133009SDavid Woodhouse g_assert(!strcmp(qemu_watches->str, 1456e133009SDavid Woodhouse "/local/domain/1/some/relative/pathqemuwatch")); 1466e133009SDavid Woodhouse 1476e133009SDavid Woodhouse g_string_truncate(qemu_watches, 0); 1486e133009SDavid Woodhouse g_string_truncate(guest_watches, 0); 1496e133009SDavid Woodhouse xs_impl_reset_watches(s, 0); 1503ef7ff83SDavid Woodhouse 1513ef7ff83SDavid Woodhouse /* Read gives back what we wrote */ 1523ef7ff83SDavid Woodhouse err = xs_impl_read(s, DOMID_GUEST, XBT_NULL, "some/relative/path", data); 1533ef7ff83SDavid Woodhouse g_assert(!err); 1543ef7ff83SDavid Woodhouse g_assert(data->len == strlen("something")); 1553ef7ff83SDavid Woodhouse g_assert(!memcmp(data->data, "something", data->len)); 1563ef7ff83SDavid Woodhouse 1573ef7ff83SDavid Woodhouse /* Even if we use an abolute path */ 1583ef7ff83SDavid Woodhouse g_byte_array_set_size(data, 0); 1593ef7ff83SDavid Woodhouse err = xs_impl_read(s, DOMID_GUEST, XBT_NULL, 1603ef7ff83SDavid Woodhouse "/local/domain/1/some/relative/path", data); 1613ef7ff83SDavid Woodhouse g_assert(!err); 1623ef7ff83SDavid Woodhouse g_assert(data->len == strlen("something")); 1633ef7ff83SDavid Woodhouse 1646e133009SDavid Woodhouse g_assert(!qemu_watches->len); 1656e133009SDavid Woodhouse g_assert(!guest_watches->len); 1663ef7ff83SDavid Woodhouse /* Keep a copy, to force COW mode */ 1673ef7ff83SDavid Woodhouse old_root = xs_node_ref(s->root); 1683ef7ff83SDavid Woodhouse 1693ef7ff83SDavid Woodhouse /* Write works again */ 1703ef7ff83SDavid Woodhouse err = write_str(s, DOMID_GUEST, XBT_NULL, 1713ef7ff83SDavid Woodhouse "/local/domain/1/some/relative/path2", 1723ef7ff83SDavid Woodhouse "something else"); 1733ef7ff83SDavid Woodhouse g_assert(!err); 1743ef7ff83SDavid Woodhouse g_assert(s->nr_nodes == 8); 1756e133009SDavid Woodhouse g_assert(!qemu_watches->len); 1766e133009SDavid Woodhouse g_assert(!strcmp(guest_watches->str, "some/relative/path2guestwatch")); 1776e133009SDavid Woodhouse g_string_truncate(guest_watches, 0); 1783ef7ff83SDavid Woodhouse 1793ef7ff83SDavid Woodhouse /* Overwrite an existing node */ 1803ef7ff83SDavid Woodhouse err = write_str(s, DOMID_GUEST, XBT_NULL, "some/relative/path", 1813ef7ff83SDavid Woodhouse "another thing"); 1823ef7ff83SDavid Woodhouse g_assert(!err); 1833ef7ff83SDavid Woodhouse g_assert(s->nr_nodes == 8); 1846e133009SDavid Woodhouse g_assert(!qemu_watches->len); 1856e133009SDavid Woodhouse g_assert(!strcmp(guest_watches->str, "some/relative/pathguestwatch")); 1866e133009SDavid Woodhouse g_string_truncate(guest_watches, 0); 1873ef7ff83SDavid Woodhouse 1883ef7ff83SDavid Woodhouse /* We can list the two files we wrote */ 1893ef7ff83SDavid Woodhouse err = xs_impl_directory(s, DOMID_GUEST, XBT_NULL, "some/relative", &gencnt, 1903ef7ff83SDavid Woodhouse &items); 1913ef7ff83SDavid Woodhouse g_assert(!err); 1923ef7ff83SDavid Woodhouse g_assert(items); 1933ef7ff83SDavid Woodhouse g_assert(gencnt == 2); 1943ef7ff83SDavid Woodhouse g_assert(!strcmp(items->data, "path")); 1953ef7ff83SDavid Woodhouse g_assert(items->next); 1963ef7ff83SDavid Woodhouse g_assert(!strcmp(items->next->data, "path2")); 1973ef7ff83SDavid Woodhouse g_assert(!items->next->next); 1983ef7ff83SDavid Woodhouse g_list_free_full(items, g_free); 1993ef7ff83SDavid Woodhouse 2006e133009SDavid Woodhouse err = xs_impl_unwatch(s, DOMID_GUEST, "some", "guestwatch", 2016e133009SDavid Woodhouse watch_cb, guest_watches); 2026e133009SDavid Woodhouse g_assert(!err); 2036e133009SDavid Woodhouse 2046e133009SDavid Woodhouse err = xs_impl_unwatch(s, DOMID_GUEST, "some", "guestwatch", 2056e133009SDavid Woodhouse watch_cb, guest_watches); 2066e133009SDavid Woodhouse g_assert(err == ENOENT); 2076e133009SDavid Woodhouse 2086e133009SDavid Woodhouse err = xs_impl_watch(s, DOMID_GUEST, "some/relative/path2", "watchp2", 2096e133009SDavid Woodhouse watch_cb, guest_watches); 2106e133009SDavid Woodhouse g_assert(!err); 2116e133009SDavid Woodhouse g_assert(guest_watches->len == strlen("some/relative/path2watchp2")); 2126e133009SDavid Woodhouse g_assert(!strcmp(guest_watches->str, "some/relative/path2watchp2")); 2136e133009SDavid Woodhouse g_string_truncate(guest_watches, 0); 2146e133009SDavid Woodhouse 2156e133009SDavid Woodhouse err = xs_impl_watch(s, DOMID_GUEST, "/local/domain/1/some/relative", 2166e133009SDavid Woodhouse "watchrel", watch_cb, guest_watches); 2176e133009SDavid Woodhouse g_assert(!err); 2186e133009SDavid Woodhouse g_assert(guest_watches->len == 2196e133009SDavid Woodhouse strlen("/local/domain/1/some/relativewatchrel")); 2206e133009SDavid Woodhouse g_assert(!strcmp(guest_watches->str, 2216e133009SDavid Woodhouse "/local/domain/1/some/relativewatchrel")); 2226e133009SDavid Woodhouse g_string_truncate(guest_watches, 0); 2236e133009SDavid Woodhouse 2243ef7ff83SDavid Woodhouse /* Write somewhere else which already existed */ 2253ef7ff83SDavid Woodhouse err = write_str(s, DOMID_GUEST, XBT_NULL, "some/relative", "moredata"); 2263ef7ff83SDavid Woodhouse g_assert(!err); 2276e133009SDavid Woodhouse g_assert(s->nr_nodes == 8); 2286e133009SDavid Woodhouse 2296e133009SDavid Woodhouse g_assert(!strcmp(guest_watches->str, 2306e133009SDavid Woodhouse "/local/domain/1/some/relativewatchrel")); 2316e133009SDavid Woodhouse g_string_truncate(guest_watches, 0); 2323ef7ff83SDavid Woodhouse 2333ef7ff83SDavid Woodhouse g_byte_array_set_size(data, 0); 2343ef7ff83SDavid Woodhouse err = xs_impl_read(s, DOMID_GUEST, XBT_NULL, "some/relative", data); 2353ef7ff83SDavid Woodhouse g_assert(!err); 2363ef7ff83SDavid Woodhouse g_assert(data->len == strlen("moredata")); 2373ef7ff83SDavid Woodhouse g_assert(!memcmp(data->data, "moredata", data->len)); 2383ef7ff83SDavid Woodhouse 2393ef7ff83SDavid Woodhouse /* Overwrite existing data */ 2403ef7ff83SDavid Woodhouse err = write_str(s, DOMID_GUEST, XBT_NULL, "some/relative", "otherdata"); 2413ef7ff83SDavid Woodhouse g_assert(!err); 2426e133009SDavid Woodhouse g_string_truncate(guest_watches, 0); 2433ef7ff83SDavid Woodhouse 2443ef7ff83SDavid Woodhouse g_byte_array_set_size(data, 0); 2453ef7ff83SDavid Woodhouse err = xs_impl_read(s, DOMID_GUEST, XBT_NULL, "some/relative", data); 2463ef7ff83SDavid Woodhouse g_assert(!err); 2473ef7ff83SDavid Woodhouse g_assert(data->len == strlen("otherdata")); 2483ef7ff83SDavid Woodhouse g_assert(!memcmp(data->data, "otherdata", data->len)); 2493ef7ff83SDavid Woodhouse 2503ef7ff83SDavid Woodhouse /* Remove the subtree */ 2513ef7ff83SDavid Woodhouse err = xs_impl_rm(s, DOMID_GUEST, XBT_NULL, "some/relative"); 2523ef7ff83SDavid Woodhouse g_assert(!err); 2533ef7ff83SDavid Woodhouse g_assert(s->nr_nodes == 5); 2543ef7ff83SDavid Woodhouse 2556e133009SDavid Woodhouse /* Each watch fires with the least specific relevant path */ 2566e133009SDavid Woodhouse g_assert(strstr(guest_watches->str, 2576e133009SDavid Woodhouse "some/relative/path2watchp2")); 2586e133009SDavid Woodhouse g_assert(strstr(guest_watches->str, 2596e133009SDavid Woodhouse "/local/domain/1/some/relativewatchrel")); 2606e133009SDavid Woodhouse g_string_truncate(guest_watches, 0); 2616e133009SDavid Woodhouse 2623ef7ff83SDavid Woodhouse g_byte_array_set_size(data, 0); 2633ef7ff83SDavid Woodhouse err = xs_impl_read(s, DOMID_GUEST, XBT_NULL, "some/relative", data); 2643ef7ff83SDavid Woodhouse g_assert(err == ENOENT); 2653ef7ff83SDavid Woodhouse g_byte_array_unref(data); 2663ef7ff83SDavid Woodhouse 2676e133009SDavid Woodhouse xs_impl_reset_watches(s, DOMID_GUEST); 2686e133009SDavid Woodhouse g_string_free(qemu_watches, true); 2696e133009SDavid Woodhouse g_string_free(guest_watches, true); 2703ef7ff83SDavid Woodhouse xs_node_unref(old_root); 2713ef7ff83SDavid Woodhouse xs_impl_delete(s); 2723ef7ff83SDavid Woodhouse } 2733ef7ff83SDavid Woodhouse 2743ef7ff83SDavid Woodhouse 275*7248b87cSDavid Woodhouse static void do_test_xs_node_tx(bool fail, bool commit) 276*7248b87cSDavid Woodhouse { 277*7248b87cSDavid Woodhouse XenstoreImplState *s = setup(); 278*7248b87cSDavid Woodhouse GString *watches = g_string_new(NULL); 279*7248b87cSDavid Woodhouse GByteArray *data = g_byte_array_new(); 280*7248b87cSDavid Woodhouse unsigned int tx_id = XBT_NULL; 281*7248b87cSDavid Woodhouse int err; 282*7248b87cSDavid Woodhouse 283*7248b87cSDavid Woodhouse g_assert(s); 284*7248b87cSDavid Woodhouse 285*7248b87cSDavid Woodhouse /* Set a watch */ 286*7248b87cSDavid Woodhouse err = xs_impl_watch(s, DOMID_GUEST, "some", "watch", 287*7248b87cSDavid Woodhouse watch_cb, watches); 288*7248b87cSDavid Woodhouse g_assert(!err); 289*7248b87cSDavid Woodhouse g_assert(watches->len == strlen("somewatch")); 290*7248b87cSDavid Woodhouse g_assert(!strcmp(watches->str, "somewatch")); 291*7248b87cSDavid Woodhouse g_string_truncate(watches, 0); 292*7248b87cSDavid Woodhouse 293*7248b87cSDavid Woodhouse /* Write something */ 294*7248b87cSDavid Woodhouse err = write_str(s, DOMID_GUEST, XBT_NULL, "some/relative/path", 295*7248b87cSDavid Woodhouse "something"); 296*7248b87cSDavid Woodhouse g_assert(s->nr_nodes == 7); 297*7248b87cSDavid Woodhouse g_assert(!err); 298*7248b87cSDavid Woodhouse g_assert(!strcmp(watches->str, 299*7248b87cSDavid Woodhouse "some/relative/pathwatch")); 300*7248b87cSDavid Woodhouse g_string_truncate(watches, 0); 301*7248b87cSDavid Woodhouse 302*7248b87cSDavid Woodhouse /* Create a transaction */ 303*7248b87cSDavid Woodhouse err = xs_impl_transaction_start(s, DOMID_GUEST, &tx_id); 304*7248b87cSDavid Woodhouse g_assert(!err); 305*7248b87cSDavid Woodhouse 306*7248b87cSDavid Woodhouse if (fail) { 307*7248b87cSDavid Woodhouse /* Write something else in the root */ 308*7248b87cSDavid Woodhouse err = write_str(s, DOMID_GUEST, XBT_NULL, "some/relative/path", 309*7248b87cSDavid Woodhouse "another thing"); 310*7248b87cSDavid Woodhouse g_assert(!err); 311*7248b87cSDavid Woodhouse g_assert(s->nr_nodes == 7); 312*7248b87cSDavid Woodhouse g_assert(!strcmp(watches->str, 313*7248b87cSDavid Woodhouse "some/relative/pathwatch")); 314*7248b87cSDavid Woodhouse g_string_truncate(watches, 0); 315*7248b87cSDavid Woodhouse } 316*7248b87cSDavid Woodhouse 317*7248b87cSDavid Woodhouse g_assert(!watches->len); 318*7248b87cSDavid Woodhouse 319*7248b87cSDavid Woodhouse /* Perform a write in the transaction */ 320*7248b87cSDavid Woodhouse err = write_str(s, DOMID_GUEST, tx_id, "some/relative/path", 321*7248b87cSDavid Woodhouse "something else"); 322*7248b87cSDavid Woodhouse g_assert(!err); 323*7248b87cSDavid Woodhouse g_assert(s->nr_nodes == 7); 324*7248b87cSDavid Woodhouse g_assert(!watches->len); 325*7248b87cSDavid Woodhouse 326*7248b87cSDavid Woodhouse err = xs_impl_read(s, DOMID_GUEST, XBT_NULL, "some/relative/path", data); 327*7248b87cSDavid Woodhouse g_assert(!err); 328*7248b87cSDavid Woodhouse if (fail) { 329*7248b87cSDavid Woodhouse g_assert(data->len == strlen("another thing")); 330*7248b87cSDavid Woodhouse g_assert(!memcmp(data->data, "another thing", data->len)); 331*7248b87cSDavid Woodhouse } else { 332*7248b87cSDavid Woodhouse g_assert(data->len == strlen("something")); 333*7248b87cSDavid Woodhouse g_assert(!memcmp(data->data, "something", data->len)); 334*7248b87cSDavid Woodhouse } 335*7248b87cSDavid Woodhouse g_byte_array_set_size(data, 0); 336*7248b87cSDavid Woodhouse 337*7248b87cSDavid Woodhouse err = xs_impl_read(s, DOMID_GUEST, tx_id, "some/relative/path", data); 338*7248b87cSDavid Woodhouse g_assert(!err); 339*7248b87cSDavid Woodhouse g_assert(data->len == strlen("something else")); 340*7248b87cSDavid Woodhouse g_assert(!memcmp(data->data, "something else", data->len)); 341*7248b87cSDavid Woodhouse g_byte_array_set_size(data, 0); 342*7248b87cSDavid Woodhouse 343*7248b87cSDavid Woodhouse /* Attempt to commit the transaction */ 344*7248b87cSDavid Woodhouse err = xs_impl_transaction_end(s, DOMID_GUEST, tx_id, commit); 345*7248b87cSDavid Woodhouse if (commit && fail) { 346*7248b87cSDavid Woodhouse g_assert(err == EAGAIN); 347*7248b87cSDavid Woodhouse } else { 348*7248b87cSDavid Woodhouse g_assert(!err); 349*7248b87cSDavid Woodhouse } 350*7248b87cSDavid Woodhouse g_assert(!watches->len); 351*7248b87cSDavid Woodhouse g_assert(s->nr_nodes == 7); 352*7248b87cSDavid Woodhouse 353*7248b87cSDavid Woodhouse err = xs_impl_unwatch(s, DOMID_GUEST, "some", "watch", 354*7248b87cSDavid Woodhouse watch_cb, watches); 355*7248b87cSDavid Woodhouse g_assert(!err); 356*7248b87cSDavid Woodhouse 357*7248b87cSDavid Woodhouse err = xs_impl_read(s, DOMID_GUEST, XBT_NULL, "some/relative/path", data); 358*7248b87cSDavid Woodhouse g_assert(!err); 359*7248b87cSDavid Woodhouse if (fail) { 360*7248b87cSDavid Woodhouse g_assert(data->len == strlen("another thing")); 361*7248b87cSDavid Woodhouse g_assert(!memcmp(data->data, "another thing", data->len)); 362*7248b87cSDavid Woodhouse } else if (commit) { 363*7248b87cSDavid Woodhouse g_assert(data->len == strlen("something else")); 364*7248b87cSDavid Woodhouse g_assert(!memcmp(data->data, "something else", data->len)); 365*7248b87cSDavid Woodhouse } else { 366*7248b87cSDavid Woodhouse g_assert(data->len == strlen("something")); 367*7248b87cSDavid Woodhouse g_assert(!memcmp(data->data, "something", data->len)); 368*7248b87cSDavid Woodhouse } 369*7248b87cSDavid Woodhouse g_byte_array_unref(data); 370*7248b87cSDavid Woodhouse g_string_free(watches, true); 371*7248b87cSDavid Woodhouse xs_impl_delete(s); 372*7248b87cSDavid Woodhouse } 373*7248b87cSDavid Woodhouse 374*7248b87cSDavid Woodhouse static void test_xs_node_tx_fail(void) 375*7248b87cSDavid Woodhouse { 376*7248b87cSDavid Woodhouse do_test_xs_node_tx(true, true); 377*7248b87cSDavid Woodhouse } 378*7248b87cSDavid Woodhouse 379*7248b87cSDavid Woodhouse static void test_xs_node_tx_abort(void) 380*7248b87cSDavid Woodhouse { 381*7248b87cSDavid Woodhouse do_test_xs_node_tx(false, false); 382*7248b87cSDavid Woodhouse do_test_xs_node_tx(true, false); 383*7248b87cSDavid Woodhouse } 384*7248b87cSDavid Woodhouse static void test_xs_node_tx_succeed(void) 385*7248b87cSDavid Woodhouse { 386*7248b87cSDavid Woodhouse do_test_xs_node_tx(false, true); 387*7248b87cSDavid Woodhouse } 388*7248b87cSDavid Woodhouse 3893ef7ff83SDavid Woodhouse int main(int argc, char **argv) 3903ef7ff83SDavid Woodhouse { 3913ef7ff83SDavid Woodhouse g_test_init(&argc, &argv, NULL); 3923ef7ff83SDavid Woodhouse module_call_init(MODULE_INIT_QOM); 3933ef7ff83SDavid Woodhouse 3943ef7ff83SDavid Woodhouse g_test_add_func("/xs_node/simple", test_xs_node_simple); 395*7248b87cSDavid Woodhouse g_test_add_func("/xs_node/tx_abort", test_xs_node_tx_abort); 396*7248b87cSDavid Woodhouse g_test_add_func("/xs_node/tx_fail", test_xs_node_tx_fail); 397*7248b87cSDavid Woodhouse g_test_add_func("/xs_node/tx_succeed", test_xs_node_tx_succeed); 3983ef7ff83SDavid Woodhouse 3993ef7ff83SDavid Woodhouse return g_test_run(); 4003ef7ff83SDavid Woodhouse } 401