inetmib1/tests: Fix duplicate expressions in if condition.
[wine] / dlls / inetmib1 / tests / main.c
1 /*
2  * Copyright 2008 Juan Lang
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 #include <stdio.h>
19 #include <stdarg.h>
20 #include <windef.h>
21 #include <winbase.h>
22 #include <snmp.h>
23
24 #include "wine/test.h"
25
26 static HMODULE inetmib1;
27
28 static void testInit(void)
29 {
30     BOOL (WINAPI *pInit)(DWORD, HANDLE *, AsnObjectIdentifier *);
31     BOOL ret;
32     HANDLE event;
33     AsnObjectIdentifier oid;
34
35     pInit = (void *)GetProcAddress(inetmib1, "SnmpExtensionInit");
36     if (!pInit)
37     {
38         win_skip("no SnmpExtensionInit\n");
39         return;
40     }
41     /* Crash
42     ret = pInit(0, NULL, NULL);
43     ret = pInit(0, NULL, &oid);
44     ret = pInit(0, &event, NULL);
45      */
46     ret = pInit(0, &event, &oid);
47     ok(ret, "SnmpExtensionInit failed: %d\n", GetLastError());
48     ok(!strcmp("1.3.6.1.2.1.1", SnmpUtilOidToA(&oid)),
49         "Expected 1.3.6.1.2.1.1, got %s\n", SnmpUtilOidToA(&oid));
50
51     SnmpUtilOidFree(&oid);
52 }
53
54 static void testQuery(void)
55 {
56     BOOL (WINAPI *pQuery)(BYTE, SnmpVarBindList *, AsnInteger32 *,
57         AsnInteger32 *);
58     BOOL ret, moreData, noChange;
59     SnmpVarBindList list;
60     AsnInteger32 error, index;
61     UINT bogus[] = { 1,2,3,4 };
62     UINT mib2System[] = { 1,3,6,1,2,1,1 };
63     UINT mib2If[] = { 1,3,6,1,2,1,2 };
64     UINT mib2IfTable[] = { 1,3,6,1,2,1,2,2 };
65     UINT mib2IfDescr[] = { 1,3,6,1,2,1,2,2,1,2 };
66     UINT mib2IfAdminStatus[] = { 1,3,6,1,2,1,2,2,1,7 };
67     UINT mib2IfOperStatus[] = { 1,3,6,1,2,1,2,2,1,8 };
68     UINT mib2IpAddr[] = { 1,3,6,1,2,1,4,20,1,1 };
69     UINT mib2IpRouteTable[] = { 1,3,6,1,2,1,4,21,1,1 };
70     UINT mib2UdpTable[] = { 1,3,6,1,2,1,7,5,1,1 };
71     SnmpVarBind vars[3], vars2[3], vars3[3];
72     UINT entry;
73
74     pQuery = (void *)GetProcAddress(inetmib1, "SnmpExtensionQuery");
75     if (!pQuery)
76     {
77         win_skip("couldn't find SnmpExtensionQuery\n");
78         return;
79     }
80     /* Crash
81     ret = pQuery(0, NULL, NULL, NULL);
82     ret = pQuery(0, NULL, &error, NULL);
83     ret = pQuery(0, NULL, NULL, &index);
84     ret = pQuery(0, &list, NULL, NULL);
85     ret = pQuery(0, &list, &error, NULL);
86      */
87
88     /* An empty list succeeds */
89     list.len = 0;
90     error = 0xdeadbeef;
91     index = 0xdeadbeef;
92     ret = pQuery(SNMP_PDU_GET, &list, &error, &index);
93     ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index);
94     ok(error == SNMP_ERRORSTATUS_NOERROR,
95         "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error);
96     ok(index == 0, "expected index 0, got %d\n", index);
97
98     /* Oddly enough, this "succeeds," even though the OID is clearly
99      * unsupported.
100      */
101     vars[0].name.idLength = sizeof(bogus) / sizeof(bogus[0]);
102     vars[0].name.ids = bogus;
103     vars[0].value.asnType = 0;
104     list.len = 1;
105     list.list = vars;
106     SetLastError(0xdeadbeef);
107     error = 0xdeadbeef;
108     index = 0xdeadbeef;
109     ret = pQuery(SNMP_PDU_GET, &list, &error, &index);
110     ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index);
111     ok(error == SNMP_ERRORSTATUS_NOERROR ||
112         error == ERROR_FILE_NOT_FOUND /* Win9x */,
113         "expected SNMP_ERRORSTATUS_NOERROR or ERROR_FILE_NOT_FOUND, got %d\n",
114         error);
115     if (error == SNMP_ERRORSTATUS_NOERROR)
116         ok(index == 0, "expected index 0, got %d\n", index);
117     else if (error == ERROR_FILE_NOT_FOUND)
118         ok(index == 1, "expected index 1, got %d\n", index);
119     /* The OID isn't changed either: */
120     ok(!strcmp("1.2.3.4", SnmpUtilOidToA(&vars[0].name)),
121         "expected 1.2.3.4, got %s\n", SnmpUtilOidToA(&vars[0].name));
122
123     /* The table is not an accessible variable, so it fails */
124     vars[0].name.idLength = sizeof(mib2IfTable) / sizeof(mib2IfTable[0]);
125     vars[0].name.ids = mib2IfTable;
126     SetLastError(0xdeadbeef);
127     error = 0xdeadbeef;
128     index = 0xdeadbeef;
129     ret = pQuery(SNMP_PDU_GET, &list, &error, &index);
130     ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index);
131     ok(error == SNMP_ERRORSTATUS_NOSUCHNAME,
132         "expected SNMP_ERRORSTATUS_NOSUCHNAME, got %d\n", error);
133     /* The index is 1-based rather than 0-based */
134     ok(index == 1, "expected index 1, got %d\n", index);
135
136     /* A Get fails on something that specifies a table (but not a particular
137      * entry in it)...
138      */
139     vars[0].name.idLength = sizeof(mib2IfDescr) / sizeof(mib2IfDescr[0]);
140     vars[0].name.ids = mib2IfDescr;
141     vars[1].name.idLength =
142         sizeof(mib2IfAdminStatus) / sizeof(mib2IfAdminStatus[0]);
143     vars[1].name.ids = mib2IfAdminStatus;
144     vars[2].name.idLength =
145         sizeof(mib2IfOperStatus) / sizeof(mib2IfOperStatus[0]);
146     vars[2].name.ids = mib2IfOperStatus;
147     list.len = 3;
148     SetLastError(0xdeadbeef);
149     error = 0xdeadbeef;
150     index = 0xdeadbeef;
151     ret = pQuery(SNMP_PDU_GET, &list, &error, &index);
152     ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index);
153     ok(error == SNMP_ERRORSTATUS_NOSUCHNAME,
154         "expected SNMP_ERRORSTATUS_NOSUCHNAME, got %d\n", error);
155     ok(index == 1, "expected index 1, got %d\n", index);
156     /* but a GetNext succeeds with the same values, because GetNext gets the
157      * entry after the specified OID, not the entry specified by it.  The
158      * successor to the table is the first entry in the table.
159      * The OIDs need to be allocated, because GetNext modifies them to indicate
160      * the end of data.
161      */
162     SnmpUtilOidCpy(&vars2[0].name, &vars[0].name);
163     SnmpUtilOidCpy(&vars2[1].name, &vars[1].name);
164     SnmpUtilOidCpy(&vars2[2].name, &vars[2].name);
165     list.list = vars2;
166     moreData = TRUE;
167     noChange = FALSE;
168     entry = 0;
169     do {
170         SetLastError(0xdeadbeef);
171         error = 0xdeadbeef;
172         index = 0xdeadbeef;
173         ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index);
174         ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index);
175         ok(error == SNMP_ERRORSTATUS_NOERROR,
176             "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error);
177         ok(index == 0, "expected index 0, got %d\n", index);
178         if (!ret)
179             moreData = FALSE;
180         else if (error)
181             moreData = FALSE;
182         else if (SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name,
183             vars[0].name.idLength))
184             moreData = FALSE;
185         else if (SnmpUtilOidNCmp(&vars2[1].name, &vars[1].name,
186             vars[1].name.idLength))
187             moreData = FALSE;
188         else if (SnmpUtilOidNCmp(&vars2[2].name, &vars[2].name,
189             vars[2].name.idLength))
190             moreData = FALSE;
191         else if (!SnmpUtilOidCmp(&vars[0].name, &vars2[0].name) ||
192          !SnmpUtilOidCmp(&vars[1].name, &vars2[1].name) ||
193          !SnmpUtilOidCmp(&vars[2].name, &vars2[2].name))
194         {
195             /* If the OID isn't modified, the function isn't implemented on this
196              * platform, skip the remaining tests.
197              */
198             noChange = TRUE;
199         }
200         if (moreData)
201         {
202             UINT lastID;
203
204             /* Check the OIDs.  For these types of values (display strings and
205              * integers) they should increase by 1 for each element of the table
206              * according to RFC 1158.  Windows sometimes has a weird value in the
207              * table, so allow any value as long as it's greater than the previous
208              * value on Windows.
209              */
210             ok(vars2[0].name.idLength == vars[0].name.idLength + 1,
211                 "expected length %d, got %d\n", vars[0].name.idLength + 1,
212                 vars2[0].name.idLength);
213             lastID = vars2[0].name.ids[vars2[0].name.idLength - 1];
214             ok(lastID == entry + 1 || broken(lastID > entry),
215                 "expected %d, got %d\n", entry + 1, lastID);
216             ok(vars2[1].name.idLength == vars[1].name.idLength + 1,
217                 "expected length %d, got %d\n", vars[1].name.idLength + 1,
218                 vars2[1].name.idLength);
219             lastID = vars2[1].name.ids[vars2[1].name.idLength - 1];
220             ok(lastID == entry + 1 || broken(lastID > entry),
221                 "expected %d, got %d\n", entry + 1, lastID);
222             ok(vars2[2].name.idLength == vars[2].name.idLength + 1,
223                 "expected length %d, got %d\n", vars[2].name.idLength + 1,
224                 vars2[2].name.idLength);
225             lastID = vars2[2].name.ids[vars2[2].name.idLength - 1];
226             ok(lastID == entry + 1 || broken(lastID > entry),
227                 "expected %d, got %d\n", entry + 1, lastID);
228             entry = lastID;
229             /* Check the types while we're at it */
230             ok(vars2[0].value.asnType == ASN_OCTETSTRING,
231                 "expected ASN_OCTETSTRING, got %02x\n", vars2[0].value.asnType);
232             ok(vars2[1].value.asnType == ASN_INTEGER,
233                 "expected ASN_INTEGER, got %02x\n", vars2[1].value.asnType);
234             ok(vars2[2].value.asnType == ASN_INTEGER,
235                 "expected ASN_INTEGER, got %02x\n", vars2[2].value.asnType);
236         }
237         else if (noChange)
238             skip("no change in OID, no MIB2 IF table implementation\n");
239     } while (moreData && !noChange);
240     SnmpUtilVarBindFree(&vars2[0]);
241     SnmpUtilVarBindFree(&vars2[1]);
242     SnmpUtilVarBindFree(&vars2[2]);
243
244     /* Even though SnmpExtensionInit says this DLL supports the MIB2 system
245      * variables, on recent systems (at least Win2k) the first variable it
246      * returns a value for is the first interface.
247      */
248     vars[0].name.idLength = sizeof(mib2System) / sizeof(mib2System[0]);
249     vars[0].name.ids = mib2System;
250     SnmpUtilOidCpy(&vars2[0].name, &vars[0].name);
251     vars2[0].value.asnType = 0;
252     list.len = 1;
253     list.list = vars2;
254     moreData = TRUE;
255     noChange = FALSE;
256     ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index);
257     ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index);
258     ok(error == SNMP_ERRORSTATUS_NOERROR,
259         "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error);
260     ok(index == 0, "expected index 0, got %d\n", index);
261     vars3[0].name.idLength = sizeof(mib2If) / sizeof(mib2If[0]);
262     vars3[0].name.ids = mib2If;
263     ok(!SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name, vars[0].name.idLength) ||
264        !SnmpUtilOidNCmp(&vars2[0].name, &vars3[0].name, vars3[0].name.idLength),
265         "expected 1.3.6.1.2.1.1 or 1.3.6.1.2.1.2, got %s\n",
266         SnmpUtilOidToA(&vars2[0].name));
267     SnmpUtilVarBindFree(&vars2[0]);
268
269     /* Check the type and OIDs of the IP address table */
270     vars[0].name.idLength = sizeof(mib2IpAddr) / sizeof(mib2IpAddr[0]);
271     vars[0].name.ids = mib2IpAddr;
272     SnmpUtilOidCpy(&vars2[0].name, &vars[0].name);
273     vars2[0].value.asnType = 0;
274     list.len = 1;
275     list.list = vars2;
276     moreData = TRUE;
277     do {
278         ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index);
279         ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index);
280         ok(error == SNMP_ERRORSTATUS_NOERROR,
281             "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error);
282         ok(index == 0, "expected index 0, got %d\n", index);
283         if (!ret)
284             moreData = FALSE;
285         else if (error)
286             moreData = FALSE;
287         else if (SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name,
288             vars[0].name.idLength))
289             moreData = FALSE;
290         else if (!SnmpUtilOidCmp(&vars2[0].name, &vars[0].name))
291         {
292             /* If the OID isn't modified, the function isn't implemented on this
293              * platform, skip the remaining tests.
294              */
295             noChange = TRUE;
296         }
297         if (moreData)
298         {
299             /* Make sure the size of the OID is right.
300              * FIXME: don't know if IPv6 addrs are shared with this table.
301              * Don't think so, but I'm not certain.
302              */
303             ok(vars2[0].name.idLength == vars[0].name.idLength + 4,
304                 "expected length %d, got %d\n", vars[0].name.idLength + 4,
305                 vars2[0].name.idLength);
306             /* Make sure the type is right */
307             ok(vars2[0].value.asnType == ASN_IPADDRESS,
308                 "expected type ASN_IPADDRESS, got %02x\n",
309                 vars2[0].value.asnType);
310             if (vars2[0].value.asnType == ASN_IPADDRESS)
311             {
312                 UINT i;
313
314                 /* This looks uglier than it is:  the base OID for the IP
315                  * address, 1.3.6.1.2.1.4.20.1.1, is appended with the IP
316                  * address of the entry.  So e.g. the loopback address is
317                  * identified in MIB2 as 1.3.6.1.2.1.4.20.1.1.127.0.0.1
318                  */
319                 for (i = 0; i < vars2[0].value.asnValue.address.length; i++)
320                 {
321                     ok(vars2[0].value.asnValue.address.stream[i] ==
322                         vars2[0].name.ids[vars2[0].name.idLength - 4 + i],
323                         "expected ident byte %d to be %d, got %d\n", i,
324                         vars2[0].value.asnValue.address.stream[i],
325                         vars2[0].name.ids[vars2[0].name.idLength - 4 + i]);
326                 }
327             }
328         }
329         else if (noChange)
330             skip("no change in OID, no MIB2 IP address table implementation\n");
331     } while (moreData && !noChange);
332     SnmpUtilVarBindFree(&vars2[0]);
333
334     /* Check the type and OIDs of the IP route table */
335     vars[0].name.idLength = DEFINE_SIZEOF(mib2IpRouteTable);
336     vars[0].name.ids = mib2IpRouteTable;
337     SnmpUtilOidCpy(&vars2[0].name, &vars[0].name);
338     vars2[0].value.asnType = 0;
339     list.len = 1;
340     list.list = vars2;
341     moreData = TRUE;
342     noChange = FALSE;
343     do {
344         ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index);
345         ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index);
346         ok(error == SNMP_ERRORSTATUS_NOERROR,
347             "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error);
348         ok(index == 0, "expected index 0, got %d\n", index);
349         if (!ret)
350             moreData = FALSE;
351         else if (error)
352             moreData = FALSE;
353         else if (SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name,
354             vars[0].name.idLength))
355             moreData = FALSE;
356         else if (!SnmpUtilOidCmp(&vars2[0].name, &vars[0].name))
357         {
358             /* If the OID isn't modified, the function isn't implemented on this
359              * platform, skip the remaining tests.
360              */
361             noChange = TRUE;
362         }
363         if (moreData)
364         {
365             /* Make sure the size of the OID is right.
366              * FIXME: don't know if IPv6 addrs are shared with this table.
367              * Don't think so, but I'm not certain.
368              */
369             ok(vars2[0].name.idLength == vars[0].name.idLength + 4,
370                 "expected length %d, got %d\n", vars[0].name.idLength + 4,
371                 vars2[0].name.idLength);
372             /* Make sure the type is right */
373             ok(vars2[0].value.asnType == ASN_IPADDRESS,
374                 "expected type ASN_IPADDRESS, got %02x\n",
375                 vars2[0].value.asnType);
376             if (vars2[0].value.asnType == ASN_IPADDRESS)
377             {
378                 UINT i;
379
380                 /* The base OID for the route table, 1.3.6.1.2.1.4.21.1.1, is
381                  * appended with the dest IP address of the entry.  So e.g. a
382                  * route entry for 224.0.0.0 is identified in MIB2 as
383                  * 1.3.6.1.2.1.4.21.1.1.224.0.0.0
384                  */
385                 for (i = 0; i < vars2[0].value.asnValue.address.length; i++)
386                 {
387                     ok(vars2[0].value.asnValue.address.stream[i] ==
388                         vars2[0].name.ids[vars2[0].name.idLength - 4 + i],
389                         "expected ident byte %d to be %d, got %d\n", i,
390                         vars2[0].value.asnValue.address.stream[i],
391                         vars2[0].name.ids[vars2[0].name.idLength - 4 + i]);
392                 }
393             }
394         }
395         else if (noChange)
396             skip("no change in OID, no MIB2 IP route table implementation\n");
397     } while (moreData && !noChange);
398     SnmpUtilVarBindFree(&vars2[0]);
399
400     /* Check the type and OIDs of the UDP table */
401     vars[0].name.idLength = DEFINE_SIZEOF(mib2UdpTable);
402     vars[0].name.ids = mib2UdpTable;
403     SnmpUtilOidCpy(&vars2[0].name, &vars[0].name);
404     vars2[0].value.asnType = 0;
405     list.len = 1;
406     list.list = vars2;
407     moreData = TRUE;
408     noChange = FALSE;
409     do {
410         ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index);
411         ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index);
412         /* FIXME:  error and index aren't checked here because the UDP table is
413          * the last OID currently supported by Wine, so the last GetNext fails.
414          * todo_wine is also not effective because it will succeed for all but
415          * the last GetNext.  Remove the if (0) if any later OID is supported
416          * by Wine.
417          */
418         if (0) {
419         ok(error == SNMP_ERRORSTATUS_NOERROR,
420             "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error);
421         ok(index == 0, "expected index 0, got %d\n", index);
422         }
423         if (!ret)
424             moreData = FALSE;
425         else if (error)
426             moreData = FALSE;
427         else if (SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name,
428             vars[0].name.idLength))
429             moreData = FALSE;
430         else if (!SnmpUtilOidCmp(&vars2[0].name, &vars[0].name))
431         {
432             /* If the OID isn't modified, the function isn't implemented on this
433              * platform, skip the remaining tests.
434              */
435             noChange = TRUE;
436         }
437         if (moreData)
438         {
439             /* Make sure the size of the OID is right. */
440             ok(vars2[0].name.idLength == vars[0].name.idLength + 5,
441                 "expected length %d, got %d\n", vars[0].name.idLength + 5,
442                 vars2[0].name.idLength);
443             /* Make sure the type is right */
444             ok(vars2[0].value.asnType == ASN_IPADDRESS,
445                 "expected type ASN_IPADDRESS, got %02x\n",
446                 vars2[0].value.asnType);
447             if (vars2[0].value.asnType == ASN_IPADDRESS)
448             {
449                 UINT i;
450
451                 /* Again with the ugly:  the base OID for the UDP table,
452                  * 1.3.6.1.2.1.7.5.1, is appended with the local IP address and
453                  * port number of the entry.  So e.g. an entry for
454                  * 192.168.1.1:4000 is identified in MIB2 as
455                  * 1.3.6.1.2.1.7.5.1.192.168.1.1.4000
456                  */
457                 for (i = 0; i < vars2[0].value.asnValue.address.length; i++)
458                 {
459                     ok(vars2[0].value.asnValue.address.stream[i] ==
460                         vars2[0].name.ids[vars2[0].name.idLength - 5 + i],
461                         "expected ident byte %d to be %d, got %d\n", i,
462                         vars2[0].value.asnValue.address.stream[i],
463                         vars2[0].name.ids[vars2[0].name.idLength - 5 + i]);
464                 }
465             }
466         }
467         else if (noChange)
468             skip("no change in OID, no MIB2 UDP table implementation\n");
469     } while (moreData && !noChange);
470     SnmpUtilVarBindFree(&vars2[0]);
471 }
472
473 START_TEST(main)
474 {
475     inetmib1 = LoadLibraryA("inetmib1");
476     testInit();
477     testQuery();
478     FreeLibrary(inetmib1);
479 }