blob: 96614e5e6d3ff39d6ca46bb156c788a5af7edd01 [file] [log] [blame]
Rich Lanea06d0c32013-03-25 08:52:03 -07001# Copyright 2013, Big Switch Networks, Inc.
2#
3# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
4# the following special exception:
5#
6# LOXI Exception
7#
8# As a special exception to the terms of the EPL, you may distribute libraries
9# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
10# that copyright and licensing notices generated by LoxiGen are not altered or removed
11# from the LoxiGen Libraries and the notice provided below is (i) included in
12# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
13# documentation for the LoxiGen Libraries, if distributed in binary form.
14#
15# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
16#
17# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
18# a copy of the EPL at:
19#
20# http://www.eclipse.org/legal/epl-v10.html
21#
22# Unless required by applicable law or agreed to in writing, software
23# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
24# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
25# EPL for the specific language governing permissions and limitations
26# under the EPL.
27
28"""
29@brief Test case generation functions
30
31@fixme Update the following
32The following components are generated.
33
34test_common.[ch]: A collection of common code for tests. Currently
35this includes the ability to set the scalar members of an object with
36incrementing values and then similarly verify those values
37
38test_scalar_acc.c: Instantiate each type of object, then set and get
39scalar values in the objects.
40
41test_list.c: Instantiate each type of list, add an element of each
42type the list supports, setting scalar values of the elements.
43
44test_match.c: Various tests for match objects
45
46test_msg.c: Instantiate top level messages
47
48These will move towards unified tests that do the following:
49
50Create or init an object.
51Populate the object with incrementing values.
52Possibly transform the object in some way (e.g., run the underlying
53wire buffer through a parse routine).
54Verify that the members all have the appropriate value
55
56Through out, checking the consistency of memory and memory operations
YAMAMOTO Takashi071b5912013-07-02 08:37:39 +090057is done with mcheck (if available).
Rich Lanea06d0c32013-03-25 08:52:03 -070058
59"""
60
61import sys
62import of_g
63import loxi_front_end.match as match
64import loxi_front_end.flags as flags
65from generic_utils import *
66import loxi_front_end.type_maps as type_maps
67import loxi_utils.loxi_utils as loxi_utils
68import loxi_front_end.identifiers as identifiers
69
70def var_name_map(m_type):
71 """
72 Map a type to a generic variable name for the type.
73 @param m_type The data type
74
75 Used mostly in test code generation, but also for the dup functions.
76 """
77 _var_name_map= dict(
78 uint8_t="val8",
79 uint16_t="val16",
80 uint32_t="val32",
81 uint64_t="val64",
Andreas Wundsamb566a162013-07-18 19:30:23 -070082 of_ipv4_t="ipv4",
Rich Lanea06d0c32013-03-25 08:52:03 -070083 of_port_no_t="port_no",
84 of_fm_cmd_t="fm_cmd",
85 of_wc_bmap_t="wc_bmap",
86 of_match_bmap_t = "match_bmap",
Andreas Wundsam53256162013-05-02 14:05:53 -070087 of_port_name_t="port_name",
Rich Lanea06d0c32013-03-25 08:52:03 -070088 of_table_name_t="table_name",
89 of_desc_str_t="desc_str",
Andreas Wundsam53256162013-05-02 14:05:53 -070090 of_serial_num_t="ser_num",
91 of_mac_addr_t="mac_addr",
Rich Lanea06d0c32013-03-25 08:52:03 -070092 of_ipv6_t="ipv6",
93 # Non-scalars; more TBD
94 of_octets_t="octets",
95 of_meter_features_t="features",
Dan Talaycoc0e802e2013-05-18 23:52:39 -070096 of_match_t="match",
97 # BSN extensions
98 of_bsn_vport_q_in_q_t="vport",
99 )
Rich Lanea06d0c32013-03-25 08:52:03 -0700100
101 if m_type.find("of_list_") == 0:
102 return "list"
103 if m_type in of_g.of_mixed_types:
104 return of_g.of_mixed_types[m_type]["short_name"]
105 return _var_name_map[m_type]
106
107integer_types = ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
108 "of_port_no_t", "of_fm_cmd_t", "of_wc_bmap_t",
Andreas Wundsamb566a162013-07-18 19:30:23 -0700109 "of_match_bmap_t", "of_ipv4_t"]
Rich Lanea06d0c32013-03-25 08:52:03 -0700110string_types = [ "of_port_name_t", "of_table_name_t",
Andreas Wundsam53256162013-05-02 14:05:53 -0700111 "of_desc_str_t", "of_serial_num_t", "of_mac_addr_t",
Rich Lanea06d0c32013-03-25 08:52:03 -0700112 "of_ipv6_t"]
113
114scalar_types = integer_types[:]
115scalar_types.extend(string_types)
116
117def ignore_member(cls, version, m_name, m_type):
118 """
119 Filter out names or types that either don't have accessors
120 or those that should not be messed with
121 or whose types we're not ready to deal with yet.
122 """
123 # This will probably need more granularity as more extensions are added
124 if (type_maps.class_is_extension(cls, version) and (
125 m_name == "experimenter" or
126 m_name == "subtype")):
127 return True
128 return loxi_utils.skip_member_name(m_name) or m_type not in scalar_types
129
130def gen_fill_string(out):
131 out.write("""
132
133/**
134 * The increment to use on values inside a string
135 */
136#define OF_TEST_STR_INCR 3
137
138/**
139 * Fill in a buffer with incrementing values starting
140 * at the given offset with the given value
141 * @param buf The buffer to fill
142 * @param value The value to use for data
143 * @param len The number of bytes to fill
144 */
145
146void
147of_test_str_fill(uint8_t *buf, int value, int len)
148{
149 int i;
150
151 for (i = 0; i < len; i++) {
152 *buf = value;
153 value += OF_TEST_STR_INCR;
154 buf++;
155 }
156}
157
158/**
159 * Given a buffer, verify that it's filled as above
160 * @param buf The buffer to check
161 * @param value The value to use for data
162 * @param len The number of bytes to fill
163 * @return Boolean True on equality (success)
164 */
165
166int
167of_test_str_check(uint8_t *buf, int value, int len)
168{
169 int i;
170 uint8_t val8;
171
172 val8 = value;
173
174 for (i = 0; i < len; i++) {
175 if (*buf != val8) {
176 return 0;
177 }
178 val8 += OF_TEST_STR_INCR;
179 buf++;
180 }
181
182 return 1;
183}
184
185/**
186 * Global that determines how octets should be populated
187 * -1 means use value % MAX (below) to determine length
188 * 0, 1, ... means used that fixed length
189 *
190 * Note: Was 16K, but that made objects too big. May add flexibility
191 * to call populate with a max parameter for length
192 */
193int octets_pop_style = -1;
194#define OCTETS_MAX_VALUE (128) /* 16K was too big */
195#define OCTETS_MULTIPLIER 6367 /* A prime */
196
197int
198of_octets_populate(of_octets_t *octets, int value)
199{
200 if (octets_pop_style < 0) {
201 octets->bytes = (value * OCTETS_MULTIPLIER) % OCTETS_MAX_VALUE;
202 } else {
203 octets->bytes = octets_pop_style;
204 }
205
206 if (octets->bytes != 0) {
207 if ((octets->data = (uint8_t *)MALLOC(octets->bytes)) == NULL) {
208 return 0;
209 }
210 of_test_str_fill(octets->data, value, octets->bytes);
211 value += 1;
212 }
213
214 return value;
215}
216
217int
218of_octets_check(of_octets_t *octets, int value)
219{
220 int len;
221
222 if (octets_pop_style < 0) {
223 len = (value * OCTETS_MULTIPLIER) % OCTETS_MAX_VALUE;
224 TEST_ASSERT(octets->bytes == len);
225 } else {
226 TEST_ASSERT(octets->bytes == octets_pop_style);
227 }
228
229 if (octets->bytes != 0) {
230 TEST_ASSERT(of_test_str_check(octets->data, value, octets->bytes)
231 == 1);
232 value += 1;
233 }
234
235 return value;
236}
237
238int
239of_match_populate(of_match_t *match, of_version_t version, int value)
240{
241 MEMSET(match, 0, sizeof(*match));
242 match->version = version;
243""")
244
245 for key, entry in match.of_match_members.items():
246 out.write("""
Andreas Wundsam53256162013-05-02 14:05:53 -0700247 if (!(of_match_incompat[version] &
Rich Lanea06d0c32013-03-25 08:52:03 -0700248 OF_OXM_BIT(OF_OXM_INDEX_%(ku)s))) {
249 OF_MATCH_MASK_%(ku)s_EXACT_SET(match);
250 VAR_%(u_type)s_INIT(match->fields.%(key)s, value);
251 value += 1;
252 }
253
254""" % dict(key=key, u_type=entry["m_type"].upper(), ku=key.upper()))
255
256 out.write("""
257 if (value % 2) {
258 /* Sometimes set ipv4 addr masks to non-exact */
259 match->masks.ipv4_src = 0xffff0000;
260 match->masks.ipv4_dst = 0xfffff800;
261 }
262 return value;
263}
264
265int
266of_match_check(of_match_t *match, of_version_t version, int value)
267{
268 of_match_t check;
269
270 value = of_match_populate(&check, match->version, value);
271 TEST_ASSERT(value != 0);
272 TEST_ASSERT(MEMCMP(match, &check, sizeof(check)) == 0);
273
274 return value;
275}
276""")
277
278def gen_common_test_header(out, name):
279 loxi_utils.gen_c_copy_license(out)
280 out.write("""
281/*
282 * Test header file
283 *
284 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
285 */
286
287#if !defined(_TEST_COMMON_H_)
288#define _TEST_COMMON_H_
289
290#define DISABLE_WARN_UNUSED_RESULT
291#include <loci/loci.h>
292#include <locitest/of_dup.h>
293#include <locitest/unittest.h>
294
295extern int global_error;
296extern int exit_on_error;
297
298/* @todo Make option for -k to continue tests if errors */
299#define RUN_TEST(test) do { \\
300 int rv; \\
301 TESTCASE(test, rv); \\
302 if (rv != TEST_PASS) { \\
303 global_error=1; \\
304 if (exit_on_error) return(1); \\
305 } \\
306 } while(0)
307
308#define TEST_OK(op) TEST_ASSERT((op) == OF_ERROR_NONE)
309#define TEST_INDIGO_OK(op) TEST_ASSERT((op) == INDIGO_ERROR_NONE)
310
311/*
312 * Declarations of functions to populate scalar values in a a class
313 */
314
315extern void of_test_str_fill(uint8_t *buf, int value, int len);
316extern int of_test_str_check(uint8_t *buf, int value, int len);
317
318
319extern int of_octets_populate(of_octets_t *octets, int value);
320extern int of_octets_check(of_octets_t *octets, int value);
321extern int of_match_populate(of_match_t *match, of_version_t version,
322 int value);
323extern int of_match_check(of_match_t *match, of_version_t version, int value);
324extern int test_ident_macros(void);
325extern int test_dump_objs(void);
326
327/* In test_match_utils.c */
328extern int test_match_utils(void);
329
330extern int run_unified_accessor_tests(void);
331extern int run_match_tests(void);
332extern int run_utility_tests(void);
333
334extern int run_scalar_acc_tests(void);
335extern int run_list_tests(void);
336extern int run_message_tests(void);
337extern int run_setup_from_add_tests(void);
338
339extern int run_validator_tests(void);
340
341extern int run_list_limits_tests(void);
342
343extern int test_ext_objs(void);
344
345""")
346
347 for version in of_g.of_version_range:
348 for cls in of_g.standard_class_order:
349 if not loxi_utils.class_in_version(cls, version):
350 continue
351 if cls in type_maps.inheritance_map:
352 continue
353 out.write("""
354extern int %(cls)s_%(v_name)s_populate(
355 %(cls)s_t *obj, int value);
356extern int %(cls)s_%(v_name)s_check(
357 %(cls)s_t *obj, int value);
358extern int %(cls)s_%(v_name)s_populate_scalars(
359 %(cls)s_t *obj, int value);
360extern int %(cls)s_%(v_name)s_check_scalars(
361 %(cls)s_t *obj, int value);
362""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
363
364 out.write("""
365/*
366 * Declarations for list population and check primitives
367 */
368""")
Andreas Wundsam53256162013-05-02 14:05:53 -0700369
Rich Lanea06d0c32013-03-25 08:52:03 -0700370 for version in of_g.of_version_range:
371 for cls in of_g.ordered_list_objects:
372 if cls in type_maps.inheritance_map:
373 continue
374
375 if version in of_g.unified[cls]:
376 out.write("""
377extern int
378 list_setup_%(cls)s_%(v_name)s(
379 %(cls)s_t *list, int value);
380extern int
381 list_check_%(cls)s_%(v_name)s(
382 %(cls)s_t *list, int value);
383""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
384
385 out.write("\n#endif /* _TEST_COMMON_H_ */\n")
386
387def gen_common_test(out, name):
388 """
389 Generate common test content including main
390 """
391 loxi_utils.gen_c_copy_license(out)
392 out.write("""
393/*
394 * Common test code for LOCI
395 *
396 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
397 */
398
399#define DISABLE_WARN_UNUSED_RESULT
400#include "loci_log.h"
401#include <loci/loci_obj_dump.h>
402#include <locitest/unittest.h>
403#include <locitest/test_common.h>
404
YAMAMOTO Takashi071b5912013-07-02 08:37:39 +0900405/* mcheck is a glibc extension */
406#if defined(__linux__)
Rich Lanea06d0c32013-03-25 08:52:03 -0700407#include <mcheck.h>
408#define MCHECK_INIT mcheck(NULL)
YAMAMOTO Takashi071b5912013-07-02 08:37:39 +0900409#else
Rich Lanea06d0c32013-03-25 08:52:03 -0700410#define MCHECK_INIT do { } while (0)
411#endif
412
413/**
414 * Exit on error if set to 1
415 */
416int exit_on_error = 1;
417
418/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700419 * Global error state: 0 is okay, 1 is error
Rich Lanea06d0c32013-03-25 08:52:03 -0700420 */
421int global_error = 0;
422
423extern int run_unified_accessor_tests(void);
424extern int run_match_tests(void);
425extern int run_utility_tests(void);
426
427extern int run_scalar_acc_tests(void);
428extern int run_list_tests(void);
429extern int run_message_tests(void);
430
431/**
432 * Macros for initializing and checking scalar types
433 *
434 * @param var The variable being initialized or checked
435 * @param val The integer value to set/check against, see below
436 *
437 * Note that equality means something special for strings. Each byte
438 * is initialized to an incrementing value. So check is done against that.
439 *
440 */
441
442""")
443 for t in scalar_types:
444 if t in integer_types:
445 out.write("""
446#define VAR_%s_INIT(var, val) var = (%s)(val)
447#define VAR_%s_CHECK(var, val) ((var) == (%s)(val))
448""" % (t.upper(), t, t.upper(), t))
449 else:
450 out.write("""
451#define VAR_%s_INIT(var, val) \\
452 of_test_str_fill((uint8_t *)&(var), val, sizeof(var))
453#define VAR_%s_CHECK(var, val) \\
454 of_test_str_check((uint8_t *)&(var), val, sizeof(var))
455""" % (t.upper(), t.upper()))
456
457 gen_fill_string(out)
458 gen_scalar_set_check_funs(out)
459 gen_list_set_check_funs(out)
460 gen_unified_accessor_funs(out)
461
462 gen_ident_tests(out)
463 gen_log_test(out)
464
465def gen_message_scalar_test(out, name):
466 """
467 Generate test cases for message objects, scalar accessors
468 """
469
470 loxi_utils.gen_c_copy_license(out)
471 out.write("""
472/**
473 *
474 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
475 *
476 * Message-scalar tests for all versions
477 */
478
479#include <locitest/test_common.h>
480""")
481 for version in of_g.of_version_range:
482 v_name = loxi_utils.version_to_name(version)
483 out.write("""
484/**
485 * Message-scalar tests for version %s
486 */
487""" % v_name)
488 for cls in of_g.standard_class_order:
489 if cls in type_maps.inheritance_map:
490 continue
491 if version in of_g.unified[cls]:
492 message_scalar_test(out, version, cls)
493
494 out.write("""
495int
496run_scalar_acc_tests(void)
497{
498""")
499 for version in of_g.of_version_range:
500 v_name = loxi_utils.version_to_name(version)
501 for cls in of_g.standard_class_order:
502 if cls in type_maps.inheritance_map:
503 continue
504 if version in of_g.unified[cls]:
505 test_name = "%s_%s" % (cls, v_name)
506 out.write(" RUN_TEST(%s_scalar);\n" % test_name)
507
508 out.write(" return TEST_PASS;\n}\n");
Andreas Wundsam53256162013-05-02 14:05:53 -0700509
Rich Lanea06d0c32013-03-25 08:52:03 -0700510def message_scalar_test(out, version, cls):
511 """
512 Generate one test case for the given version and class
513 """
514
515 members, member_types = scalar_member_types_get(cls, version)
Rich Lanef70be942013-07-18 13:33:14 -0700516 length = of_g.base_length[(cls, version)] + of_g.extra_length.get((cls, version), 0)
Rich Lanea06d0c32013-03-25 08:52:03 -0700517 v_name = loxi_utils.version_to_name(version)
518
519 out.write("""
520static int
521test_%(cls)s_%(v_name)s_scalar(void)
522{
523 %(cls)s_t *obj;
524
525 obj = %(cls)s_new(%(v_name)s);
526 TEST_ASSERT(obj != NULL);
527 TEST_ASSERT(obj->version == %(v_name)s);
528 TEST_ASSERT(obj->length == %(length)d);
529 TEST_ASSERT(obj->parent == NULL);
530 TEST_ASSERT(obj->object_id == %(u_cls)s);
Andreas Wundsam53256162013-05-02 14:05:53 -0700531""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700532 v_name=v_name, length=length, version=version))
533 if not type_maps.class_is_virtual(cls):
534 out.write("""
535 if (obj->wire_length_get != NULL) {
536 int length;
537
538 obj->wire_length_get((of_object_t *)obj, &length);
539 TEST_ASSERT(length == %(length)d);
540 }
541
542 /* Set up incrementing values for scalar members */
543 %(cls)s_%(v_name)s_populate_scalars(obj, 1);
544
545 /* Check values just set */
546 TEST_ASSERT(%(cls)s_%(v_name)s_check_scalars(obj, 1) != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -0700547""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700548 v_name=v_name, length=length, version=version))
549
550 out.write("""
551 %(cls)s_delete(obj);
552
553 /* To do: Check memory */
554 return TEST_PASS;
555}
556""" % dict(cls=cls))
557
558# Get the members and list of scalar types for members of a given class
559def scalar_member_types_get(cls, version):
560 member_types = []
561
562 if not version in of_g.unified[cls]:
563 return ([], [])
564
565 if "use_version" in of_g.unified[cls][version]:
566 v = of_g.unified[cls][version]["use_version"]
567 members = of_g.unified[cls][v]["members"]
568 else:
569 members = of_g.unified[cls][version]["members"]
570 # Accumulate variables that are supported
571 for member in members:
572 m_type = member["m_type"]
573 m_name = member["name"]
Andreas Wundsam53256162013-05-02 14:05:53 -0700574 if (not loxi_utils.type_is_scalar(m_type) or
Rich Lanea06d0c32013-03-25 08:52:03 -0700575 ignore_member(cls, version, m_name, m_type)):
576 continue
577 if not m_type in member_types:
578 member_types.append(m_type)
579
580 return (members, member_types)
581
582def scalar_funs_instance(out, cls, version, members, member_types):
583 """
584 Generate one instance of scalar set/check functions
585 """
586 out.write("""
587/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700588 * Populate the scalar values in obj of type %(cls)s,
589 * version %(v_name)s
Rich Lanea06d0c32013-03-25 08:52:03 -0700590 * @param obj Pointer to an object to populate
591 * @param value The seed value to use in populating the object
592 * @returns The value after increments for this object's values
593 */
594int %(cls)s_%(v_name)s_populate_scalars(
595 %(cls)s_t *obj, int value) {
596""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
597 # Declare string types
598 for t in member_types:
599 out.write(" %s %s;\n" % (t, var_name_map(t)))
600 for member in members:
601 m_type = member["m_type"]
602 m_name = member["name"]
603 if (not loxi_utils.type_is_scalar(m_type) or
604 ignore_member(cls, version, m_name, m_type)):
605 continue
606 v_name = var_name_map(m_type);
607 out.write("""
608 VAR_%(u_type)s_INIT(%(v_name)s, value);
609 %(cls)s_%(m_name)s_set(obj, %(v_name)s);
610 value += 1;
611""" % dict(cls=cls, m_name=m_name, u_type=m_type.upper(), v_name=v_name))
612 out.write("""
613 return value;
614}
615""")
Andreas Wundsam53256162013-05-02 14:05:53 -0700616
Rich Lanea06d0c32013-03-25 08:52:03 -0700617 out.write("""
618/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700619 * Check scalar values in obj of type %(cls)s,
620 * version %(v_name)s
Rich Lanea06d0c32013-03-25 08:52:03 -0700621 * @param obj Pointer to an object to check
622 * @param value Starting value for checking
623 * @returns The value after increments for this object's values
624 */
625int %(cls)s_%(v_name)s_check_scalars(
626 %(cls)s_t *obj, int value) {
627""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
628
629 for t in member_types:
630 out.write(" %s %s;\n" % (t, var_name_map(t)))
631 for member in members:
632 m_type = member["m_type"]
633 m_name = member["name"]
634 if (not loxi_utils.type_is_scalar(m_type) or
635 ignore_member(cls, version, m_name, m_type)):
636 continue
637 v_name = var_name_map(m_type);
638 out.write("""
639 %(cls)s_%(m_name)s_get(obj, &%(v_name)s);
640 TEST_ASSERT(VAR_%(u_type)s_CHECK(%(v_name)s, value));
641 value += 1;
642""" % dict(cls=cls, m_name=m_name, u_type=m_type.upper(), v_name=v_name))
643
644 out.write("""
645 return value;
646}
647
648""")
649
650def gen_scalar_set_check_funs(out):
651 """
Andreas Wundsam53256162013-05-02 14:05:53 -0700652 For each object class with scalar members, generate functions that
Rich Lanea06d0c32013-03-25 08:52:03 -0700653 set and check their values
654 """
655 for version in of_g.of_version_range:
656 for cls in of_g.standard_class_order:
657 (members, member_types) = scalar_member_types_get(cls, version)
658 scalar_funs_instance(out, cls, version, members, member_types)
659
660
661# Helper function to set up a subclass instance for a test
662def setup_instance(out, cls, subcls, instance, v_name, inst_len, version):
663 base_type = loxi_utils.list_to_entry_type(cls)
664 setup_template = """
665 %(subcls)s_init(%(inst)s, %(v_name)s, -1, 1);
Andreas Wundsam53256162013-05-02 14:05:53 -0700666 %(cls)s_append_bind(list,
Rich Lanea06d0c32013-03-25 08:52:03 -0700667 (%(base_type)s_t *)%(inst)s);
668 value = %(subcls)s_%(v_name)s_populate(
669 %(inst)s, value);
670 cur_len += %(inst)s->length;
671 TEST_ASSERT(list->length == cur_len);
672"""
673 out.write("""
674 /* Append two instances of type %s */
675""" % subcls)
676 for i in range(2):
677 out.write(setup_template %
Andreas Wundsam53256162013-05-02 14:05:53 -0700678 dict(inst=instance, subcls=subcls, v_name=v_name,
679 base_type=base_type, cls=cls, inst_len=inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700680 version=version))
681
682def check_instance(out, cls, subcls, instance, v_name, inst_len, version, last):
683 check_template = ""
684 if inst_len >= 0:
685 check_template = """
686 TEST_ASSERT(%(inst)s->length == %(inst_len)d);
687 if (%(inst)s->wire_length_get != NULL) {
688 int length;
689
690 %(inst)s->wire_length_get(
691 (of_object_t *)&elt, &length);
692 TEST_ASSERT(length == %(inst_len)d);
693 }
694"""
695 check_template += """
696 TEST_ASSERT(%(inst)s->object_id == %(elt_name)s);
697 value = %(subcls)s_%(v_name)s_check(
698 %(inst)s, value);
699 TEST_ASSERT(value != 0);
700"""
701 out.write("\n /* Check two instances of type %s */" % instance)
702
Andreas Wundsam53256162013-05-02 14:05:53 -0700703 out.write(check_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700704 dict(elt_name=loxi_utils.enum_name(subcls), inst_len=inst_len,
705 inst=instance, subcls=subcls,
706 v_name=loxi_utils.version_to_name(version)))
707 out.write("""\
708 TEST_OK(%(cls)s_next(list, &elt));
709""" % dict(cls=cls))
710
Andreas Wundsam53256162013-05-02 14:05:53 -0700711 out.write(check_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700712 dict(elt_name=loxi_utils.enum_name(subcls), inst_len=inst_len,
713 inst=instance, subcls=subcls,
714 v_name=loxi_utils.version_to_name(version)))
715 if last:
716 out.write("""\
717 TEST_ASSERT(%(cls)s_next(list, &elt) == OF_ERROR_RANGE);
718""" % dict(cls=cls))
719 else:
720 out.write("""\
721 TEST_OK(%(cls)s_next(list, &elt));
722""" % dict(cls=cls))
723
724def setup_list_fn(out, version, cls):
725 """
726 Generate a helper function that populates a list with two
727 of each type of subclass it supports
728 """
729 out.write("""
730/**
731 * Set up a list of type %(cls)s with two of each type of subclass
732 */
733int
734list_setup_%(cls)s_%(v_name)s(
735 %(cls)s_t *list, int value)
736{
737""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
738 base_type = loxi_utils.list_to_entry_type(cls)
739 out.write("""
740 %(base_type)s_t elt;
741 int cur_len = 0;
742""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -0700743
Rich Lanea06d0c32013-03-25 08:52:03 -0700744 sub_classes = type_maps.sub_class_map(base_type, version)
745 v_name = loxi_utils.version_to_name(version)
746
747 if len(sub_classes) == 0:
748 out.write(" /* No subclasses for %s */\n"% base_type)
749 out.write(" %s_t *elt_p;\n" % base_type)
750 out.write("\n elt_p = &elt;\n")
751 else:
752 out.write(" /* Declare pointers for each subclass */\n")
753 for instance, subcls in sub_classes:
754 out.write(" %s_t *%s;\n" % (subcls, instance))
755 out.write("\n /* Instantiate pointers for each subclass */\n")
756 for instance, subcls in sub_classes:
757 out.write(" %s = &elt.%s;\n" % (instance, instance))
758
759 if len(sub_classes) == 0: # No inheritance case
760 inst_len = loxi_utils.base_type_to_length(base_type, version)
761 setup_instance(out, cls, base_type, "elt_p", v_name, inst_len, version)
762 else:
763 for instance, subcls in sub_classes:
764 inst_len = of_g.base_length[(subcls, version)]
765 setup_instance(out, cls, subcls, instance, v_name, inst_len, version)
766 out.write("""
767
768 return value;
769}
770""")
771
772def check_list_fn(out, version, cls):
773 """
774 Generate a helper function that checks a list populated by above fn
775 """
776 out.write("""
777/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700778 * Check a list of type %(cls)s generated by
Rich Lanea06d0c32013-03-25 08:52:03 -0700779 * list_setup_%(cls)s_%(v_name)s
780 */
781int
782list_check_%(cls)s_%(v_name)s(
783 %(cls)s_t *list, int value)
784{
785""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
786 base_type = loxi_utils.list_to_entry_type(cls)
787 out.write("""
788 %(base_type)s_t elt;
789""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -0700790
Rich Lanea06d0c32013-03-25 08:52:03 -0700791 sub_classes = type_maps.sub_class_map(base_type, version)
792 v_name = loxi_utils.version_to_name(version)
793
794 if len(sub_classes) == 0:
795 out.write(" /* No subclasses for %s */\n"% base_type)
796 out.write(" %s_t *elt_p;\n" % base_type)
797 out.write("\n elt_p = &elt;\n")
798 else:
799 out.write(" /* Declare pointers for each subclass */\n")
800 for instance, subcls in sub_classes:
801 out.write(" %s_t *%s;\n" % (subcls, instance))
802 out.write("\n /* Instantiate pointers for each subclass */\n")
803 for instance, subcls in sub_classes:
804 out.write(" %s = &elt.%s;\n" % (instance, instance))
805
806 out.write(" TEST_OK(%(cls)s_first(list, &elt));\n" % dict(cls=cls))
807 if len(sub_classes) == 0: # No inheritance case
808 if loxi_utils.class_is_var_len(base_type, version):
809 inst_len = -1
810 else:
811 inst_len = loxi_utils.base_type_to_length(base_type, version)
Andreas Wundsam53256162013-05-02 14:05:53 -0700812 check_instance(out, cls, base_type, "elt_p", v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700813 version, True)
814 else:
815 count = 0
816 for instance, subcls in sub_classes:
817 count += 1
818 if loxi_utils.class_is_var_len(subcls, version):
819 inst_len = -1
820 else:
821 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -0700822 check_instance(out, cls, subcls, instance, v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700823 version, count==len(sub_classes))
824
825 out.write("""
826 return value;
827}
828""" % dict(base_type=base_type))
829
830def gen_list_set_check_funs(out):
831 for version in of_g.of_version_range:
832 for cls in of_g.ordered_list_objects:
833 if cls in type_maps.inheritance_map:
834 continue
835
836 if version in of_g.unified[cls]:
837 setup_list_fn(out, version, cls)
838 check_list_fn(out, version, cls)
839
840# Maybe: Get a map from list class to parent, mem_name of container
841
842def list_test(out, version, cls):
843 out.write("""
844static int
845test_%(cls)s_%(v_name)s(void)
846{
847""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
848 base_type = loxi_utils.list_to_entry_type(cls)
849
850 out.write(""" %(cls)s_t *list;
851 int value = 1;
852""" % dict(cls=cls, base_type=base_type))
853
854 out.write("""
855 list = %(cls)s_new(%(v_name)s);
856 TEST_ASSERT(list != NULL);
857 TEST_ASSERT(list->version == %(v_name)s);
858 TEST_ASSERT(list->length == 0);
859 TEST_ASSERT(list->parent == NULL);
860 TEST_ASSERT(list->object_id == %(enum_cls)s);
861
862 value = list_setup_%(cls)s_%(v_name)s(list, value);
863 TEST_ASSERT(value != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -0700864""" % dict(cls=cls, base_type=base_type, v_name=loxi_utils.version_to_name(version),
Rich Lanea06d0c32013-03-25 08:52:03 -0700865 enum_cls=loxi_utils.enum_name(cls)))
866
867 out.write("""
868 /* Now check values */
869 value = 1;
870 value = list_check_%(cls)s_%(v_name)s(list, value);
871 TEST_ASSERT(value != 0);
872""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
873
874 out.write("""
875 %(cls)s_delete(list);
876
877 return TEST_PASS;
878}
879""" % dict(cls=cls))
880
881def gen_list_test(out, name):
882 """
883 Generate base line test cases for lists
884 @param out The file handle to write to
885 """
886
887 loxi_utils.gen_c_copy_license(out)
888 out.write("""
889/**
890 *
891 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
892 *
893 * Message-scalar tests for all versions
894 */
895
896#include <locitest/test_common.h>
897""")
Andreas Wundsam53256162013-05-02 14:05:53 -0700898
Rich Lanea06d0c32013-03-25 08:52:03 -0700899 for version in of_g.of_version_range:
900 v_name = loxi_utils.version_to_name(version)
901 out.write("""
902/**
903 * Baseline list tests for version %s
904 */
905""" % v_name)
906 for cls in of_g.ordered_list_objects:
907 if cls in type_maps.inheritance_map:
908 continue
909 if version in of_g.unified[cls]:
910 list_test(out, version, cls)
911
912 out.write("""
913int
914run_list_tests(void)
915{
916""")
917 for version in of_g.of_version_range:
918 v_name = loxi_utils.version_to_name(version)
919 for cls in of_g.ordered_list_objects:
920 if cls in type_maps.inheritance_map:
921 continue
922 if version in of_g.unified[cls]:
923 test_name = "%s_%s" % (cls, v_name)
924 out.write(" RUN_TEST(%s);\n" % test_name)
925
926 out.write("\n return TEST_PASS;\n}\n");
927
928def gen_match_test(out, name):
929 """
930 Generate baseline tests for match functions
931 """
932
933 loxi_utils.gen_c_copy_license(out)
934 out.write("""\
935/**
936 *
937 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
938 *
939 * Message-scalar tests for all versions
940 * @fixme These are mostly hard coded now.
941 */
942
943#include <locitest/test_common.h>
944
945static int
946test_match_1(void)
947{
948 of_match_v1_t *m_v1;
949 of_match_v2_t *m_v2;
950 of_match_v3_t *m_v3;
951 of_match_v4_t *m_v4;
952 of_match_t match;
953 int value = 1;
954 int idx;
955 uint32_t exp_value;
956
957 /* Verify default values for ip mask map */
958 for (idx = 0; idx < OF_IP_MASK_MAP_COUNT; idx++) {
959 exp_value = (idx < 32) ? ~((1 << idx) - 1) : 0;
960 TEST_ASSERT(of_ip_index_to_mask(idx) == exp_value);
961 if (idx < 32) {
962 TEST_ASSERT(of_ip_mask_to_index(exp_value) == idx);
963 }
964 }
965
966 TEST_ASSERT(of_ip_mask_map_set(17, 0xabcdef00) == OF_ERROR_NONE);
967 TEST_ASSERT(of_ip_mask_to_index(0xabcdef00) == 17);
968 TEST_ASSERT(of_ip_index_to_mask(17) == 0xabcdef00);
969
970 TEST_ASSERT(of_ip_mask_map_set(62, 0xabcdefff) == OF_ERROR_NONE);
971 TEST_ASSERT(of_ip_mask_to_index(0xabcdefff) == 62);
972 TEST_ASSERT(of_ip_index_to_mask(62) == 0xabcdefff);
973
974 /* Test re-init */
975 of_ip_mask_map_init();
976 for (idx = 0; idx < OF_IP_MASK_MAP_COUNT; idx++) {
977 exp_value = (idx < 32) ? ~((1 << idx) - 1) : 0;
978 TEST_ASSERT(of_ip_index_to_mask(idx) == exp_value);
979 if (idx < 32) {
980 TEST_ASSERT(of_ip_mask_to_index(exp_value) == idx);
981 }
982 }
983""")
984
985 for version in of_g.of_version_range:
986 out.write("""
987 /* Create/populate/convert and delete for version %(v_name)s */
988 m_v%(version)d = of_match_v%(version)d_new(%(v_name)s);
989 TEST_ASSERT(m_v%(version)d != NULL);
990 TEST_ASSERT((value = of_match_populate(&match, %(v_name)s, value)) > 0);
991 TEST_OK(of_match_to_wire_match_v%(version)d(&match, m_v%(version)d));
992 of_match_v%(version)d_delete(m_v%(version)d);
993""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
994
995 out.write("""
996 return TEST_PASS;
997}
998""")
999
1000 out.write("""
1001static int
1002test_match_2(void)
1003{
1004 of_match_v1_t *m_v1;
1005 of_match_v2_t *m_v2;
1006 of_match_v3_t *m_v3;
1007 of_match_v3_t *m_v4;
1008 of_match_t match1;
1009 of_match_t match2;
1010 int value = 1;
1011""")
1012
1013 for version in of_g.of_version_range:
1014 out.write("""
1015 TEST_ASSERT((value = of_match_populate(&match1, %(v_name)s, value)) > 0);
1016 m_v%(version)d = of_match_v%(version)d_new(%(v_name)s);
1017 TEST_ASSERT(m_v%(version)d != NULL);
1018 TEST_OK(of_match_to_wire_match_v%(version)d(&match1, m_v%(version)d));
1019 TEST_OK(of_match_v%(version)d_to_match(m_v%(version)d, &match2));
1020 TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
1021 of_match_v%(version)d_delete(m_v%(version)d);
1022""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
1023
1024 out.write("""
1025 return TEST_PASS;
1026}
1027""")
1028
1029 out.write("""
1030static int
1031test_match_3(void)
1032{
1033 of_match_t match1;
1034 of_match_t match2;
1035 int value = 1;
1036 of_octets_t octets;
1037""")
1038 for version in of_g.of_version_range:
1039 out.write("""
1040 /* Serialize to version %(v_name)s */
1041 TEST_ASSERT((value = of_match_populate(&match1, %(v_name)s, value)) > 0);
Andreas Wundsam53256162013-05-02 14:05:53 -07001042 TEST_ASSERT(of_match_serialize(%(v_name)s, &match1, &octets) ==
Rich Lanea06d0c32013-03-25 08:52:03 -07001043 OF_ERROR_NONE);
Andreas Wundsam53256162013-05-02 14:05:53 -07001044 TEST_ASSERT(of_match_deserialize(%(v_name)s, &match2, &octets) ==
Rich Lanea06d0c32013-03-25 08:52:03 -07001045 OF_ERROR_NONE);
1046 TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
1047 FREE(octets.data);
1048""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
1049
1050 out.write("""
1051 return TEST_PASS;
1052}
1053""")
1054
1055 out.write("""
1056int run_match_tests(void)
1057{
1058 RUN_TEST(match_1);
1059 RUN_TEST(match_2);
1060 RUN_TEST(match_3);
1061 RUN_TEST(match_utils);
1062
1063 return TEST_PASS;
1064}
1065""")
1066
1067def gen_msg_test(out, name):
1068 loxi_utils.gen_c_copy_license(out)
1069 out.write("""
1070/**
1071 *
1072 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1073 *
1074 * Message-scalar tests for all versions
1075 */
1076
1077#include <locitest/test_common.h>
1078""")
1079 for version in of_g.of_version_range:
1080 for cls in of_g.ordered_messages:
1081 if not (cls, version) in of_g.base_length:
1082 continue
Rich Lanef70be942013-07-18 13:33:14 -07001083 bytes = of_g.base_length[(cls, version)] + of_g.extra_length.get((cls, version), 0)
Rich Lanea06d0c32013-03-25 08:52:03 -07001084 out.write("""
1085static int
1086test_%(cls)s_create_%(v_name)s(void)
1087{
1088 %(cls)s_t *obj;
1089 uint8_t *msg_buf;
1090 int value;
1091 int len;
1092
1093 obj = %(cls)s_new(%(v_name)s);
1094 TEST_ASSERT(obj != NULL);
1095 TEST_ASSERT(obj->version == %(v_name)s);
1096 TEST_ASSERT(obj->length == %(bytes)d);
1097 TEST_ASSERT(obj->parent == NULL);
1098 TEST_ASSERT(obj->object_id == %(enum)s);
1099
1100 /* Set up incrementing values for scalar members */
1101 value = %(cls)s_%(v_name)s_populate_scalars(obj, 1);
1102 TEST_ASSERT(value != 0);
1103
1104 /* Grab the underlying buffer from the message */
1105 len = obj->length;
1106 of_object_wire_buffer_steal((of_object_t *)obj, &msg_buf);
1107 TEST_ASSERT(msg_buf != NULL);
1108 %(cls)s_delete(obj);
1109 /* TODO: */
1110 TEST_ASSERT(of_message_to_object_id(msg_buf, len) == %(enum)s);
1111 obj = %(cls)s_new_from_message(OF_BUFFER_TO_MESSAGE(msg_buf));
1112
1113 TEST_ASSERT(obj != NULL);
1114
1115 /* @fixme Set up all message objects (recursively?) */
1116
1117 value = %(cls)s_%(v_name)s_check_scalars(obj, 1);
1118 TEST_ASSERT(value != 0);
1119
1120 %(cls)s_delete(obj);
1121
1122 return TEST_PASS;
1123}
1124""" % dict(cls=cls, version=version, enum=loxi_utils.enum_name(cls),
1125 v_name=loxi_utils.version_to_name(version), bytes=bytes))
1126
1127 out.write("""
1128int
1129run_message_tests(void)
1130{
1131""")
1132 for version in of_g.of_version_range:
1133 for cls in of_g.ordered_messages:
1134 if not (cls, version) in of_g.base_length:
1135 continue
1136 test_name = "%s_create_%s" % (cls, loxi_utils.version_to_name(version))
1137 out.write(" RUN_TEST(%s);\n" % test_name)
1138
1139 out.write("\n return TEST_PASS;\n}\n");
Andreas Wundsam53256162013-05-02 14:05:53 -07001140
Rich Lanea06d0c32013-03-25 08:52:03 -07001141
1142def gen_list_setup_check(out, cls, version):
1143 """
1144 Generate functions that populate and check a list with two
1145 of each type of subclass it supports
1146 """
1147 out.write("""
1148/**
1149 * Populate a list of type %(cls)s with two of each type of subclass
1150 * @param list Pointer to the list to be populated
1151 * @param value The seed value to use in populating the list
1152 * @returns The value after increments for this object's values
1153 */
1154int
1155%(cls)s_%(v_name)s_populate(
1156 %(cls)s_t *list, int value)
1157{
1158""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1159 base_type = loxi_utils.list_to_entry_type(cls)
1160 out.write("""
1161 %(base_type)s_t elt;
1162 int cur_len = 0;
1163""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -07001164
Rich Lanea06d0c32013-03-25 08:52:03 -07001165 sub_classes = type_maps.sub_class_map(base_type, version)
1166 v_name = loxi_utils.version_to_name(version)
1167
1168 if len(sub_classes) == 0:
1169 out.write(" /* No subclasses for %s */\n"% base_type)
1170 out.write(" %s_t *elt_p;\n" % base_type)
1171 out.write("\n elt_p = &elt;\n")
1172 else:
1173 out.write(" /* Declare pointers for each subclass */\n")
1174 for instance, subcls in sub_classes:
1175 out.write(" %s_t *%s;\n" % (subcls, instance))
1176 out.write("\n /* Instantiate pointers for each subclass */\n")
1177 for instance, subcls in sub_classes:
1178 out.write(" %s = &elt.%s;\n" % (instance, instance))
1179
1180# if type_maps.class_is_virtual(base_type):
1181# out.write("""\
1182# TEST_OK(%(base_type)s_header_init(
1183# (%(base_type)s_header_t *)&elt, %(v_name)s, -1, 1));
1184# """ % dict(base_type=base_type, v_name=loxi_utils.version_to_name(version)))
1185# else:
1186# out.write("""\
1187# TEST_OK(%(base_type)s_init(&elt, %(v_name)s, -1, 1));
1188# """ % dict(base_type=base_type, v_name=loxi_utils.version_to_name(version)))
1189
1190 if len(sub_classes) == 0: # No inheritance case
1191 inst_len = loxi_utils.base_type_to_length(base_type, version)
1192 setup_instance(out, cls, base_type, "elt_p", v_name, inst_len, version)
1193 else:
1194 for instance, subcls in sub_classes:
1195 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -07001196 setup_instance(out, cls, subcls, instance, v_name,
Rich Lanea06d0c32013-03-25 08:52:03 -07001197 inst_len, version)
1198 out.write("""
1199 return value;
1200}
1201""")
1202 out.write("""
1203/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001204 * Check a list of type %(cls)s generated by
Rich Lanea06d0c32013-03-25 08:52:03 -07001205 * %(cls)s_%(v_name)s_populate
1206 * @param list Pointer to the list that was populated
1207 * @param value Starting value for checking
1208 * @returns The value after increments for this object's values
1209 */
1210int
1211%(cls)s_%(v_name)s_check(
1212 %(cls)s_t *list, int value)
1213{
1214""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1215 base_type = loxi_utils.list_to_entry_type(cls)
1216 out.write("""
1217 %(base_type)s_t elt;
1218 int count = 0;
1219 int rv;
1220""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -07001221
Rich Lanea06d0c32013-03-25 08:52:03 -07001222
1223 sub_classes = type_maps.sub_class_map(base_type, version)
1224 v_name = loxi_utils.version_to_name(version)
1225
1226 if len(sub_classes) == 0:
1227 entry_count = 2
1228 out.write(" /* No subclasses for %s */\n"% base_type)
1229 out.write(" %s_t *elt_p;\n" % base_type)
1230 out.write("\n elt_p = &elt;\n")
1231 else:
1232 entry_count = 2 * len(sub_classes) # Two of each type appended
1233 out.write(" /* Declare pointers for each subclass */\n")
1234 for instance, subcls in sub_classes:
1235 out.write(" %s_t *%s;\n" % (subcls, instance))
1236 out.write("\n /* Instantiate pointers for each subclass */\n")
1237 for instance, subcls in sub_classes:
1238 out.write(" %s = &elt.%s;\n" % (instance, instance))
1239
1240 out.write(" TEST_OK(%(cls)s_first(list, &elt));\n" % dict(cls=cls))
1241 if len(sub_classes) == 0: # No inheritance case
1242 if loxi_utils.class_is_var_len(base_type, version):
1243 inst_len = -1
1244 else:
1245 inst_len = loxi_utils.base_type_to_length(base_type, version)
Andreas Wundsam53256162013-05-02 14:05:53 -07001246 check_instance(out, cls, base_type, "elt_p", v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -07001247 version, True)
1248 else:
1249 count = 0
1250 for instance, subcls in sub_classes:
1251 count += 1
1252 if loxi_utils.class_is_var_len(subcls, version):
1253 inst_len = -1
1254 else:
1255 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -07001256 check_instance(out, cls, subcls, instance, v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -07001257 version, count==len(sub_classes))
1258 out.write("""
1259""" % dict(base_type=base_type))
1260
1261 out.write("""
1262 /* Do an iterate to test the iterator */
1263 %(u_cls)s_ITER(list, &elt, rv) {
1264 count += 1;
1265 }
1266
1267 TEST_ASSERT(rv == OF_ERROR_RANGE);
1268 TEST_ASSERT(count == %(entry_count)d);
1269
1270 /* We shoehorn a test of the dup functions here */
1271 {
1272 %(cls)s_t *dup;
1273
1274 TEST_ASSERT((dup = %(cls)s_dup(list)) != NULL);
1275 TEST_ASSERT(dup->length == list->length);
1276 TEST_ASSERT(dup->object_id == list->object_id);
1277 TEST_ASSERT(dup->version == list->version);
1278 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1279 OF_OBJECT_BUFFER_INDEX(list, 0), list->length) == 0);
1280 of_object_delete((of_object_t *)dup);
1281
1282 /* And now for the generic dup function */
1283 TEST_ASSERT((dup = (%(cls)s_t *)
1284 of_object_dup(list)) != NULL);
1285 TEST_ASSERT(dup->length == list->length);
1286 TEST_ASSERT(dup->object_id == list->object_id);
1287 TEST_ASSERT(dup->version == list->version);
1288 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1289 OF_OBJECT_BUFFER_INDEX(list, 0), list->length) == 0);
1290 of_object_delete((of_object_t *)dup);
1291 }
1292
1293 return value;
1294}
1295""" % dict(cls=cls, u_cls=cls.upper(), entry_count=entry_count))
1296
1297
1298def gen_class_setup_check(out, cls, version):
1299 out.write("""
1300/**
1301 * Populate all members of an object of type %(cls)s
1302 * with incrementing values
1303 * @param obj Pointer to an object to populate
1304 * @param value The seed value to use in populating the object
1305 * @returns The value after increments for this object's values
1306 */
1307
1308int
1309%(cls)s_%(v_name)s_populate(
1310 %(cls)s_t *obj, int value)
1311{
1312""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1313 members, member_types = loxi_utils.all_member_types_get(cls, version)
1314 for m_type in member_types:
1315 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1316 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1317 else:
1318 out.write(" %s *%s;\n" % (m_type, var_name_map(m_type)))
1319 out.write("""
1320 /* Run thru accessors after new to ensure okay */
1321""")
1322 for member in members:
1323 m_type = member["m_type"]
1324 m_name = member["name"]
1325 if loxi_utils.skip_member_name(m_name):
1326 continue
1327 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1328 out.write("""\
1329 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1330""" % dict(var_name=var_name_map(m_type), cls=cls, m_name=m_name))
1331 else:
1332 sub_cls = m_type[:-2] # Trim _t
1333 out.write("""\
1334 {
1335 %(sub_cls)s_t sub_cls;
1336
1337 /* Test bind */
1338 %(cls)s_%(m_name)s_bind(obj, &sub_cls);
1339 }
Andreas Wundsam53256162013-05-02 14:05:53 -07001340""" % dict(var_name=var_name_map(m_type), cls=cls,
Rich Lanea06d0c32013-03-25 08:52:03 -07001341 m_name=m_name, sub_cls=sub_cls,
1342 v_name=loxi_utils.version_to_name(version)))
1343
1344 out.write("""
1345 value = %(cls)s_%(v_name)s_populate_scalars(
1346 obj, value);
1347 TEST_ASSERT(value != 0);
1348""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1349
1350 for member in members:
1351 m_type = member["m_type"]
1352 m_name = member["name"]
1353 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1354 continue
1355 if loxi_utils.skip_member_name(m_name):
1356 continue
1357 if m_type == "of_match_t":
1358 out.write("""\
1359 value = of_match_populate(&%(var_name)s, %(v_name)s, value);
1360 TEST_ASSERT(value != 0);
1361 %(cls)s_%(m_name)s_set(
1362 obj, &%(var_name)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001363""" % dict(cls=cls, var_name=var_name_map(m_type),
Rich Lanea06d0c32013-03-25 08:52:03 -07001364 m_name=m_name, v_name=loxi_utils.version_to_name(version)))
1365 elif m_type == "of_octets_t":
1366 out.write("""\
1367 value = of_octets_populate(&%(var_name)s, value);
1368 TEST_ASSERT(value != 0);
1369 %(cls)s_%(m_name)s_set(
1370 obj, &%(var_name)s);
1371 if (octets.bytes) {
1372 FREE(octets.data);
1373 }
1374""" % dict(var_name=var_name_map(m_type), cls=cls, m_name=m_name))
1375 else:
1376 sub_cls = m_type[:-2] # Trim _t
1377 out.write("""
1378 %(var_name)s = %(sub_cls)s_new(%(v_name)s);
1379 TEST_ASSERT(%(var_name)s != NULL);
1380 value = %(sub_cls)s_%(v_name)s_populate(
1381 %(var_name)s, value);
1382 TEST_ASSERT(value != 0);
1383 %(cls)s_%(m_name)s_set(
1384 obj, %(var_name)s);
1385 %(sub_cls)s_delete(%(var_name)s);
1386""" % dict(cls=cls, sub_cls=sub_cls, m_name=m_name, m_type=m_type,
1387 var_name=var_name_map(m_type),
1388 v_name=loxi_utils.version_to_name(version)))
1389
1390 out.write("""
1391 return value;
1392}
1393""")
1394
1395 out.write("""
1396/**
1397 * Check all members of an object of type %(cls)s
1398 * populated by the above function
1399 * @param obj Pointer to an object to check
1400 * @param value Starting value for checking
1401 * @returns The value after increments for this object's values
1402 */
1403
1404int
1405%(cls)s_%(v_name)s_check(
1406 %(cls)s_t *obj, int value)
1407{
1408""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1409 members, member_types = loxi_utils.all_member_types_get(cls, version)
1410 for m_type in member_types:
1411 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1412 continue
1413 if loxi_utils.type_is_of_object(m_type):
1414 continue
1415 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1416 out.write("""
1417 value = %(cls)s_%(v_name)s_check_scalars(
1418 obj, value);
1419 TEST_ASSERT(value != 0);
1420""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1421
1422 for member in members:
1423 m_type = member["m_type"]
1424 m_name = member["name"]
1425 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1426 continue
1427 if loxi_utils.skip_member_name(m_name):
1428 continue
1429 if m_type == "of_match_t":
1430 out.write("""\
1431 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1432 value = of_match_check(&%(var_name)s, %(v_name)s, value);
1433""" % dict(cls=cls, var_name=var_name_map(m_type), m_name=m_name,
1434 v_name=loxi_utils.version_to_name(version)))
1435 elif m_type == "of_octets_t":
1436 out.write("""\
1437 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1438 value = of_octets_check(&%(var_name)s, value);
1439""" % dict(cls=cls, var_name=var_name_map(m_type), m_name=m_name,
1440 v_name=loxi_utils.version_to_name(version)))
1441 else:
1442 sub_cls = m_type[:-2] # Trim _t
1443 out.write("""
1444 { /* Use get/delete to access on check */
1445 %(m_type)s *%(m_name)s_ptr;
1446
1447 %(m_name)s_ptr = %(cls)s_%(m_name)s_get(obj);
1448 TEST_ASSERT(%(m_name)s_ptr != NULL);
1449 value = %(sub_cls)s_%(v_name)s_check(
1450 %(m_name)s_ptr, value);
1451 TEST_ASSERT(value != 0);
1452 %(sub_cls)s_delete(%(m_name)s_ptr);
1453 }
1454""" % dict(cls=cls, sub_cls=sub_cls, m_name=m_name, m_type=m_type,
1455 var_name=var_name_map(m_type),
1456 v_name=loxi_utils.version_to_name(version)))
1457
1458 out.write("""
1459 /* We shoehorn a test of the dup functions here */
1460 {
1461 %(cls)s_t *dup;
1462
1463 TEST_ASSERT((dup = %(cls)s_dup(obj)) != NULL);
1464 TEST_ASSERT(dup->length == obj->length);
1465 TEST_ASSERT(dup->object_id == obj->object_id);
1466 TEST_ASSERT(dup->version == obj->version);
1467 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1468 OF_OBJECT_BUFFER_INDEX(obj, 0), obj->length) == 0);
1469 of_object_delete((of_object_t *)dup);
1470
1471 /* And now for the generic dup function */
1472 TEST_ASSERT((dup = (%(cls)s_t *)
1473 of_object_dup(obj)) != NULL);
1474 TEST_ASSERT(dup->length == obj->length);
1475 TEST_ASSERT(dup->object_id == obj->object_id);
1476 TEST_ASSERT(dup->version == obj->version);
1477 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1478 OF_OBJECT_BUFFER_INDEX(obj, 0), obj->length) == 0);
1479 of_object_delete((of_object_t *)dup);
1480 }
1481
1482 return value;
1483}
1484""" % dict(cls=cls))
1485
1486def unified_accessor_test_case(out, cls, version):
1487 """
1488 Generate one test case for the given version and class
1489 """
1490
1491 members, member_types = scalar_member_types_get(cls, version)
Rich Lanef70be942013-07-18 13:33:14 -07001492 length = of_g.base_length[(cls, version)] + of_g.extra_length.get((cls, version), 0)
Rich Lanea06d0c32013-03-25 08:52:03 -07001493 v_name = loxi_utils.version_to_name(version)
1494
1495 out.write("""
1496static int
1497test_%(cls)s_%(v_name)s(void)
1498{
1499 %(cls)s_t *obj;
1500 obj = %(cls)s_new(%(v_name)s);
1501 TEST_ASSERT(obj != NULL);
1502 TEST_ASSERT(obj->version == %(v_name)s);
1503 TEST_ASSERT(obj->length == %(length)d);
1504 TEST_ASSERT(obj->parent == NULL);
1505 TEST_ASSERT(obj->object_id == %(u_cls)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001506""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -07001507 v_name=v_name, length=length, version=version))
1508 if (not type_maps.class_is_virtual(cls)) or loxi_utils.class_is_list(cls):
1509 out.write("""
1510 if (obj->wire_length_get != NULL) {
1511 int length;
1512
1513 obj->wire_length_get((of_object_t *)obj, &length);
1514 TEST_ASSERT(length == %(length)d);
1515 }
1516 if (obj->wire_type_get != NULL) {
1517 of_object_id_t obj_id;
1518
1519 obj->wire_type_get((of_object_t *)obj, &obj_id);
1520 TEST_ASSERT(obj_id == %(u_cls)s);
1521 }
1522
1523 /* Set up incrementing values for members */
1524 TEST_ASSERT(%(cls)s_%(v_name)s_populate(
1525 obj, 1) != 0);
1526
1527 /* Check values just set */
1528 TEST_ASSERT(%(cls)s_%(v_name)s_check(
1529 obj, 1) != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -07001530""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -07001531 v_name=v_name, length=length, version=version))
1532
1533 out.write("""
1534 %(cls)s_delete(obj);
1535
1536 /* To do: Check memory */
1537 return TEST_PASS;
1538}
1539""" % dict(cls=cls))
1540
1541
1542def gen_unified_accessor_funs(out):
1543 for version in of_g.of_version_range:
1544 for cls in of_g.standard_class_order:
1545 if not loxi_utils.class_in_version(cls, version):
1546 continue
1547 if cls in type_maps.inheritance_map:
1548 continue
1549 elif loxi_utils.class_is_list(cls):
1550 gen_list_setup_check(out, cls, version)
1551 else:
1552 gen_class_setup_check(out, cls, version)
1553
1554def gen_unified_accessor_tests(out, name):
1555 loxi_utils.gen_c_copy_license(out)
1556 out.write("""
1557/**
1558 *
1559 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1560 *
1561 * Unified simple class instantiation tests for all versions
1562 */
1563
1564#include <locitest/test_common.h>
1565""")
1566 for version in of_g.of_version_range:
1567 for cls in of_g.standard_class_order:
1568 if not loxi_utils.class_in_version(cls, version):
1569 continue
1570 if cls in type_maps.inheritance_map:
1571 continue
1572 unified_accessor_test_case(out, cls, version)
1573
1574 out.write("""
1575int
1576run_unified_accessor_tests(void)
1577{
1578""")
1579 for version in of_g.of_version_range:
1580 v_name = loxi_utils.version_to_name(version)
1581 for cls in of_g.standard_class_order:
1582 if not loxi_utils.class_in_version(cls, version):
1583 continue
1584 if cls in type_maps.inheritance_map:
1585 continue
1586 test_name = "%s_%s" % (cls, v_name)
1587 out.write(" RUN_TEST(%s);\n" % test_name)
1588
1589 out.write(" return TEST_PASS;\n}\n");
1590
1591
1592
1593################################################################
1594#
1595# Object duplication functions
1596#
1597# These exercise the accessors to create duplicate objects.
1598# They are used in the LOCI test shim which sits in an OF
1599# protocol stream.
1600#
1601# TODO
1602# Resolve version stuff
1603# Complete list dup
1604
1605def gen_dup_list(out, cls, version):
1606 ver_name = loxi_utils.version_to_name(version)
1607 elt_type = loxi_utils.list_to_entry_type(cls)
1608 out.write("""
1609/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001610 * Duplicate a list of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001611 * using accessor functions
1612 * @param src Pointer to object to be duplicated
1613 * @returns A new object of type %(cls)s.
1614 *
1615 * The caller is responsible for deleting the returned value
1616 */
1617%(cls)s_t *
1618%(cls)s_%(ver_name)s_dup(
1619 %(cls)s_t *src)
1620{
1621 %(elt_type)s_t src_elt;
1622 %(elt_type)s_t *dst_elt;
1623 int rv;
1624 %(cls)s_t *dst;
1625
1626 if ((dst = %(cls)s_new(src->version)) == NULL) {
1627 return NULL;
1628 }
1629""" % dict(elt_type=elt_type, cls=cls, ver_name=ver_name))
1630
1631 out.write("""
1632 %(u_cls)s_ITER(src, &src_elt, rv) {
1633 if ((dst_elt = %(elt_type)s_%(ver_name)s_dup(&src_elt)) == NULL) {
1634 of_object_delete((of_object_t *)dst);
1635 return NULL;
1636 }
1637 _TRY_FREE(%(cls)s_append(dst, dst_elt),
1638 dst, NULL);
1639 of_object_delete((of_object_t *)dst_elt);
1640 }
1641
1642 return dst;
1643}
1644""" % dict(u_cls=cls.upper(), elt_type=elt_type, cls=cls, ver_name=ver_name))
1645
1646
1647def gen_dup_inheritance(out, cls, version):
1648 ver_name = loxi_utils.version_to_name(version)
1649 out.write("""
1650/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001651 * Duplicate a super class object of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001652 * @param src Pointer to object to be duplicated
1653 * @returns A new object of type %(cls)s.
1654 *
1655 * The caller is responsible for deleting the returned value
1656 */
1657%(cls)s_t *
1658%(cls)s_%(ver_name)s_dup(
1659 %(cls)s_t *src)
1660{
1661""" % dict(cls=cls, ver_name=ver_name))
1662
1663 # For each subclass, check if this is an instance of that subclass
1664 version_classes = type_maps.inheritance_data[cls][version]
1665 for sub_cls in version_classes:
1666 sub_enum = (cls + "_" + sub_cls).upper()
1667 out.write("""
1668 if (src->header.object_id == %(sub_enum)s) {
1669 return (%(cls)s_t *)%(cls)s_%(sub_cls)s_%(ver_name)s_dup(
1670 &src->%(sub_cls)s);
1671 }
1672""" % dict(sub_cls=sub_cls, ver_name=ver_name, sub_enum=sub_enum, cls=cls))
1673
1674 out.write("""
1675 return NULL;
1676}
1677""")
1678
1679
1680def gen_dup_cls(out, cls, version):
1681 """
1682 Generate duplication routine for class cls
1683 """
1684 ver_name = loxi_utils.version_to_name(version)
1685
1686 out.write("""
1687/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001688 * Duplicate an object of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001689 * using accessor functions
1690 * @param src Pointer to object to be duplicated
1691 * @returns A new object of type %(cls)s.
1692 *
1693 * The caller is responsible for deleting the returned value
1694 */
1695%(cls)s_t *
1696%(cls)s_%(ver_name)s_dup(
1697 %(cls)s_t *src)
1698{
1699 %(cls)s_t *dst;
1700""" % dict(cls=cls, ver_name=ver_name))
1701
1702 # Get members and types for the class
1703 members, member_types = loxi_utils.all_member_types_get(cls, version)
1704
1705 # Add declarations for each member type
1706 for m_type in member_types:
1707 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1708 # Declare instance of these
1709 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1710 else:
1711 out.write("""
1712 %(m_type)s src_%(v_name)s;
1713 %(m_type)s *dst_%(v_name)s;
1714""" % dict(m_type=m_type, v_name=var_name_map(m_type)))
1715
1716 out.write("""
1717 if ((dst = %(cls)s_new(src->version)) == NULL) {
1718 return NULL;
1719 }
1720""" % dict(cls=cls))
1721
1722 for member in members:
1723 m_type = member["m_type"]
1724 m_name = member["name"]
1725 if loxi_utils.skip_member_name(m_name):
1726 continue
1727 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1728 out.write("""
1729 %(cls)s_%(m_name)s_get(src, &%(v_name)s);
1730 %(cls)s_%(m_name)s_set(dst, %(v_name)s);
1731""" % dict(cls=cls, m_name=m_name, v_name=var_name_map(m_type)))
1732 elif m_type in ["of_match_t", "of_octets_t"]:
1733 out.write("""
1734 %(cls)s_%(m_name)s_get(src, &%(v_name)s);
1735 %(cls)s_%(m_name)s_set(dst, &%(v_name)s);
1736""" % dict(cls=cls, m_name=m_name, v_name=var_name_map(m_type)))
1737 else:
1738 sub_cls = m_type[:-2] # Trim _t
1739 out.write("""
1740 %(cls)s_%(m_name)s_bind(
1741 src, &src_%(v_name)s);
1742 dst_%(v_name)s = %(sub_cls)s_%(ver_name)s_dup(&src_%(v_name)s);
1743 if (dst_%(v_name)s == NULL) {
1744 %(cls)s_delete(dst);
1745 return NULL;
1746 }
1747 %(cls)s_%(m_name)s_set(dst, dst_%(v_name)s);
1748 %(sub_cls)s_delete(dst_%(v_name)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001749""" % dict(sub_cls=sub_cls, cls=cls, m_name=m_name,
Rich Lanea06d0c32013-03-25 08:52:03 -07001750 v_name=var_name_map(m_type), ver_name=ver_name))
1751
1752 out.write("""
1753 return dst;
1754}
1755""")
1756
1757def gen_version_dup(out=sys.stdout):
1758 """
1759 Generate duplication routines for each object type
1760 """
1761 out.write("""
1762/* Special try macro for duplicating */
1763#define _TRY_FREE(op, obj, rv) do { \\
1764 int _rv; \\
1765 if ((_rv = (op)) < 0) { \\
1766 LOCI_LOG_ERROR("ERROR %d at %s:%d\\n", _rv, __FILE__, __LINE__); \\
1767 of_object_delete((of_object_t *)(obj)); \\
1768 return (rv); \\
1769 } \\
1770 } while (0)
1771""")
1772
1773 for version in of_g.of_version_range:
1774 for cls in of_g.standard_class_order:
1775 if not loxi_utils.class_in_version(cls, version):
1776 continue
1777 if cls in type_maps.inheritance_map:
1778 gen_dup_inheritance(out, cls, version)
1779 elif loxi_utils.class_is_list(cls):
1780 gen_dup_list(out, cls, version)
1781 else:
1782 gen_dup_cls(out, cls, version)
1783
1784def gen_dup(out=sys.stdout):
1785 """
1786 Generate non-version specific duplication routines for each object type
1787 """
1788
1789 for cls in of_g.standard_class_order:
1790 out.write("""
1791%(cls)s_t *
1792%(cls)s_dup(
1793 %(cls)s_t *src)
1794{
1795""" % dict(cls=cls))
1796 for version in of_g.of_version_range:
1797 if not loxi_utils.class_in_version(cls, version):
1798 continue
1799 hdr = "header." if cls in type_maps.inheritance_map else ""
1800
1801 ver_name = loxi_utils.version_to_name(version)
1802 out.write("""
1803 if (src->%(hdr)sversion == %(ver_name)s) {
1804 return %(cls)s_%(ver_name)s_dup(src);
1805 }
1806""" % dict(cls=cls, ver_name=ver_name, hdr=hdr))
1807
1808 out.write("""
1809 /* Class not supported in given version */
1810 return NULL;
1811}
1812""")
1813
1814def dup_c_gen(out, name):
1815 """
1816 Generate the C file for duplication functions
1817 """
1818 loxi_utils.gen_c_copy_license(out)
1819 out.write("""\
1820/*
1821 * Duplication functions for all OF objects
1822 *
1823 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1824 *
1825 * These are test functions for exercising accessors. You can call
1826 * of_object_dup for an efficient duplication.
1827 */
1828
1829#define DISABLE_WARN_UNUSED_RESULT
1830#include "loci_log.h"
1831#include <locitest/of_dup.h>
1832
1833""")
1834
1835 gen_version_dup(out)
1836 gen_dup(out)
1837
1838
1839def dup_h_gen(out, name):
1840 """
1841 Generate the header file for duplication functions
1842 """
1843
1844 loxi_utils.gen_c_copy_license(out)
1845 out.write("""
1846/*
1847 * Duplication function header file
1848 *
1849 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1850 */
1851
1852#if !defined(_OF_DUP_H_)
1853#define _OF_DUP_H_
1854
1855#include <loci/loci.h>
1856""")
1857
1858 for cls in of_g.standard_class_order:
1859 out.write("""
1860extern %(cls)s_t *
1861 %(cls)s_dup(
1862 %(cls)s_t *src);
1863""" % dict(cls=cls))
1864
1865 for version in of_g.of_version_range:
1866 for cls in of_g.standard_class_order:
1867 if not loxi_utils.class_in_version(cls, version):
1868 continue
1869 ver_name = loxi_utils.version_to_name(version)
1870 out.write("""
1871extern %(cls)s_t *
1872 %(cls)s_%(ver_name)s_dup(
1873 %(cls)s_t *src);
1874""" % dict(cls=cls, ver_name=ver_name))
1875
1876 out.write("\n#endif /* _OF_DUP_H_ */\n")
1877
1878def gen_log_test(out):
1879 """
1880 Generate test for obj log calls
1881
1882 Define a trivial handler for object logging; call all obj log fns
1883 """
1884 out.write("""
1885
1886/**
1887 * Test object dump functions
1888 */
1889
1890int
1891test_dump_objs(void)
1892{
1893 of_object_t *obj;
1894
1895 FILE *out = fopen("/dev/null", "w");
1896
1897 /* Call each obj dump function */
1898""")
1899 for version in of_g.of_version_range:
1900 for j, cls in enumerate(of_g.all_class_order):
1901 if not loxi_utils.class_in_version(cls, version):
1902 continue
1903 if cls in type_maps.inheritance_map:
1904 continue
1905 out.write("""
1906 obj = (of_object_t *)%(cls)s_new(%(version)s);
1907 of_object_dump((loci_writer_f)fprintf, out, obj);
1908 of_object_delete(obj);
1909""" % dict(cls=cls, version=of_g.of_version_wire2name[version]))
Andreas Wundsam53256162013-05-02 14:05:53 -07001910
Rich Lanea06d0c32013-03-25 08:52:03 -07001911 out.write("""
1912 fclose(out);
1913 return TEST_PASS;
1914}
1915""")
1916
1917def gen_ident_tests(out):
1918 """
1919 Generate tests for identifiers
1920
1921 For all idents, instantiate, test version supported macros
1922 For flags, set it, test it, clear it, test it.
1923 """
1924 out.write("""
1925/**
1926 * Test cases for all flag accessor macros
1927 * These only test self consistency (and that they compile)
1928 */
1929int
1930test_ident_macros(void)
1931{
1932 int value __attribute__((unused));
1933 uint32_t flags;
1934
1935""")
1936
1937 for ident, info in of_g.identifiers.items():
1938 if not identifiers.defined_versions_agree(of_g.identifiers,
1939 of_g.target_version_list,
1940 ident):
1941 # @fixme
1942 continue
1943 out.write(" value = %s;\n" % ident)
1944 for version in of_g.target_version_list:
1945 if version in info["values_by_version"].keys():
1946 out.write(" TEST_ASSERT(%s_SUPPORTED(%s));\n" %
1947 (ident, of_g.of_version_wire2name[version]))
1948 else:
1949 out.write(" TEST_ASSERT(!%s_SUPPORTED(%s));\n" %
1950 (ident, of_g.of_version_wire2name[version]))
1951 if flags.ident_is_flag(ident):
1952 # Grab first supported version
1953 for version in info["values_by_version"]:
1954 break
1955 out.write("""
1956 flags = 0;
1957 %(ident)s_SET(flags, %(ver_name)s);
1958 TEST_ASSERT(flags == %(ident)s_BY_VERSION(%(ver_name)s));
1959 TEST_ASSERT(%(ident)s_TEST(flags, %(ver_name)s));
1960 %(ident)s_CLEAR(flags, %(ver_name)s);
1961 TEST_ASSERT(flags == 0);
1962 TEST_ASSERT(!%(ident)s_TEST(flags, %(ver_name)s));
1963""" % dict(ident=ident, ver_name=of_g.of_version_wire2name[version]))
1964
1965 out.write("""
1966 return TEST_PASS;
1967}
1968""")
1969