diff options
| author | Christian Hopps <chopps@labn.net> | 2025-02-17 03:59:38 +0000 | 
|---|---|---|
| committer | Christian Hopps <chopps@labn.net> | 2025-02-26 13:38:42 +0000 | 
| commit | bce25cf43bca7b5bddd7126ab16e9018d8c9dbfa (patch) | |
| tree | 79a37c3c34c6dd0e2550f031ab543617899ff0bd | |
| parent | 656c4692a0f1bef9c213dda465d17a5455ea9b3a (diff) | |
tests: add oper test using existing libyang state tree
Signed-off-by: Christian Hopps <chopps@labn.net>
| -rw-r--r-- | tests/lib/northbound/test_oper_data.c | 26 | ||||
| -rw-r--r-- | tests/lib/northbound/test_oper_data.in | 2 | ||||
| -rw-r--r-- | tests/lib/northbound/test_oper_data.refout | 8 | ||||
| -rw-r--r-- | tests/lib/northbound/test_oper_exists.c | 266 | ||||
| -rw-r--r-- | tests/lib/northbound/test_oper_exists.in | 8 | ||||
| -rw-r--r-- | tests/lib/northbound/test_oper_exists.py | 5 | ||||
| -rw-r--r-- | tests/lib/northbound/test_oper_exists.refout | 208 | ||||
| -rw-r--r-- | tests/lib/subdir.am | 13 | ||||
| -rw-r--r-- | yang/frr-test-module.yang | 18 | 
9 files changed, 542 insertions, 12 deletions
diff --git a/tests/lib/northbound/test_oper_data.c b/tests/lib/northbound/test_oper_data.c index 0b334c6522..a38325173a 100644 --- a/tests/lib/northbound/test_oper_data.c +++ b/tests/lib/northbound/test_oper_data.c @@ -236,13 +236,9 @@ static int frr_test_module_vrfs_vrf_ping(struct nb_cb_rpc_args *args)  	return NB_OK;  } -/* - * XPath: /frr-test-module:frr-test-module/c1value - */ -static struct yang_data * -frr_test_module_c1value_get_elem(struct nb_cb_get_elem_args *args) +static struct yang_data *__return_null(struct nb_cb_get_elem_args *args)  { -	return yang_data_new_uint8(args->xpath, 21); +	return NULL;  }  /* @@ -263,6 +259,14 @@ static enum nb_error frr_test_module_c2cont_c2value_get(const struct nb_node *nb  	return NB_OK;  } +/* + * XPath: /frr-test-module:frr-test-module/c3value + */ +static struct yang_data *frr_test_module_c3value_get_elem(struct nb_cb_get_elem_args *args) +{ +	return yang_data_new_uint8(args->xpath, 21); +} +  /* clang-format off */  const struct frr_yang_module_info frr_test_module_info = {  	.name = "frr-test-module", @@ -316,13 +320,21 @@ const struct frr_yang_module_info frr_test_module_info = {  		},  		{  			.xpath = "/frr-test-module:frr-test-module/c1value", -			.cbs.get_elem = frr_test_module_c1value_get_elem, +			.cbs.get_elem = __return_null,  		},  		{  			.xpath = "/frr-test-module:frr-test-module/c2cont/c2value",  			.cbs.get = frr_test_module_c2cont_c2value_get,  		},  		{ +			.xpath = "/frr-test-module:frr-test-module/c3value", +			.cbs.get_elem = frr_test_module_c3value_get_elem, +		}, +		{ +			.xpath = "/frr-test-module:frr-test-module/c4cont/c4value", +			.cbs.get_elem = __return_null, +		}, +		{  			.xpath = NULL,  		},  	} diff --git a/tests/lib/northbound/test_oper_data.in b/tests/lib/northbound/test_oper_data.in index 94fcdc1e1c..bed83b8d74 100644 --- a/tests/lib/northbound/test_oper_data.in +++ b/tests/lib/northbound/test_oper_data.in @@ -2,7 +2,7 @@ show yang operational-data /frr-test-module:frr-test-module  show yang operational-data /frr-test-module:frr-test-module/vrfs/vrf[name='vrf0']/routes/route[2]  show yang operational-data /frr-test-module:frr-test-module/vrfs/vrf[name='vrf0']/routes/route[3]/interface  show yang operational-data /frr-test-module:frr-test-module/vrfs/vrf[name='vrf0']/routes/route[10] -show yang operational-data /frr-test-module:frr-test-module/c1value +show yang operational-data /frr-test-module:frr-test-module/c3value  show yang operational-data /frr-test-module:frr-test-module/c2cont  show yang operational-data /frr-test-module:frr-test-module/c2cont/  show yang operational-data /frr-test-module:frr-test-module/c2cont/c2value diff --git a/tests/lib/northbound/test_oper_data.refout b/tests/lib/northbound/test_oper_data.refout index 57061d0371..2feadf4b77 100644 --- a/tests/lib/northbound/test_oper_data.refout +++ b/tests/lib/northbound/test_oper_data.refout @@ -125,10 +125,10 @@ test# show yang operational-data /frr-test-module:frr-test-module          }
        ]
      },
 -    "c1value": 21,
      "c2cont": {
        "c2value": 2868969987
 -    }
 +    },
 +    "c3value": 21
    }
  }
  test# show yang operational-data /frr-test-module:frr-test-module/vrfs/vrf[name='vrf0']/routes/route[2] @@ -174,10 +174,10 @@ test# show yang operational-data /frr-test-module:frr-test-module/vrfs/vrf[name=  }
  test# show yang operational-data /frr-test-module:frr-test-module/vrfs/vrf[name='vrf0']/routes/route[10]  {}
 -test# show yang operational-data /frr-test-module:frr-test-module/c1value +test# show yang operational-data /frr-test-module:frr-test-module/c3value  {    "frr-test-module:frr-test-module": { -    "c1value": 21 +    "c3value": 21    }  }  test# show yang operational-data /frr-test-module:frr-test-module/c2cont diff --git a/tests/lib/northbound/test_oper_exists.c b/tests/lib/northbound/test_oper_exists.c new file mode 100644 index 0000000000..17afcc7fd4 --- /dev/null +++ b/tests/lib/northbound/test_oper_exists.c @@ -0,0 +1,266 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2018  NetDEF, Inc. + *                     Renato Westphal + * Copyright (C) 2025 LabN Consulting, L.L.C. + */ + +#include <zebra.h> +#include <sys/stat.h> + +#include "debug.h" +#include "frrevent.h" +#include "vty.h" +#include "command.h" +#include "memory.h" +#include "lib_vty.h" +#include "log.h" +#include "northbound.h" +#include "northbound_cli.h" + +static struct event_loop *master; +static struct lyd_node *data_tree; +static uint data_tree_lock; + +const char *data_json = "\n" +	"{\n" +	"  \"frr-test-module:frr-test-module\": {\n" +	"    \"vrfs\": {\n" +	"      \"vrf\": [\n" +	"	 {\n" +	"	   \"name\": \"vrf0\",\n" +	"	   \"interfaces\": {\n" +	"	     \"interface\": [\n" +	"		\"eth0\",\n" +	"		\"eth1\",\n" +	"		\"eth2\",\n" +	"		\"eth3\"\n" +	"	     ],\n" +	"	     \"interface-new\": [\n" +	"		\"eth0\",\n" +	"		\"eth1\",\n" +	"		\"eth2\",\n" +	"		\"eth3\"\n" +	"	     ]\n" +	"	   },\n" +	"	   \"routes\": {\n" +	"	     \"route\": [\n" +	"		{\n" +	"		  \"prefix\": \"10.0.0.0/32\",\n" +	"		  \"next-hop\": \"172.16.0.0\",\n" +	"		  \"interface\": \"eth0\",\n" +	"		  \"metric\": 0,\n" +	"		  \"active\": [null]\n" +	"		},\n" +	"		{\n" +	"		  \"prefix\": \"10.0.0.1/32\",\n" +	"		  \"next-hop\": \"172.16.0.1\",\n" +	"		  \"interface\": \"eth1\",\n" +	"		  \"metric\": 1\n" +	"		},\n" +	"		{\n" +	"		  \"prefix\": \"10.0.0.2/32\",\n" +	"		  \"next-hop\": \"172.16.0.2\",\n" +	"		  \"interface\": \"eth2\",\n" +	"		  \"metric\": 2,\n" +	"		  \"active\": [null]\n" +	"		},\n" +	"		{\n" +	"		  \"prefix\": \"10.0.0.3/32\",\n" +	"		  \"next-hop\": \"172.16.0.3\",\n" +	"		  \"interface\": \"eth3\",\n" +	"		  \"metric\": 3\n" +	"		},\n" +	"		{\n" +	"		  \"prefix\": \"10.0.0.4/32\",\n" +	"		  \"next-hop\": \"172.16.0.4\",\n" +	"		  \"interface\": \"eth4\",\n" +	"		  \"metric\": 4,\n" +	"		  \"active\": [null]\n" +	"		},\n" +	"		{\n" +	"		  \"prefix\": \"10.0.0.5/32\",\n" +	"		  \"next-hop\": \"172.16.0.5\",\n" +	"		  \"interface\": \"eth5\",\n" +	"		  \"metric\": 5\n" +	"		}\n" +	"	     ]\n" +	"	   }\n" +	"	 },\n" +	"	 {\n" +	"	   \"name\": \"vrf1\",\n" +	"	   \"interfaces\": {\n" +	"	     \"interface\": [\n" +	"		\"eth0\",\n" +	"		\"eth1\",\n" +	"		\"eth2\",\n" +	"		\"eth3\"\n" +	"	     ],\n" +	"	     \"interface-new\": [\n" +	"		\"eth0\",\n" +	"		\"eth1\",\n" +	"		\"eth2\",\n" +	"		\"eth3\"\n" +	"	     ]\n" +	"	   },\n" +	"	   \"routes\": {\n" +	"	     \"route\": [\n" +	"		{\n" +	"		  \"prefix\": \"10.0.0.0/32\",\n" +	"		  \"next-hop\": \"172.16.0.0\",\n" +	"		  \"interface\": \"eth0\",\n" +	"		  \"metric\": 0,\n" +	"		  \"active\": [null]\n" +	"		},\n" +	"		{\n" +	"		  \"prefix\": \"10.0.0.1/32\",\n" +	"		  \"next-hop\": \"172.16.0.1\",\n" +	"		  \"interface\": \"eth1\",\n" +	"		  \"metric\": 1\n" +	"		},\n" +	"		{\n" +	"		  \"prefix\": \"10.0.0.2/32\",\n" +	"		  \"next-hop\": \"172.16.0.2\",\n" +	"		  \"interface\": \"eth2\",\n" +	"		  \"metric\": 2,\n" +	"		  \"active\": [null]\n" +	"		},\n" +	"		{\n" +	"		  \"prefix\": \"10.0.0.3/32\",\n" +	"		  \"next-hop\": \"172.16.0.3\",\n" +	"		  \"interface\": \"eth3\",\n" +	"		  \"metric\": 3\n" +	"		},\n" +	"		{\n" +	"		  \"prefix\": \"10.0.0.4/32\",\n" +	"		  \"next-hop\": \"172.16.0.4\",\n" +	"		  \"interface\": \"eth4\",\n" +	"		  \"metric\": 4,\n" +	"		  \"active\": [null]\n" +	"		},\n" +	"		{\n" +	"		  \"prefix\": \"10.0.0.5/32\",\n" +	"		  \"next-hop\": \"172.16.0.5\",\n" +	"		  \"interface\": \"eth5\",\n" +	"		  \"metric\": 5\n" +	"		}\n" +	"	     ]\n" +	"	   }\n" +	"	 }\n" +	"      ]\n" +	"    },\n" +	"    \"c2cont\": {\n" +	"      \"c2value\": 2868969987\n" +	"    },\n" +	"    \"c3value\": 21\n" +	"  }\n" +	"}\n"; + + +static const struct lyd_node *test_oper_get_tree_locked(const char *xpath) +{ +	++data_tree_lock; +	return data_tree; +} + +static void test_oper_unlock_tree(const struct lyd_node *tree __attribute__((unused))) +{ +	data_tree_lock--; +} + +static int __rpc_return_ok(struct nb_cb_rpc_args *args) +{ +	return NB_OK; +} + +/* clang-format off */ +const struct frr_yang_module_info frr_test_module_info = { +	.name = "frr-test-module", +	.get_tree_locked = test_oper_get_tree_locked, +	.unlock_tree = test_oper_unlock_tree, +	.nodes = { +		{ +			.xpath = "/frr-test-module:frr-test-module/vrfs/vrf/ping", +			.cbs.rpc = __rpc_return_ok, +		}, +		{ +			.xpath = NULL, +		}, +	} +}; +/* clang-format on */ + +static const struct frr_yang_module_info *const modules[] = { +	&frr_test_module_info, +}; + +static void vty_do_exit(int isexit) +{ +	printf("\nend.\n"); + +	lyd_free_all(data_tree); + +	cmd_terminate(); +	vty_terminate(); +	nb_terminate(); +	yang_terminate(); +	event_master_free(master); + +	log_memstats(NULL, true); +	if (!isexit) +		exit(0); +} + + +static struct lyd_node *load_data(void) +{ +	struct ly_in *in = NULL; +	struct lyd_node *tree = NULL; +	LY_ERR err; + +	err = ly_in_new_memory(data_json, &in); +	if (!err) +		err = lyd_parse_data(ly_native_ctx, NULL, in, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_OPERATIONAL, &tree); +	ly_in_free(in, 0); +	if (err) { +		fprintf(stderr, "LYERR: %s\n", getcwd(NULL, 0)); +		fprintf(stderr, "LYERR: %s\n", ly_last_errmsg()); +		exit(1); +	} +	return tree; +} + +/* main routine. */ +int main(int argc, char **argv) +{ +	struct event thread; + +	/* Set umask before anything for security */ +	umask(0027); + +	/* master init. */ +	master = event_master_create(NULL); + +	// zlog_aux_init("NONE: ", ZLOG_DISABLED); + +	/* Library inits. */ +	cmd_init(1); +	cmd_hostname_set("test"); +	vty_init(master, false); +	lib_cmd_init(); +	debug_init(); +	nb_init(master, modules, array_size(modules), false, false); + +	/* Create artificial data. */ +	data_tree = load_data(); + +	/* Read input from .in file. */ +	vty_stdio(vty_do_exit); + +	/* Fetch next active thread. */ +	while (event_fetch(master, &thread)) +		event_call(&thread); + +	/* Not reached. */ +	exit(0); +} diff --git a/tests/lib/northbound/test_oper_exists.in b/tests/lib/northbound/test_oper_exists.in new file mode 100644 index 0000000000..7b83c27a0b --- /dev/null +++ b/tests/lib/northbound/test_oper_exists.in @@ -0,0 +1,8 @@ +show yang operational-data /frr-test-module:frr-test-module +show yang operational-data /frr-test-module:frr-test-module/vrfs/vrf[name='vrf0']/routes/route[2] +show yang operational-data /frr-test-module:frr-test-module/vrfs/vrf[name='vrf0']/routes/route[3]/interface +show yang operational-data /frr-test-module:frr-test-module/vrfs/vrf[name='vrf0']/routes/route[10] +show yang operational-data /frr-test-module:frr-test-module/c3value +show yang operational-data /frr-test-module:frr-test-module/c2cont +show yang operational-data /frr-test-module:frr-test-module/c2cont/ +show yang operational-data /frr-test-module:frr-test-module/c2cont/c2value diff --git a/tests/lib/northbound/test_oper_exists.py b/tests/lib/northbound/test_oper_exists.py new file mode 100644 index 0000000000..423414eb85 --- /dev/null +++ b/tests/lib/northbound/test_oper_exists.py @@ -0,0 +1,5 @@ +import frrtest + + +class TestNbOperData(frrtest.TestRefOut): +    program = "./test_oper_exists" diff --git a/tests/lib/northbound/test_oper_exists.refout b/tests/lib/northbound/test_oper_exists.refout new file mode 100644 index 0000000000..4060a096fd --- /dev/null +++ b/tests/lib/northbound/test_oper_exists.refout @@ -0,0 +1,208 @@ +test# show yang operational-data /frr-test-module:frr-test-module +{ +  "frr-test-module:frr-test-module": { +    "vrfs": { +      "vrf": [ +        { +          "name": "vrf0", +          "interfaces": { +            "interface": [ +              "eth0", +              "eth1", +              "eth2", +              "eth3" +            ], +            "interface-new": [ +              "eth0", +              "eth1", +              "eth2", +              "eth3" +            ] +          }, +          "routes": { +            "route": [ +              { +                "prefix": "10.0.0.0/32", +                "next-hop": "172.16.0.0", +                "interface": "eth0", +                "metric": 0, +                "active": [null] +              }, +              { +                "prefix": "10.0.0.1/32", +                "next-hop": "172.16.0.1", +                "interface": "eth1", +                "metric": 1 +              }, +              { +                "prefix": "10.0.0.2/32", +                "next-hop": "172.16.0.2", +                "interface": "eth2", +                "metric": 2, +                "active": [null] +              }, +              { +                "prefix": "10.0.0.3/32", +                "next-hop": "172.16.0.3", +                "interface": "eth3", +                "metric": 3 +              }, +              { +                "prefix": "10.0.0.4/32", +                "next-hop": "172.16.0.4", +                "interface": "eth4", +                "metric": 4, +                "active": [null] +              }, +              { +                "prefix": "10.0.0.5/32", +                "next-hop": "172.16.0.5", +                "interface": "eth5", +                "metric": 5 +              } +            ] +          } +        }, +        { +          "name": "vrf1", +          "interfaces": { +            "interface": [ +              "eth0", +              "eth1", +              "eth2", +              "eth3" +            ], +            "interface-new": [ +              "eth0", +              "eth1", +              "eth2", +              "eth3" +            ] +          }, +          "routes": { +            "route": [ +              { +                "prefix": "10.0.0.0/32", +                "next-hop": "172.16.0.0", +                "interface": "eth0", +                "metric": 0, +                "active": [null] +              }, +              { +                "prefix": "10.0.0.1/32", +                "next-hop": "172.16.0.1", +                "interface": "eth1", +                "metric": 1 +              }, +              { +                "prefix": "10.0.0.2/32", +                "next-hop": "172.16.0.2", +                "interface": "eth2", +                "metric": 2, +                "active": [null] +              }, +              { +                "prefix": "10.0.0.3/32", +                "next-hop": "172.16.0.3", +                "interface": "eth3", +                "metric": 3 +              }, +              { +                "prefix": "10.0.0.4/32", +                "next-hop": "172.16.0.4", +                "interface": "eth4", +                "metric": 4, +                "active": [null] +              }, +              { +                "prefix": "10.0.0.5/32", +                "next-hop": "172.16.0.5", +                "interface": "eth5", +                "metric": 5 +              } +            ] +          } +        } +      ] +    }, +    "c2cont": { +      "c2value": 2868969987 +    }, +    "c3value": 21 +  } +} +test# show yang operational-data /frr-test-module:frr-test-module/vrfs/vrf[name='vrf0']/routes/route[2] +{ +  "frr-test-module:frr-test-module": { +    "vrfs": { +      "vrf": [ +        { +          "name": "vrf0", +          "routes": { +            "route": [ +              { +                "prefix": "10.0.0.1/32", +                "next-hop": "172.16.0.1", +                "interface": "eth1", +                "metric": 1 +              } +            ] +          } +        } +      ] +    } +  } +} +test# show yang operational-data /frr-test-module:frr-test-module/vrfs/vrf[name='vrf0']/routes/route[3]/interface +{ +  "frr-test-module:frr-test-module": { +    "vrfs": { +      "vrf": [ +        { +          "name": "vrf0", +          "routes": { +            "route": [ +              { +                "interface": "eth2" +              } +            ] +          } +        } +      ] +    } +  } +} +test# show yang operational-data /frr-test-module:frr-test-module/vrfs/vrf[name='vrf0']/routes/route[10] +{} +test# show yang operational-data /frr-test-module:frr-test-module/c3value +{ +  "frr-test-module:frr-test-module": { +    "c3value": 21 +  } +} +test# show yang operational-data /frr-test-module:frr-test-module/c2cont +{ +  "frr-test-module:frr-test-module": { +    "c2cont": { +      "c2value": 2868969987 +    } +  } +} +test# show yang operational-data /frr-test-module:frr-test-module/c2cont/ +{ +  "frr-test-module:frr-test-module": { +    "c2cont": { +      "c2value": 2868969987 +    } +  } +} +test# show yang operational-data /frr-test-module:frr-test-module/c2cont/c2value +{ +  "frr-test-module:frr-test-module": { +    "c2cont": { +      "c2value": 2868969987 +    } +  } +} +test#  +end. diff --git a/tests/lib/subdir.am b/tests/lib/subdir.am index 1a21684f16..ca74306543 100644 --- a/tests/lib/subdir.am +++ b/tests/lib/subdir.am @@ -131,6 +131,19 @@ EXTRA_DIST += \  	# end +check_PROGRAMS += tests/lib/northbound/test_oper_exists +tests_lib_northbound_test_oper_exists_CFLAGS = $(TESTS_CFLAGS) +tests_lib_northbound_test_oper_exists_CPPFLAGS = $(TESTS_CPPFLAGS) +tests_lib_northbound_test_oper_exists_LDADD = $(ALL_TESTS_LDADD) +tests_lib_northbound_test_oper_exists_SOURCES = tests/lib/northbound/test_oper_exists.c +nodist_tests_lib_northbound_test_oper_exists_SOURCES = yang/frr-test-module.yang.c +EXTRA_DIST += \ +	tests/lib/northbound/test_oper_exists.in \ +	tests/lib/northbound/test_oper_exists.py \ +	tests/lib/northbound/test_oper_exists.refout \ +	# end + +  check_PROGRAMS += tests/lib/test_assert  tests_lib_test_assert_CFLAGS = $(TESTS_CFLAGS)  tests_lib_test_assert_CPPFLAGS = $(TESTS_CPPFLAGS) diff --git a/yang/frr-test-module.yang b/yang/frr-test-module.yang index 773a959553..909c199b2f 100644 --- a/yang/frr-test-module.yang +++ b/yang/frr-test-module.yang @@ -139,5 +139,23 @@ module frr-test-module {          }        }      } +    choice bchoice { +      description "a choice statement"; +      case case3 { +        leaf c3value { +          type uint8; +          description "A uint8 value for case 3"; +        } +      } +      case case4 { +        container c4cont { +          description "case 2 container"; +          leaf c4value { +            type uint32; +            description "A uint32 value for case 4"; +          } +        } +      } +    }    }  }  | 
