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