diff --git a/test/README.md b/test/README.md new file mode 100644 index 0000000..6f2871b --- /dev/null +++ b/test/README.md @@ -0,0 +1,70 @@ +## Tox/pytest testing + +The directory `unit` contains tests that do not require DrNED to be installed +and do not start NSO; they require NSO and in particular its Python API to be +installed though (FIXME: this dependency is planned to be removed). + +The tests are not actual unit tests, they try to test the code end-to-end, but +with as few external dependencies as possible. In particular, they use `mock` +and `pyfakefs` modules to mock NSO libraries or system calls. As a result, no +NSO instance is started or needs to be running, no device or device simulator +is required, and the filesystem is not changed. + +### Using tox + +You can run tests using [tox](https://pypi.org/project/tox/); for that you need +to have `tox` itself, and an NSO installation pointed to by `NCS_DIR`. Also, +the project must have been compiled (namely, the generated Python namespace +module needs to exist). + +``` +$ tox +... (some output) + py27: commands succeeded + py36: commands succeeded + congratulations :) +$ +``` + +### Using pytest alone + +You can use `pytest` directly and select only a subset of tests. All +requirements are in `requirements.txt`, so you can do + +``` +$ pip install -r requirements.txt +``` + +- this should install everything that is needed. Apart from that, your +PYTHONPATH should point to NSO Python API and to the code itself, e.g. + +``` +$ export PYTHONPATH=$NCS_DIR/ncs/src/ncs/pyapi:../../python +$ pytest +... +$ pytest -v -k test_filter +... +$ +``` + +## Lux testing + +The directory `lux` contains one test case that tries to verify that basic +integration with NSO and DrNED works. The prerequisites are: + + * DrNED must be installed and the environment variable `DRNED` points to the + installation directory + * `PYTHONPATH` must point to NSO Python API + * several additional Python packages need to be installed, see + `requirements.txt` + +When this is set correctly, run + +``` +$ lux basic.lux +... +successful : 1 +summary : SUCCESS +... +$ +``` diff --git a/test/lux/basic.lux b/test/lux/basic.lux new file mode 100644 index 0000000..dafb1b8 --- /dev/null +++ b/test/lux/basic.lux @@ -0,0 +1,136 @@ +[doc Testing DrNED-XMNR integration with NCS and DrNED] +[config timeout=2000] + +[macro shell-check] + !echo ==$?== + ?==0== +[endmacro] + +[shell os] + !rm -rf ncs-run + [progress prepare ncs-run and packages] + !ncs-project create ncs-run + [invoke shell-check] + !cd ncs-run/packages + [invoke shell-check] + !ln -s ../../../../ drned-xmnr + !file drned-xmnr + ?drned-xmnr: symbolic link to .* + !file drned-xmnr/python + ?drned-xmnr/python: directory + !echo `dirname $$PWD` + !ncs-make-package --netconf-ned ../../yang ned + [invoke shell-check] + !make -C drned-xmnr/src all + [invoke shell-check] + !make -C ned/src all + [invoke shell-check] + [progress create and start the netsim] + !cd .. + !ncs-netsim delete-network + !ncs-netsim create-network packages/ned 1 ned + [invoke shell-check] + !ncs-netsim start + [invoke shell-check] + [progress start ncs] + [timeout 10] + !ncs --stop; ncs + [invoke shell-check] + [timeout] + +[shell ncs-cli] + -[Ee][Rr][Rr][Oo][Rr] + !ncs_cli -u admin -C + ???admin@ncs# + !config + [progress set up the NCS device] + # clean up, if there is anything left from previous runs + !no devices device dhcp + # set up python-vm logging to see any problems + !python-vm logging level level-debug + !commit + ???Commit complete. + !devices device dhcp + ???admin@ncs(config-device-dhcp)# + """! + address 127.0.0.1 + port 12022 + device-type netconf + authgroup default + state admin-state unlocked + ssh fetch-host-keys + """ + !commit + ???Commit complete. + !sync-from + !no config + !commit + ?Commit complete|No modifications to commit + [progress setup xmnr] + !drned-xmnr setup setup-xmnr overwrite true + ???success + [progress record states] + !drned-xmnr state record-state state-name empty + ???success + !config dhcp defaultLeaseTime 200s + !commit + ???Commit complete. + !drned-xmnr state record-state state-name time + ???success + !config dhcp SharedNetworks sharedNetwork test SubNets subNet 1.1.1.1 255.255.255.0 + !commit + ???Commit complete. + !drned-xmnr state record-state state-name subnet + ???success + [progress walk states] + [timeout 10] + !drned-xmnr transitions walk-states states [ empty subnet time ] + """??? + Prepare the device + Test transition to empty + load empty + commit + succeeded + compare config + succeeded + rollback + commit + succeeded + compare config + succeeded + Test transition to subnet + load subnet + commit + (no modifications) + compare config + succeeded + rollback + commit + (no modifications) + compare config + succeeded + Test transition to time + load time + commit + succeeded + compare config + succeeded + rollback + commit + succeeded + compare config + succeeded + commit + (no modifications) + compare config + succeeded + success Completed successfully + """ + +[cleanup] + !cd ncs-run + ?SH-PROMPT: + !ncs --stop + ?SH-PROMPT: + !ncs-netsim stop + ?SH-PROMPT: diff --git a/test/lux/requirements.txt b/test/lux/requirements.txt new file mode 100644 index 0000000..d3fbdc5 --- /dev/null +++ b/test/lux/requirements.txt @@ -0,0 +1,5 @@ +pytest +pexpect +lxml +requests +paramiko diff --git a/test/lux/yang/dhcpd.yang b/test/lux/yang/dhcpd.yang new file mode 100644 index 0000000..f3ff4b0 --- /dev/null +++ b/test/lux/yang/dhcpd.yang @@ -0,0 +1,89 @@ +module dhcpd { + + namespace "http://tail-f.com/ns/example/dhcpd"; + prefix dhcpd; + + import ietf-inet-types { + prefix inet; + } + + import tailf-xsd-types { + prefix xs; + } + + typedef loglevel { + type enumeration { + enum kern; + enum mail; + enum local7; + } + } + + grouping subNet { + list subNet { + key "net mask"; + leaf net { + type inet:ipv4-address; + } + leaf mask { + type inet:ipv4-address; + } + container range { + presence ""; + leaf dynamicBootP { + type boolean; + default false; + description "Enable BOOTP for this instance."; + } + leaf lowAddr { + type inet:ipv4-address; + mandatory true; + description "Enable BOOTP for this instance."; + } + leaf hiAddr { + type inet:ipv4-address; + description "Enable BOOTP for this instance."; + } + } + leaf routers { + type string; + } + leaf maxLeaseTime { + type xs:duration; + default PT7200S; + } + } + } + + + + container dhcp { + leaf defaultLeaseTime { + type xs:duration; + default PT600S; + } + leaf maxLeaseTime { + type xs:duration; + default PT7200S; + } + leaf logFacility { + type loglevel; + default local7; + } + container SubNets { + uses subNet; + } + container SharedNetworks { + list sharedNetwork { + key name; + max-elements 1024; + leaf name { + type string; + } + container SubNets { + uses subNet ; + } + } + } + } +}