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