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