1 /*
2 * Copyright © 2013-2020 Inria. All rights reserved.
3 * See COPYING in top-level directory.
4 */
5
6 #include "hwloc.h"
7
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <assert.h>
12
main(void)13 int main(void)
14 {
15 hwloc_topology_t topo1, topo2, topo3;
16 hwloc_topology_diff_t diff, diff2, tmpdiff;
17 hwloc_obj_t obj;
18 char *xmlbuffer;
19 int xmlbuflen;
20 char *refname;
21 int err;
22
23 putenv((char *) "HWLOC_LIBXML_CLEANUP=1");
24
25 hwloc_topology_init(&topo1);
26 hwloc_topology_load(topo1);
27 printf("duplicate topo1 into topo2\n");
28 hwloc_topology_dup(&topo2, topo1);
29
30 printf("check that topo2 is identical\n");
31 err = hwloc_topology_diff_build(topo1, topo2, 0, &diff);
32 assert(err == 0);
33 assert(!diff);
34
35 printf("add a new info to topo2 root\n");
36 obj = hwloc_get_root_obj(topo1);
37 hwloc_obj_add_info(obj, "Foo", "Bar");
38 printf("check that topo2 cannot be diff'ed from topo1\n");
39 err = hwloc_topology_diff_build(topo1, topo2, 0, &diff);
40 assert(err == 1);
41 assert(diff->generic.type == HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX);
42 assert(diff->generic.next == NULL);
43 assert(diff->too_complex.obj_depth == 0);
44 assert(diff->too_complex.obj_index == 0);
45 hwloc_topology_diff_destroy(diff);
46
47 printf("add a similar info to topo1, and change memory size of first NUMA\n");
48 obj = hwloc_get_root_obj(topo2);
49 hwloc_obj_add_info(obj, "Foo", "Bar2");
50
51 obj = hwloc_get_obj_by_type(topo2, HWLOC_OBJ_NUMANODE, 0);
52 obj->attr->numanode.local_memory += 32*4096;
53
54 printf("check that topo2 is now properly diff'ed\n");
55 err = hwloc_topology_diff_build(topo1, topo2, 0, &diff);
56 assert(err == 0);
57 tmpdiff = diff;
58 assert(tmpdiff->generic.type == HWLOC_TOPOLOGY_DIFF_OBJ_ATTR);
59 assert(tmpdiff->obj_attr.obj_depth == 0);
60 assert(tmpdiff->obj_attr.obj_index == 0);
61 assert(tmpdiff->obj_attr.diff.generic.type == HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO);
62 err = strcmp(tmpdiff->obj_attr.diff.string.name, "Foo");
63 assert(!err);
64 err = strcmp(tmpdiff->obj_attr.diff.string.oldvalue, "Bar");
65 assert(!err);
66 err = strcmp(tmpdiff->obj_attr.diff.string.newvalue, "Bar2");
67 assert(!err);
68 tmpdiff = tmpdiff->generic.next;
69 assert(tmpdiff->generic.type == HWLOC_TOPOLOGY_DIFF_OBJ_ATTR);
70 assert(tmpdiff->obj_attr.obj_depth == hwloc_get_type_depth(topo1, HWLOC_OBJ_NUMANODE));
71 assert(tmpdiff->obj_attr.obj_index == 0);
72 assert(tmpdiff->obj_attr.diff.generic.type == HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_SIZE);
73 assert(tmpdiff->obj_attr.diff.uint64.newvalue - tmpdiff->obj_attr.diff.uint64.oldvalue == 32*4096);
74 assert(tmpdiff->generic.next == NULL);
75
76 printf("apply the diff to new duplicate topo3 of topo1\n");
77 hwloc_topology_dup(&topo3, topo1);
78 err = hwloc_topology_diff_apply(topo3, diff, 0);
79 assert(!err);
80 printf("check that topo2 and topo3 are identical\n");
81 err = hwloc_topology_diff_build(topo2, topo3, 0, &diff2);
82 assert(err == 0);
83 assert(!diff2);
84
85 printf("apply the reverse diff to topo2\n");
86 err = hwloc_topology_diff_apply(topo2, diff, HWLOC_TOPOLOGY_DIFF_APPLY_REVERSE);
87 assert(!err);
88 printf("check that topo2 and topo1 are identical\n");
89 err = hwloc_topology_diff_build(topo1, topo2, 0, &diff2);
90 assert(err == 0);
91 assert(!diff2);
92
93 printf("exporting and reloading diff from XML buffer without refname\n");
94 err = hwloc_topology_diff_export_xmlbuffer(diff, NULL, &xmlbuffer, &xmlbuflen);
95 assert(!err);
96 hwloc_topology_diff_destroy(diff);
97 err = hwloc_topology_diff_load_xmlbuffer(xmlbuffer, xmlbuflen, &diff2, &refname);
98 assert(!err);
99 assert(diff2);
100 assert(!refname);
101 assert(!err);
102 hwloc_free_xmlbuffer(topo1, xmlbuffer);
103
104 printf("exporting and reloading diff from XML buffer with refname\n");
105 err = hwloc_topology_diff_export_xmlbuffer(diff2, "foobar", &xmlbuffer, &xmlbuflen);
106 assert(!err);
107 hwloc_topology_diff_destroy(diff2);
108 err = hwloc_topology_diff_load_xmlbuffer(xmlbuffer, xmlbuflen, &diff, &refname);
109 assert(!err);
110 assert(diff);
111 err = strcmp(refname, "foobar");
112 assert(!err);
113 free(refname);
114 hwloc_free_xmlbuffer(topo1, xmlbuffer);
115
116 tmpdiff = diff;
117 assert(tmpdiff->generic.type == HWLOC_TOPOLOGY_DIFF_OBJ_ATTR);
118 assert(tmpdiff->obj_attr.obj_depth == 0);
119 assert(tmpdiff->obj_attr.obj_index == 0);
120 assert(tmpdiff->obj_attr.diff.generic.type == HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO);
121 err = strcmp(tmpdiff->obj_attr.diff.string.name, "Foo");
122 assert(!err);
123 err = strcmp(tmpdiff->obj_attr.diff.string.oldvalue, "Bar");
124 assert(!err);
125 err = strcmp(tmpdiff->obj_attr.diff.string.newvalue, "Bar2");
126 assert(!err);
127 tmpdiff = tmpdiff->generic.next;
128 assert(tmpdiff->generic.type == HWLOC_TOPOLOGY_DIFF_OBJ_ATTR);
129 assert(tmpdiff->obj_attr.obj_depth == hwloc_get_type_depth(topo1, HWLOC_OBJ_NUMANODE));
130 assert(tmpdiff->obj_attr.obj_index == 0);
131 assert(tmpdiff->obj_attr.diff.generic.type == HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_SIZE);
132 assert(tmpdiff->obj_attr.diff.uint64.newvalue - tmpdiff->obj_attr.diff.uint64.oldvalue == 32*4096);
133 assert(tmpdiff->generic.next == NULL);
134
135 printf("reapplying to topo2\n");
136 err = hwloc_topology_diff_apply(topo2, diff, 0);
137 assert(!err);
138 printf("check that topo2 and topo3 are again identical\n");
139 err = hwloc_topology_diff_build(topo2, topo3, 0, &diff2);
140 assert(err == 0);
141 assert(!diff2);
142
143 hwloc_topology_diff_destroy(diff);
144
145 printf("adding new key to the bottom of topo3 on first PU\n");
146 obj = hwloc_get_obj_by_type(topo3, HWLOC_OBJ_PU, 0);
147 assert(obj);
148 hwloc_obj_add_info(obj, "Bar", "Baz3");
149
150 printf("check that diff fails at the 2nd or 3rd entry\n");
151 err = hwloc_topology_diff_build(topo1, topo3, 0, &diff);
152 assert(err == 1);
153 assert(diff);
154 tmpdiff = diff;
155 assert(tmpdiff->generic.type == HWLOC_TOPOLOGY_DIFF_OBJ_ATTR);
156 tmpdiff = tmpdiff->generic.next;
157 if (tmpdiff->generic.type == HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX) {
158 /* normal case, PU appears before NUMA, we get ATTR(root)+TOO_COMPLEX(pu)+ATTR(numa) */
159 tmpdiff = tmpdiff->generic.next;
160 assert(tmpdiff->generic.type == HWLOC_TOPOLOGY_DIFF_OBJ_ATTR);
161 assert(tmpdiff->generic.next == NULL);
162 } else if (tmpdiff->generic.type == HWLOC_TOPOLOGY_DIFF_OBJ_ATTR) {
163 /* unusual case, PU appears after NUMA (first NUMA is CPUless), we get ATTR(root)+ATTR(numa)+TOO_COMPLEX(pu) */
164 tmpdiff = tmpdiff->generic.next;
165 assert(tmpdiff->generic.type == HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX);
166 assert(tmpdiff->generic.next == NULL);
167 } else {
168 assert(0);
169 }
170 hwloc_topology_diff_destroy(diff);
171
172 printf("adding similar key to topo1\n");
173 obj = hwloc_get_obj_by_type(topo1, HWLOC_OBJ_PU, 0);
174 assert(obj);
175 hwloc_obj_add_info(obj, "Bar", "Baz1");
176 printf("checking that topo3 diff fails to reverse apply to topo2\n");
177 err = hwloc_topology_diff_build(topo1, topo3, 0, &diff);
178 assert(err == 0);
179 assert(diff);
180 err = hwloc_topology_diff_apply(topo2, diff, HWLOC_TOPOLOGY_DIFF_APPLY_REVERSE);
181 assert(err == -2 || err == -3);
182 hwloc_topology_diff_destroy(diff);
183
184 hwloc_topology_destroy(topo3);
185 hwloc_topology_destroy(topo2);
186 hwloc_topology_destroy(topo1);
187
188 return 0;
189 }
190