diff --git a/meta/gensairpc.pl b/meta/gensairpc.pl index 6a05e182a..402b8fdb3 100755 --- a/meta/gensairpc.pl +++ b/meta/gensairpc.pl @@ -90,6 +90,7 @@ [ 'verbose|v', 'Print more details', { default => 0 } ], [ 'mandatory-attrs', 'Make mandatory attributes obligatory in sai_adapter.py', { default => 0 } ], [ 'dev-utils:s', 'Generate additional development utils within the generated code. Additional options: [=log,zero]', { default => 0 } ], + [ 'skip_error:s', 'Skip test on specified error code. Additional options: [=-2]', { default => 0 } ], [ 'attr-header', 'Generate additional header of attributes definitions (including object types)', { default => 0 } ], [ 'help|h', 'Print this help', { shortcircuit => 1 } ], ); @@ -114,6 +115,7 @@ my $clean = $args->clean_meta; my $mandatory_attrs = $args->mandatory_attrs; my $dev_utils = ( $args->dev_utils ne q{} ? $args->dev_utils : 1 ); +my $skip_error = ( $args->skip_error ne q{} ? $args->skip_error : 1 ); my $attr_header = $args->attr_header; # Configure SAI meta @@ -159,6 +161,7 @@ dbg => $dbg, mandatory_attrs => $mandatory_attrs, dev_utils => $dev_utils, + skip_error => $skip_error, templates_dir => $templates_dir }; diff --git a/meta/rpc/README.md b/meta/rpc/README.md index 2963b7f5b..9cfcb4b3a 100644 --- a/meta/rpc/README.md +++ b/meta/rpc/README.md @@ -19,6 +19,7 @@ Optional arguments are useful for development purposes. | `-d` `--dump` | Dump all data to the file. **Should be used during development**. | | `--mandatory-attrs` | Make mandatory attributes obligatory in *sai\_adapter.py*. It removes `=None` from attributes, which are passed as arguments into python functions. Can be useful for debugging purposes, but since most of attributes are **optionally** mandatory, this is not as useful as it could be. | | `--dev-utils[=STR]` | Generate additional development utils within the generated code. Additional options: [=log,zero]. Useful for tests development and debugging. The generated code **should not** be committed. | +| `--skip_error[=STR]` | Skip test on specified error code. Additional options: [=-2]. The generated code **should not** be committed. | | `-h` `--help` | Print the help. | *gensairpc.pl* development diff --git a/meta/templates/sai_adapter.py.tt b/meta/templates/sai_adapter.py.tt index 57df542b3..a5df12140 100644 --- a/meta/templates/sai_adapter.py.tt +++ b/meta/templates/sai_adapter.py.tt @@ -93,6 +93,15 @@ def [% function.thrift_name %](client [%- FOREACH attr IN apis.$api.objects.${function.object}.attrs.${function.operation} -%] ,[% br %][% attr.simple_name %]=None [%- END -%] + [%- IF function.operation == 'stats' OR function.operation == 'clear' -%] + [%- FOREACH arg IN function.adapter_preprocessed_args -%] + [%- IF arg.is_list and arg.name == 'counter_ids' -%] +,[% br %][% arg.name %]=[% function.name %]_[% arg.name %] + [%- ELSIF arg.is_attr %] + [% arg.name %] = None + [%- END -%] + [%- END -%] + [%- END -%] ): [% END -%] @@ -103,7 +112,7 @@ def [% function.thrift_name %](client [%- # but are required by thritft functions -%] [%- FOREACH arg IN function.adapter_preprocessed_args -%] - [%- IF arg.is_list %] + [%- IF arg.is_list AND arg.name!= 'counter_ids' %] [% arg.name %] = [] [%- ELSIF arg.is_attr %] [% arg.name %] = None @@ -111,6 +120,25 @@ def [% function.thrift_name %](client [%- END -%] [%- END -%] +[%- BLOCK declare_stats_variables -%] + [%- IF function.operation == 'stats' OR function.operation == 'clear' %] + [%- FOREACH arg IN function.adapter_preprocessed_args -%] + + [%- IF arg.is_list %] +[% function.name %]_[% arg.name %] = [] +[% function.name %]_[% arg.name %]_dict = dict() + [%- ELSIF arg.is_attr %] + [% arg.name %] = None + [%- END -%] + [%- END -%] + [%- FOREACH stat IN apis.$api.objects.${function.object}.stats.all %] +[% function.name %]_[% arg.name %].append([% stat.name %]) +[% function.name %]_[% arg.name %]_dict[[% stat.name %]] = "[% stat.name %]" + [%- END -%] + + [%- END -%] +[%- END -%] + [%- ######################################################################## -%] [%- ######################################################################## -%] @@ -240,6 +268,7 @@ client.[% function.thrift_name %]( [%- BLOCK preprocess_attributes %] [%- # For 'set attr' function we just do call the funtion for first argument -%] [%- IF function.operation == 'set' -%] + global status status = SAI_STATUS_SUCCESS @@ -279,8 +308,10 @@ client.[% function.thrift_name %]( [%- BLOCK preprocess_stats -%] - [%- FOREACH stat IN apis.$api.objects.${function.object}.stats.all %] - [% arg.name %].append([% stat.name %]) + [%- IF arg.name != "counter_ids" -%] + [%- FOREACH stat IN apis.$api.objects.${function.object}.stats.all %] + [% function.name %]_[% arg.name %].append([% stat.name %]) + [%- END -%] [%- END -%] [%- END -%] @@ -292,11 +323,9 @@ client.[% function.thrift_name %]( [%- BLOCK postprocess_stats %] stats = dict() - [%- i = 0 %] - [%- FOREACH stat IN apis.$api.objects.${function.object}.stats.all %] - stats["[% stat.name %]"] = [% function.rpc_return.name %][[% i %]] - [%- i = i + 1 -%] - [%- END %] + for index, item in enumerate(counter_ids): + stats[[% function.name %]_[% arg.name %]_dict[item]] = counters[index] + [%- END -%] @@ -308,13 +337,11 @@ client.[% function.thrift_name %]( [%- # Basically we do it for each list variable, we assume we have one -%] [%- FOREACH arg IN function.adapter_preprocessed_args -%] [%- IF function.operation == 'stats' OR function.operation == 'clear' %] - [%- # For 'get stats' function create stats list -%] + [%- # For 'get stats' function NOT create stats list in function body -%] [%- PROCESS preprocess_stats %] - [%- ELSIF function.operation != 'remove' %] [%- # For 'create' and 'get' functions create list of arguments -%] [%- PROCESS preprocess_attributes %] - [%- END -%] [%- END -%] @@ -400,17 +427,21 @@ client.[% function.thrift_name %]( [%- ######################################################################## -%] [%- BLOCK function_body -%] + [%- PROCESS declare_stats_variables -%] + + [%- PROCESS decorate_method IF dev_utils -%] + [%- PROCESS decorate_skip_test_on_error IF skip_error -%] [%- PROCESS function_header %] [%- PROCESS function_docstring %] [%- IF has_body -%] [%- PROCESS declare_variables %] - [%- PROCESS preprocess_args -%] [%- # Now, call the thrift function -%] [%- IF function.operation != 'set' -%] + global status status = SAI_STATUS_SUCCESS @@ -457,6 +488,7 @@ Thrift SAI interface basic tests # pylint: disable=too-many-return-statements,line-too-long,invalid-name [%- PROCESS dev_utils_imports IF dev_utils -%] +[%- PROCESS skip_test_on_error_imports IF skip_error -%] from sai_thrift.ttypes import * from sai_thrift.sai_headers import * @@ -472,6 +504,7 @@ CATCH_EXCEPTIONS = True status = 0 [%- PROCESS dev_utils IF dev_utils -%] +[%- PROCESS skip_error IF skip_error -%] [%- FOREACH api IN apis.keys.sort -%] [%- IF apis.$api.functions.size %] diff --git a/meta/templates/sai_adapter_utils.tt b/meta/templates/sai_adapter_utils.tt index fbe9748ee..05ecb5e3d 100644 --- a/meta/templates/sai_adapter_utils.tt +++ b/meta/templates/sai_adapter_utils.tt @@ -4,7 +4,13 @@ from __future__ import print_function from collections import defaultdict from collections import Counter +[% IF NOT skip_error %]from functools import wraps[% END %] +[% END -%] + +[%- BLOCK skip_test_on_error_imports %] from functools import wraps +from unittest import SkipTest +from ptf import testutils [% END -%] [%- ######################################################################## -%] @@ -18,6 +24,13 @@ from functools import wraps [% PROCESS instance_counter %] [% END -%] +[%- BLOCK skip_error %] + +# skip_error + +[% PROCESS skip_test_on_error %] +[% END -%] + [%- ######################################################################## -%] [%- ######################################################################## -%] @@ -161,6 +174,39 @@ instance_counter.removed = defaultdict(Counter) instance_counter.not_removed = defaultdict(Counter) [%- END -%] +[%- BLOCK skip_test_on_error -%] +def skip_test_on_error(errorcode=[-2]): + def skip_test_on_error_decorator(func): + """ + Decorator for skip the test when error happened. + Args: + errorcode: a list of the error code that test will be skipped. + """ + + @wraps(func) + def decorated(*args, **kwargs): + """ + Check the return value and check if the status is the error code + on which the test should be skipped. + + Args: + args(List): original args + kwargs(Dict): original kwargs + Returns: + retval(Any): the original return value + """ + retval = func(*args, **kwargs) + global status + if status in errorcode: + reason = "SkipTest: {} with errorcode: {}".format(func.__name__, status) + print(reason) + testutils.skipped_test_count=1 + raise SkipTest(reason) + return retval + return decorated + return skip_test_on_error_decorator +[%- END -%] + [%- ######################################################################## -%] [%- ######################################################################## -%] @@ -169,4 +215,8 @@ instance_counter.not_removed = defaultdict(Counter) @instance_counter("[% function.object %]", "[% function.operation %]"[% IF dev_utils.match('log') %], log=True[% END %][% IF dev_utils.match('zero') %], zero=True[% END %]) [%- END -%] +[%- BLOCK decorate_skip_test_on_error %] +@skip_test_on_error([% IF skip_error %]errorcode=[[% skip_error %]][% END %]) +[%- END -%] + [%- ######################################################################## -%]