1 /*
2  * Copyright © 2012-2020 Inria.  All rights reserved.
3  * See COPYING in top-level directory.
4  */
5 
6 #include "private/autogen/config.h" /* for HWLOC_WIN_SYS */
7 #include "hwloc.h"
8 
9 #include <stdlib.h>
10 #include <stdio.h>
11 #ifdef HAVE_UNISTD_H
12 #include <unistd.h>
13 #endif
14 #include <string.h>
15 #include <errno.h>
16 #include <assert.h>
17 
18 #ifndef HAVE_MKSTEMP
19 #include <fcntl.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include "private/misc.h" /* for S_IRWXU */
mkstemp(char * name)23 static inline int mkstemp(char *name)
24 {
25   mktemp(name);
26   return open(name, O_RDWR|O_CREAT, S_IRWXU);
27 }
28 #endif
29 
30 /* mostly useful with valgrind, to check if backend cleanup properly */
31 
get_backend_name(hwloc_topology_t topo)32 static const char *get_backend_name(hwloc_topology_t topo)
33 {
34   hwloc_obj_t root = hwloc_get_root_obj(topo);
35   return hwloc_obj_get_info_by_name(root, "Backend");
36 }
37 
assert_backend_name(hwloc_topology_t topo,const char * wanted)38 static void assert_backend_name(hwloc_topology_t topo, const char *wanted)
39 {
40   const char *found = get_backend_name(topo);
41   int diff;
42   assert(found);
43   diff = strcmp(found, wanted);
44   assert(!diff);
45 }
46 
assert_foo_bar(hwloc_topology_t topo,int setornot)47 static void assert_foo_bar(hwloc_topology_t topo, int setornot)
48 {
49   hwloc_obj_t root = hwloc_get_root_obj(topo);
50   const char *found = hwloc_obj_get_info_by_name(root, "Foo");
51   if (!setornot) {
52     assert(!found);
53   } else {
54     int diff;
55     assert(found);
56     diff = strcmp(found, "Bar");
57     assert(!diff);
58   }
59 }
60 
main(void)61 int main(void)
62 {
63   hwloc_topology_t topology1, topology2;
64   char *xmlbuf;
65   int xmlbuflen;
66   char xmlfile[] = "hwloc_backends.tmpxml.XXXXXX";
67   char env[64];
68   int xmlbufok = 0, xmlfileok = 0, xmlfilefd;
69   const char *orig_backend_name;
70   int err;
71 
72   putenv((char *) "HWLOC_LIBXML_CLEANUP=1");
73 
74   printf("trying to export topology to XML buffer and file for later...\n");
75   hwloc_topology_init(&topology1);
76   hwloc_topology_load(topology1);
77   orig_backend_name = get_backend_name(topology1);
78   hwloc_obj_add_info(hwloc_get_root_obj(topology1), "Foo", "Bar");
79   assert(hwloc_topology_is_thissystem(topology1));
80   if (hwloc_topology_export_xmlbuffer(topology1, &xmlbuf, &xmlbuflen, 0) < 0)
81     printf("XML buffer export failed (%s), ignoring\n", strerror(errno));
82   else
83     xmlbufok = 1;
84   xmlfilefd = mkstemp(xmlfile);
85   if (xmlfilefd < 0 || hwloc_topology_export_xml(topology1, xmlfile, 0) < 0)
86     printf("XML file export failed (%s), ignoring\n", strerror(errno));
87   else
88     xmlfileok = 1;
89 
90 
91   /* init+config+destroy without loading */
92   printf("init...\n");
93   hwloc_topology_init(&topology2);
94   if (xmlfileok) {
95     printf("switching to xml...\n");
96     assert(!hwloc_topology_set_xml(topology2, xmlfile));
97   }
98   if (xmlbufok) {
99     printf("switching to xmlbuffer...\n");
100     assert(!hwloc_topology_set_xmlbuffer(topology2, xmlbuf, xmlbuflen));
101   }
102   printf("switching to synthetic...\n");
103   hwloc_topology_set_synthetic(topology2, "pack:2 node:3 l1:2 pu:4");
104   hwloc_topology_destroy(topology2);
105 
106   /* init+xml+load+destroy */
107   if (xmlfileok) {
108     printf("switching to xml and loading...\n");
109     hwloc_topology_init(&topology2);
110     assert(!hwloc_topology_set_xml(topology2, xmlfile));
111     hwloc_topology_load(topology2);
112     assert_backend_name(topology2, orig_backend_name);
113     assert_foo_bar(topology2, 1);
114     hwloc_topology_check(topology2);
115     assert(!hwloc_topology_is_thissystem(topology2));
116     hwloc_topology_destroy(topology2);
117   }
118 
119   /* init+xmlbuf+load+destroy */
120   if (xmlbufok) {
121     printf("switching to xmlbuffer and loading...\n");
122     hwloc_topology_init(&topology2);
123     assert(!hwloc_topology_set_xmlbuffer(topology2, xmlbuf, xmlbuflen));
124     hwloc_topology_load(topology2);
125     assert_backend_name(topology2, orig_backend_name);
126     assert_foo_bar(topology2, 1);
127     hwloc_topology_check(topology2);
128     assert(!hwloc_topology_is_thissystem(topology2));
129     hwloc_topology_destroy(topology2);
130   }
131 
132   /* init+synthetic+load+destroy */
133   printf("switching to synthetic and loading...\n");
134   hwloc_topology_init(&topology2);
135   hwloc_topology_set_synthetic(topology2, "pack:2 node:3 l3i:2 pu:4");
136   hwloc_topology_load(topology2);
137   assert_backend_name(topology2, "Synthetic");
138   assert_foo_bar(topology2, 0);
139   assert(hwloc_get_nbobjs_by_type(topology2, HWLOC_OBJ_PU) == 2*3*2*4);
140   hwloc_topology_check(topology2);
141   assert(!hwloc_topology_is_thissystem(topology2));
142   hwloc_topology_destroy(topology2);
143 
144   /* xmlenv+init+load+destroy */
145   if (xmlfileok) {
146     printf("switching to xml by env and loading...\n");
147     snprintf(env, sizeof(env), "HWLOC_XMLFILE=%s", xmlfile);
148     putenv(env);
149     hwloc_topology_init(&topology2);
150     hwloc_topology_load(topology2);
151     assert_backend_name(topology2, orig_backend_name);
152     assert_foo_bar(topology2, 1);
153     hwloc_topology_check(topology2);
154     assert(!hwloc_topology_is_thissystem(topology2));
155     hwloc_topology_destroy(topology2);
156   }
157 
158   /* syntheticenv+init+load+destroy, synthetic env overrides xml */
159   printf("switching to synthetic by env and loading...\n");
160   putenv((char *) "HWLOC_SYNTHETIC=node:3 pu:3");
161   hwloc_topology_init(&topology2);
162   hwloc_topology_load(topology2);
163   assert_backend_name(topology2, "Synthetic");
164   assert_foo_bar(topology2, 0);
165   assert(hwloc_get_nbobjs_by_type(topology2, HWLOC_OBJ_PU) == 3*3);
166   hwloc_topology_check(topology2);
167   assert(!hwloc_topology_is_thissystem(topology2));
168   hwloc_topology_destroy(topology2);
169 
170   /* componentsenv+init+load+destroy for testing defaults, overrides synthetic/xml/fsroot envs */
171   printf("switching to default components by env and loading...\n");
172   putenv((char *) "HWLOC_COMPONENTS=,"); /* don't set to empty since it means 'unset' on windows */
173   hwloc_topology_init(&topology2);
174   hwloc_topology_load(topology2);
175   assert_backend_name(topology2, orig_backend_name);
176   assert_foo_bar(topology2, 0);
177   hwloc_topology_check(topology2);
178   assert(hwloc_topology_is_thissystem(topology2));
179   hwloc_topology_destroy(topology2);
180 
181   if (xmlbufok)
182     hwloc_free_xmlbuffer(topology1, xmlbuf);
183   if (xmlfilefd >= 0) {
184     unlink(xmlfile);
185     close(xmlfilefd);
186   }
187   hwloc_topology_destroy(topology1);
188 
189   /* blacklist everything but noos with hwloc_topology_set_components() */
190   printf("disabling everything but noos with hwloc_topology_set_components()\n");
191   putenv((char *) "HWLOC_COMPONENTS="); /* means 'unset' on windows, which means HWLOC_XMLFILE and HWLOC_SYNTHETIC
192 				* would be processed if not empty, so clear them too. */
193   putenv((char *) "HWLOC_XMLFILE=");
194   putenv((char *) "HWLOC_SYNTHETIC=");
195   hwloc_topology_init(&topology1);
196   err = hwloc_topology_set_components(topology1, HWLOC_TOPOLOGY_COMPONENTS_FLAG_BLACKLIST, "foobar");
197   assert(err == -1);
198   assert(errno == EINVAL);
199   err = hwloc_topology_set_components(topology1, ~HWLOC_TOPOLOGY_COMPONENTS_FLAG_BLACKLIST, "synthetic");
200   assert(err == -1);
201   assert(errno == EINVAL);
202   err = hwloc_topology_set_components(topology1, HWLOC_TOPOLOGY_COMPONENTS_FLAG_BLACKLIST, "synthetic");
203   assert(!err);
204   err = hwloc_topology_set_components(topology1, HWLOC_TOPOLOGY_COMPONENTS_FLAG_BLACKLIST, "xml");
205   assert(!err);
206   err = hwloc_topology_set_components(topology1, HWLOC_TOPOLOGY_COMPONENTS_FLAG_BLACKLIST, "x86");
207 #ifdef HWLOC_HAVE_X86_CPUID
208   assert(!err);
209 #else
210   assert(err == -1);
211   assert(errno == EINVAL);
212 #endif
213 #ifdef HWLOC_LINUX_SYS
214   err = hwloc_topology_set_components(topology1, HWLOC_TOPOLOGY_COMPONENTS_FLAG_BLACKLIST, "linux:0xf");
215   assert(!err);
216   err = hwloc_topology_set_components(topology1, HWLOC_TOPOLOGY_COMPONENTS_FLAG_BLACKLIST, "linux:0xfffffff0");
217   assert(!err);
218 #endif
219 #ifdef HWLOC_BGQ_SYS
220   err = hwloc_topology_set_components(topology1, HWLOC_TOPOLOGY_COMPONENTS_FLAG_BLACKLIST, "bgq");
221   assert(!err);
222 #endif
223 #ifdef HWLOC_DARWIN_SYS
224   err = hwloc_topology_set_components(topology1, HWLOC_TOPOLOGY_COMPONENTS_FLAG_BLACKLIST, "darwin");
225   assert(!err);
226 #endif
227 #ifdef HWLOC_SOLARIS_SYS
228   err = hwloc_topology_set_components(topology1, HWLOC_TOPOLOGY_COMPONENTS_FLAG_BLACKLIST, "solaris");
229   assert(!err);
230 #endif
231 #ifdef HWLOC_AIX_SYS
232   err = hwloc_topology_set_components(topology1, HWLOC_TOPOLOGY_COMPONENTS_FLAG_BLACKLIST, "aix");
233   assert(!err);
234 #endif
235 #ifdef HWLOC_HPUX_SYS
236   err = hwloc_topology_set_components(topology1, HWLOC_TOPOLOGY_COMPONENTS_FLAG_BLACKLIST, "hpux");
237   assert(!err);
238 #endif
239 #ifdef HWLOC_WIN_SYS
240   err = hwloc_topology_set_components(topology1, HWLOC_TOPOLOGY_COMPONENTS_FLAG_BLACKLIST, "windows");
241   assert(!err);
242 #endif
243 #ifdef HWLOC_FREEBSD_SYS
244   err = hwloc_topology_set_components(topology1, HWLOC_TOPOLOGY_COMPONENTS_FLAG_BLACKLIST, "freebsd");
245   assert(!err);
246 #endif
247 #ifdef HWLOC_NETBSD_SYS
248   err = hwloc_topology_set_components(topology1, HWLOC_TOPOLOGY_COMPONENTS_FLAG_BLACKLIST, "netbsd");
249   assert(!err);
250 #endif
251   hwloc_topology_load(topology1);
252   assert(!get_backend_name(topology1)); /* noos doesn't put any Backend info attr */
253   hwloc_topology_check(topology1);
254   assert(hwloc_topology_is_thissystem(topology1));
255   hwloc_topology_destroy(topology1);
256 
257   return 0;
258 }
259