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