diff options
author | Rob Johnston <rob.johnston@joyent.com> | 2020-02-20 16:38:42 -0800 |
---|---|---|
committer | Dan McDonald <danmcd@joyent.com> | 2020-04-03 15:03:01 -0400 |
commit | c559157643fef9f9afb0414e00a3579407ba3052 (patch) | |
tree | 108a39e69361244fbd351d0ad1994bc50c3f6025 /usr/src/test/os-tests | |
parent | 3afb2a2ae94e9183977495f0d248b766e58e4016 (diff) | |
download | illumos-gate-c559157643fef9f9afb0414e00a3579407ba3052.tar.gz |
12330 libtopo: add support for directed graph based topologies
Portions contributed by: Kody Kantor <kody.kantor@joyent.com>
Reviewed by: Robert Mustacchi <rm@fingolfin.org>
Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src/test/os-tests')
9 files changed, 923 insertions, 0 deletions
diff --git a/usr/src/test/os-tests/runfiles/default.run b/usr/src/test/os-tests/runfiles/default.run index 650f023d77..f3f7c14a0e 100644 --- a/usr/src/test/os-tests/runfiles/default.run +++ b/usr/src/test/os-tests/runfiles/default.run @@ -90,3 +90,7 @@ arch = i86pc [/opt/os-tests/tests/uccid] arch = i86pc tests = ['atrparse'] + +[/opt/os-tests/tests/libtopo] +user = root +tests = ['digraph-test'] diff --git a/usr/src/test/os-tests/tests/Makefile b/usr/src/test/os-tests/tests/Makefile index f923125d5e..37c9a2029f 100644 --- a/usr/src/test/os-tests/tests/Makefile +++ b/usr/src/test/os-tests/tests/Makefile @@ -19,6 +19,7 @@ SUBDIRS_i386 = i386 imc SUBDIRS = \ ddi_ufm \ file-locking \ + libtopo \ pf_key \ poll \ sdevfs \ diff --git a/usr/src/test/os-tests/tests/libtopo/Makefile b/usr/src/test/os-tests/tests/libtopo/Makefile new file mode 100644 index 0000000000..8b7fe43bb7 --- /dev/null +++ b/usr/src/test/os-tests/tests/libtopo/Makefile @@ -0,0 +1,58 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2020 Joyent, Inc. +# + +include $(SRC)/Makefile.master + +ROOTOPTPKG = $(ROOT)/opt/os-tests +TESTDIR = $(ROOTOPTPKG)/tests/libtopo + +PROGS = digraph-test + +XML = digraph-test-in.xml \ + digraph-test-in-badscheme.xml \ + digraph-test-in-badnum.xml \ + digraph-test-in-badedge.xml \ + digraph-test-in-badelement.xml + +include $(SRC)/cmd/Makefile.cmd +include $(SRC)/test/Makefile.com + +LDLIBS += -L$(ROOT)/usr/lib/fm -ltopo -R/usr/lib/fm +CFLAGS += -I$(SRC)/lib/fm/topo/libtopo/ +CSTD= $(CSTD_GNU99) + +CMDS = $(PROGS:%=$(TESTDIR)/%) +$(CMDS) := FILEMODE = 0555 + +FILES = $(XML:%=$(TESTDIR)/%) +$(FILES) := FILEMODE = 0444 + +all: $(PROGS) + +install: all $(CMDS) $(FILES) + +clobber: clean + -$(RM) $(PROGS) $(FILES) + +clean: + -$(RM) *.o + +$(CMDS): $(TESTDIR) $(PROGS) + +$(TESTDIR): + $(INS.dir) + +$(TESTDIR)/%: % + $(INS.file) diff --git a/usr/src/test/os-tests/tests/libtopo/digraph-test-in-badedge.xml b/usr/src/test/os-tests/tests/libtopo/digraph-test-in-badedge.xml new file mode 100644 index 0000000000..db86874817 --- /dev/null +++ b/usr/src/test/os-tests/tests/libtopo/digraph-test-in-badedge.xml @@ -0,0 +1,46 @@ +<?xml version="1.0"?> +<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/digraph-topology.dtd.1"> + +<!-- + Copyright 2020 Joyent, Inc. + +--> + +<topo-digraph fmri-scheme='hc' nodename='test-nodename' os-version='test-os-version' product-id='test-product-id' timestamp='2019-12-20T01:51:26Z'> +<vertices> +<vertex name='node' instance='0x0' fmri='hc:///node=0'> + + <nvpair name='property-groups' type='nvlist-array'> + <nvlist> + <nvpair name='property-group-name' type='string' value='protocol' /> + <nvpair name='property-values' type='nvlist-array'> + <nvlist> + <nvpair name='property-name' type='string' value='resource' /> + <nvpair name='property-type' type='uint32' value='9' /> + <nvpair name='property-value' type='nvlist'> + <nvlist> + <nvpair name='scheme' type='string' value='hc' /> + <nvpair name='version' type='uint8' value='0' /> + <nvpair name='hc-list' type='nvlist-array'> + <nvlist> + <nvpair name='hc-name' type='string' value='node' /> + <nvpair name='hc-id' type='string' value='0' /> + </nvlist> + </nvpair> + </nvlist> + </nvpair> <!-- property-value --> + </nvlist> + </nvpair> <!-- property-values --> + </nvlist> + + </nvpair> <!-- property-groups --> + + <outgoing-edges> + <!-- non-existent edge --> + <edge fmri='hc:///node=1' /> + </outgoing-edges> + +</vertex> + +</vertices> +</topo-digraph> diff --git a/usr/src/test/os-tests/tests/libtopo/digraph-test-in-badelement.xml b/usr/src/test/os-tests/tests/libtopo/digraph-test-in-badelement.xml new file mode 100644 index 0000000000..374bcc85cc --- /dev/null +++ b/usr/src/test/os-tests/tests/libtopo/digraph-test-in-badelement.xml @@ -0,0 +1,42 @@ +<?xml version="1.0"?> +<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/digraph-topology.dtd.1"> + +<!-- + Copyright 2020 Joyent, Inc. + +--> + +<topo-digraph fmri-scheme='hc' nodename='test-nodename' os-version='test-os-version' product-id='test-product-id' timestamp='2019-12-20T01:51:26Z'> +<vertices> +<vertex name='node' instance='0x0' fmri='hc:///node=0'> + + <nvpair name='property-groups' type='nvlist-array'> + <!-- DTD violation: bad element --> + <badelement> + <nvpair name='property-group-name' type='string' value='protocol' /> + <nvpair name='property-values' type='nvlist-array'> + <nvlist> + <nvpair name='property-name' type='string' value='resource' /> + <nvpair name='property-type' type='uint32' value='9' /> + <nvpair name='property-value' type='nvlist'> + <nvlist> + <nvpair name='scheme' type='string' value='hc' /> + <nvpair name='version' type='uint8' value='0' /> + <nvpair name='hc-list' type='nvlist-array'> + <nvlist> + <nvpair name='hc-name' type='string' value='node' /> + <nvpair name='hc-id' type='string' value='0' /> + </nvlist> + </nvpair> + </nvlist> + </nvpair> <!-- property-value --> + </nvlist> + </nvpair> <!-- property-values --> + </nvlist> + + </nvpair> <!-- property-groups --> + +</vertex> + +</vertices> +</topo-digraph> diff --git a/usr/src/test/os-tests/tests/libtopo/digraph-test-in-badnum.xml b/usr/src/test/os-tests/tests/libtopo/digraph-test-in-badnum.xml new file mode 100644 index 0000000000..28f737dfb6 --- /dev/null +++ b/usr/src/test/os-tests/tests/libtopo/digraph-test-in-badnum.xml @@ -0,0 +1,42 @@ +<?xml version="1.0"?> +<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/digraph-topology.dtd.1"> + +<!-- + Copyright 2020 Joyent, Inc. + +--> + +<topo-digraph fmri-scheme='hc' nodename='test-nodename' os-version='test-os-version' product-id='test-product-id' timestamp='2019-12-20T01:51:26Z'> +<vertices> +<vertex name='node' instance='0x0' fmri='hc:///node=0'> + + <nvpair name='property-groups' type='nvlist-array'> + <nvlist> + <nvpair name='property-group-name' type='string' value='protocol' /> + <nvpair name='property-values' type='nvlist-array'> + <nvlist> + <nvpair name='property-name' type='string' value='resource' /> + <!-- bad numeric value --> + <nvpair name='property-type' type='uint32' value='gdfgdfgdffg' /> + <nvpair name='property-value' type='nvlist'> + <nvlist> + <nvpair name='scheme' type='string' value='hc' /> + <nvpair name='version' type='uint8' value='0' /> + <nvpair name='hc-list' type='nvlist-array'> + <nvlist> + <nvpair name='hc-name' type='string' value='node' /> + <nvpair name='hc-id' type='string' value='0' /> + </nvlist> + </nvpair> + </nvlist> + </nvpair> <!-- property-value --> + </nvlist> + </nvpair> <!-- property-values --> + </nvlist> + + </nvpair> <!-- property-groups --> + +</vertex> + +</vertices> +</topo-digraph> diff --git a/usr/src/test/os-tests/tests/libtopo/digraph-test-in-badscheme.xml b/usr/src/test/os-tests/tests/libtopo/digraph-test-in-badscheme.xml new file mode 100644 index 0000000000..254519692d --- /dev/null +++ b/usr/src/test/os-tests/tests/libtopo/digraph-test-in-badscheme.xml @@ -0,0 +1,42 @@ +<?xml version="1.0"?> +<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/digraph-topology.dtd.1"> + +<!-- + Copyright 2020 Joyent, Inc. + +--> + +<!-- invalid fmri-scheme value --> +<topo-digraph fmri-scheme='badscheme' nodename='test-nodename' os-version='test-os-version' product-id='test-product-id' timestamp='2019-12-20T01:51:26Z'> +<vertices> +<vertex name='node' instance='0x0' fmri='hc:///node=0'> + + <nvpair name='property-groups' type='nvlist-array'> + <nvlist> + <nvpair name='property-group-name' type='string' value='protocol' /> + <nvpair name='property-values' type='nvlist-array'> + <nvlist> + <nvpair name='property-name' type='string' value='resource' /> + <nvpair name='property-type' type='uint32' value='9' /> + <nvpair name='property-value' type='nvlist'> + <nvlist> + <nvpair name='scheme' type='string' value='hc' /> + <nvpair name='version' type='uint8' value='0' /> + <nvpair name='hc-list' type='nvlist-array'> + <nvlist> + <nvpair name='hc-name' type='string' value='node' /> + <nvpair name='hc-id' type='string' value='0' /> + </nvlist> + </nvpair> + </nvlist> + </nvpair> <!-- property-value --> + </nvlist> + </nvpair> <!-- property-values --> + </nvlist> + + </nvpair> <!-- property-groups --> + +</vertex> + +</vertices> +</topo-digraph> diff --git a/usr/src/test/os-tests/tests/libtopo/digraph-test-in.xml b/usr/src/test/os-tests/tests/libtopo/digraph-test-in.xml new file mode 100644 index 0000000000..679e1f834b --- /dev/null +++ b/usr/src/test/os-tests/tests/libtopo/digraph-test-in.xml @@ -0,0 +1,308 @@ +<?xml version="1.0"?> +<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/digraph-topology.dtd.1"> + +<!-- + Copyright 2020 Joyent, Inc. + + This XML represents a directed graph that looks like the following: + + |===> node=2 === + | | + node=0 ====> node=1 === |===> node=4 == + | | | + |===> node=3 === | + ^ ^ | + node=5 | | | + | | | + node=6 ======================= ====================== + +--> + +<topo-digraph fmri-scheme='hc' nodename='test-nodename' os-version='test-os-version' product-id='test-product-id' timestamp='2019-12-20T01:51:26Z'> +<vertices> +<vertex name='node' instance='0x0' fmri='hc:///node=0'> + + <nvpair name='property-groups' type='nvlist-array'> + <nvlist> + <nvpair name='property-group-name' type='string' value='test-pg-1' /> + <nvpair name='property-values' type='nvlist-array'> + + <nvlist> + <nvpair name='property-name' type='string' value='string-prop' /> + <nvpair name='property-type' type='uint32' value='6' /> + <nvpair name='property-value' type='string' value='blahblahblah' /> + </nvlist> + + <nvlist> + <nvpair name='property-name' type='string' value='uint64-array-prop' /> + <nvpair name='property-type' type='uint32' value='13' /> + <nvpair name='property-value' type='uint64-array'> + <nvpair value='0x1' /> + <nvpair value='0x2' /> + </nvpair> + </nvlist> + + <nvlist> + <nvpair name='property-name' type='string' value='int64-array-prop' /> + <nvpair name='property-type' type='uint32' value='12' /> + <nvpair name='property-value' type='int64-array'> + <nvpair value='1' /> + <nvpair value='2' /> + </nvpair> + </nvlist> + + <nvlist> + <nvpair name='property-name' type='string' value='uint32-array-prop' /> + <nvpair name='property-type' type='uint32' value='11' /> + <nvpair name='property-value' type='uint32-array'> + <nvpair value='1' /> + <nvpair value='2' /> + </nvpair> + </nvlist> + + <nvlist> + <nvpair name='property-name' type='string' value='int32-array-prop' /> + <nvpair name='property-type' type='uint32' value='10' /> + <nvpair name='property-value' type='int32-array'> + <nvpair value='1' /> + <nvpair value='2' /> + </nvpair> + </nvlist> + + <nvlist> + <nvpair name='property-name' type='string' value='uint64-prop' /> + <nvpair name='property-type' type='uint32' value='5' /> + <nvpair name='property-value' type='uint64' value='0x5003048023567a00' /> + </nvlist> + + <nvlist> + <nvpair name='property-name' type='string' value='uint32-prop' /> + <nvpair name='property-type' type='uint32' value='3' /> + <nvpair name='property-value' type='uint32' value='1' /> + </nvlist> + + </nvpair> <!-- property-values --> + </nvlist> + <nvlist> + <nvpair name='property-group-name' type='string' value='protocol' /> + <nvpair name='property-values' type='nvlist-array'> + <nvlist> + <nvpair name='property-name' type='string' value='resource' /> + <nvpair name='property-type' type='uint32' value='9' /> + <nvpair name='property-value' type='nvlist'> + <nvlist> + <nvpair name='scheme' type='string' value='hc' /> + <nvpair name='version' type='uint8' value='0' /> + <nvpair name='hc-list' type='nvlist-array'> + <nvlist> + <nvpair name='hc-name' type='string' value='node' /> + <nvpair name='hc-id' type='string' value='0' /> + </nvlist> + </nvpair> + </nvlist> + </nvpair> <!-- property-value --> + </nvlist> + </nvpair> <!-- property-values --> + </nvlist> + + </nvpair> <!-- property-groups --> + <outgoing-edges> + <edge fmri='hc:///node=1' /> + </outgoing-edges> + +</vertex> + +<vertex name='node' instance='0x1' fmri='hc:///node=1'> + + <nvpair name='property-groups' type='nvlist-array'> + + <nvlist> + <nvpair name='property-group-name' type='string' value='protocol' /> + <nvpair name='property-values' type='nvlist-array'> + <nvlist> + <nvpair name='property-name' type='string' value='resource' /> + <nvpair name='property-type' type='uint32' value='9' /> + <nvpair name='property-value' type='nvlist'> + <nvlist> + <nvpair name='scheme' type='string' value='hc' /> + <nvpair name='version' type='uint8' value='0' /> + <nvpair name='hc-list' type='nvlist-array'> + <nvlist> + <nvpair name='hc-name' type='string' value='node' /> + <nvpair name='hc-id' type='string' value='1' /> + </nvlist> + </nvpair> + </nvlist> + </nvpair> <!-- property-value --> + </nvlist> + </nvpair> <!-- property-values --> + </nvlist> + </nvpair> <!-- property-groups --> + <outgoing-edges> + <edge fmri='hc:///node=2' /> + <edge fmri='hc:///node=3' /> + </outgoing-edges> + +</vertex> + +<vertex name='node' instance='0x2' fmri='hc:///node=2'> + + <nvpair name='property-groups' type='nvlist-array'> + + <nvlist> + <nvpair name='property-group-name' type='string' value='protocol' /> + <nvpair name='property-values' type='nvlist-array'> + <nvlist> + <nvpair name='property-name' type='string' value='resource' /> + <nvpair name='property-type' type='uint32' value='9' /> + <nvpair name='property-value' type='nvlist'> + <nvlist> + <nvpair name='scheme' type='string' value='hc' /> + <nvpair name='version' type='uint8' value='0' /> + <nvpair name='hc-list' type='nvlist-array'> + <nvlist> + <nvpair name='hc-name' type='string' value='node' /> + <nvpair name='hc-id' type='string' value='2' /> + </nvlist> + </nvpair> + </nvlist> + </nvpair> <!-- property-value --> + </nvlist> + </nvpair> <!-- property-values --> + </nvlist> + + </nvpair> <!-- property-groups --> + <outgoing-edges> + <edge fmri='hc:///node=4' /> + </outgoing-edges> + +</vertex> + +<vertex name='node' instance='0x3' fmri='hc:///node=3'> + + <nvpair name='property-groups' type='nvlist-array'> + + <nvlist> + <nvpair name='property-group-name' type='string' value='protocol' /> + <nvpair name='property-values' type='nvlist-array'> + <nvlist> + <nvpair name='property-name' type='string' value='resource' /> + <nvpair name='property-type' type='uint32' value='9' /> + <nvpair name='property-value' type='nvlist'> + <nvlist> + <nvpair name='scheme' type='string' value='hc' /> + <nvpair name='version' type='uint8' value='0' /> + <nvpair name='hc-list' type='nvlist-array'> + <nvlist> + <nvpair name='hc-name' type='string' value='node' /> + <nvpair name='hc-id' type='string' value='3' /> + </nvlist> + </nvpair> + </nvlist> + </nvpair> <!-- property-value --> + </nvlist> + </nvpair> <!-- property-values --> + </nvlist> + + </nvpair> <!-- property-groups --> + <outgoing-edges> + <edge fmri='hc:///node=4' /> + </outgoing-edges> + +</vertex> + +<vertex name='node' instance='0x4' fmri='hc:///node=4'> + + <nvpair name='property-groups' type='nvlist-array'> + <nvlist> + <nvpair name='property-group-name' type='string' value='protocol' /> + <nvpair name='property-values' type='nvlist-array'> + <nvlist> + <nvpair name='property-name' type='string' value='resource' /> + <nvpair name='property-type' type='uint32' value='9' /> + <nvpair name='property-value' type='nvlist'> + <nvlist> + <nvpair name='scheme' type='string' value='hc' /> + <nvpair name='version' type='uint8' value='0' /> + <nvpair name='hc-list' type='nvlist-array'> + <nvlist> + <nvpair name='hc-name' type='string' value='node' /> + <nvpair name='hc-id' type='string' value='4' /> + </nvlist> + </nvpair> + </nvlist> + </nvpair> <!-- property-value --> + </nvlist> + </nvpair> <!-- property-values --> + </nvlist> + + </nvpair> <!-- property-groups --> + <outgoing-edges> + <edge fmri='hc:///node=3' /> + </outgoing-edges> + +</vertex> + +<vertex name='node' instance='0x5' fmri='hc:///node=5'> + + <nvpair name='property-groups' type='nvlist-array'> + <nvlist> + <nvpair name='property-group-name' type='string' value='protocol' /> + <nvpair name='property-values' type='nvlist-array'> + <nvlist> + <nvpair name='property-name' type='string' value='resource' /> + <nvpair name='property-type' type='uint32' value='9' /> + <nvpair name='property-value' type='nvlist'> + <nvlist> + <nvpair name='scheme' type='string' value='hc' /> + <nvpair name='version' type='uint8' value='0' /> + <nvpair name='hc-list' type='nvlist-array'> + <nvlist> + <nvpair name='hc-name' type='string' value='node' /> + <nvpair name='hc-id' type='string' value='5' /> + </nvlist> + </nvpair> + </nvlist> + </nvpair> <!-- property-value --> + </nvlist> + </nvpair> <!-- property-values --> + </nvlist> + + </nvpair> <!-- property-groups --> + +</vertex> + +<vertex name='node' instance='0x6' fmri='hc:///node=6'> + + <nvpair name='property-groups' type='nvlist-array'> + <nvlist> + <nvpair name='property-group-name' type='string' value='protocol' /> + <nvpair name='property-values' type='nvlist-array'> + <nvlist> + <nvpair name='property-name' type='string' value='resource' /> + <nvpair name='property-type' type='uint32' value='9' /> + <nvpair name='property-value' type='nvlist'> + <nvlist> + <nvpair name='scheme' type='string' value='hc' /> + <nvpair name='version' type='uint8' value='0' /> + <nvpair name='hc-list' type='nvlist-array'> + <nvlist> + <nvpair name='hc-name' type='string' value='node' /> + <nvpair name='hc-id' type='string' value='6' /> + </nvlist> + </nvpair> + </nvlist> + </nvpair> <!-- property-value --> + </nvlist> + </nvpair> <!-- property-values --> + </nvlist> + + </nvpair> <!-- property-groups --> + <outgoing-edges> + <edge fmri='hc:///node=3' /> + </outgoing-edges> + +</vertex> + +</vertices> +</topo-digraph> diff --git a/usr/src/test/os-tests/tests/libtopo/digraph-test.c b/usr/src/test/os-tests/tests/libtopo/digraph-test.c new file mode 100644 index 0000000000..b829f0bb8f --- /dev/null +++ b/usr/src/test/os-tests/tests/libtopo/digraph-test.c @@ -0,0 +1,380 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2020 Joyent, Inc. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <fcntl.h> +#include <libnvpair.h> +#include <string.h> +#include <stropts.h> +#include <unistd.h> +#include <fm/libtopo.h> +#include <sys/debug.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/varargs.h> + + +#define TEST_HOME "/opt/os-tests/tests/libtopo/" +#define TEST_XML_IN "digraph-test-in.xml" +#define TEST_XML_IN_BADSCHEME "digraph-test-in-badscheme.xml" +#define TEST_XML_IN_BADNUM "digraph-test-in-badnum.xml" +#define TEST_XML_IN_BADEDGE "digraph-test-in-badedge.xml" +#define TEST_XML_IN_BADELEMENT "digraph-test-in-badelement.xml" +#define TEST_GRAPH_SZ 7 +#define TEST_XML_OUT_DIR "/var/tmp" +#define TEST_XML_OUT_PREFIX "digraph-test-out" + +static const char *pname; + +extern int topo_hdl_errno(topo_hdl_t *); + +/* + * Generate an ISO 8601 timestamp + */ +static void +get_timestamp(char *buf, size_t bufsize) +{ + time_t utc_time; + struct tm *p_tm; + + (void) time(&utc_time); + p_tm = localtime(&utc_time); + + (void) strftime(buf, bufsize, "%FT%TZ", p_tm); +} + +/* PRINTFLIKE1 */ +static void +logmsg(const char *format, ...) +{ + char timestamp[128]; + va_list ap; + + get_timestamp(timestamp, sizeof (timestamp)); + (void) fprintf(stdout, "%s ", timestamp); + va_start(ap, format); + (void) vfprintf(stdout, format, ap); + va_end(ap); + (void) fprintf(stdout, "\n"); + (void) fflush(stdout); +} + +static topo_digraph_t * +test_deserialize(topo_hdl_t *thp, const char *path) +{ + struct stat statbuf = { 0 }; + char *buf = NULL; + int fd = -1; + topo_digraph_t *tdg = NULL; + + logmsg("\tOpening test XML topology"); + if ((fd = open(path, O_RDONLY)) < 0) { + logmsg("\tfailed to open %s (%s)", path, strerror(errno)); + goto out; + } + if (fstat(fd, &statbuf) != 0) { + logmsg("\tfailed to stat %s (%s)", path, strerror(errno)); + goto out; + } + if ((buf = malloc(statbuf.st_size)) == NULL) { + logmsg("\tfailed to alloc read buffer: (%s)", strerror(errno)); + goto out; + } + if (read(fd, buf, statbuf.st_size) != statbuf.st_size) { + logmsg("\tfailed to read file: (%s)", strerror(errno)); + goto out; + } + + logmsg("\tDeserializing XML topology"); + tdg = topo_digraph_deserialize(thp, buf, statbuf.st_size); + if (tdg == NULL) { + logmsg("\ttopo_digraph_deserialize() failed!"); + goto out; + } + logmsg("\ttopo_digraph_deserialize() succeeded"); +out: + free(buf); + if (fd > 0) { + (void) close(fd); + } + return (tdg); +} + +struct cb_arg { + topo_vertex_t **vertices; +}; + +static int +test_paths_cb(topo_hdl_t *thp, topo_vertex_t *vtx, boolean_t last_vtx, + void *arg) +{ + struct cb_arg *cbarg = arg; + uint_t idx = topo_node_instance(topo_vertex_node(vtx)); + + cbarg->vertices[idx] = vtx; + + return (TOPO_WALK_NEXT); +} + +static int +test_paths(topo_hdl_t *thp, topo_digraph_t *tdg) +{ + topo_vertex_t *vertices[TEST_GRAPH_SZ]; + struct cb_arg cbarg = { 0 }; + int ret = -1; + topo_path_t **paths; + uint_t np; + + cbarg.vertices = vertices; + if (topo_vertex_iter(thp, tdg, test_paths_cb, &cbarg) != 0) { + logmsg("\tfailed to iterate over graph vertices"); + goto out; + } + + logmsg("\tCalculating number of paths between node 0 and node 4"); + if (topo_digraph_paths(thp, tdg, vertices[0], vertices[4], &paths, + &np) < 0) { + logmsg("\ttopo_digraph_paths() failed"); + goto out; + } + if (np != 2) { + logmsg("\t%d paths found (expected 2)", np); + goto out; + } + for (uint_t i = 0; i < np; i++) { + topo_path_destroy(thp, paths[i]); + } + topo_hdl_free(thp, paths, np * sizeof (topo_path_t *)); + + logmsg("\tCalculating number of paths between node 6 and node 4"); + if (topo_digraph_paths(thp, tdg, vertices[6], vertices[4], &paths, + &np) < 0) { + logmsg("\ttopo_digraph_paths() failed"); + goto out; + } + if (np != 1) { + logmsg("\t%d paths found (expected 1)", np); + goto out; + } + for (uint_t i = 0; i < np; i++) { + topo_path_destroy(thp, paths[i]); + } + topo_hdl_free(thp, paths, np * sizeof (topo_path_t *)); + + logmsg("\tCalculating number of paths between node 5 and node 1"); + if (topo_digraph_paths(thp, tdg, vertices[5], vertices[1], &paths, + &np) < 0) { + logmsg("\ttopo_digraph_paths() failed"); + goto out; + } + if (np != 0) { + logmsg("\t%d paths found (expected 0)", np); + goto out; + } + ret = 0; + +out: + if (np > 0) { + for (uint_t i = 0; i < np; i++) { + topo_path_destroy(thp, paths[i]); + } + topo_hdl_free(thp, paths, np * sizeof (topo_path_t *)); + } + return (ret); +} + +static int +test_serialize(topo_hdl_t *thp, topo_digraph_t *tdg, const char *path) +{ + FILE *xml_out; + + if ((xml_out = fopen(path, "w")) == NULL) { + logmsg("\tfailed to open %s for writing (%s)", + strerror(errno)); + return (-1); + } + logmsg("\tSerializing topology to XML (%s)", path); + if (topo_digraph_serialize(thp, tdg, xml_out) != 0) { + logmsg("\ttopo_digraph_serialize() failed!"); + (void) fclose(xml_out); + return (-1); + } + (void) fclose(xml_out); + return (0); +} + +int +main(int argc, char **argv) +{ + topo_hdl_t *thp = NULL; + topo_digraph_t *tdg; + char *root = "/", *out_path = NULL; + boolean_t abort_on_exit = B_FALSE; + int err, status = EXIT_FAILURE; + + pname = argv[0]; + + /* + * Setting DIGRAPH_TEST_CORE causes us to abort and dump core before + * exiting. This is useful for examining for memory leaks. + */ + if (getenv("DIGRAPH_TEST_CORE") != NULL) { + abort_on_exit = B_TRUE; + } + + logmsg("Opening libtopo"); + if ((thp = topo_open(TOPO_VERSION, root, &err)) == NULL) { + logmsg("failed to get topo handle: %s", topo_strerror(err)); + goto out; + } + + logmsg("TEST: Deserialize directed graph topology"); + if ((tdg = test_deserialize(thp, TEST_HOME TEST_XML_IN)) == NULL) { + logmsg("FAIL"); + goto out; + } + logmsg("PASS"); + + logmsg("TEST: Serialize directed graph topology"); + if ((out_path = tempnam(TEST_XML_OUT_DIR, TEST_XML_OUT_PREFIX)) == + NULL) { + logmsg("\tFailed to create temporary file name under %s (%s)", + TEST_XML_OUT_DIR, strerror(errno)); + logmsg("FAIL"); + goto out; + } + if (test_serialize(thp, tdg, out_path) != 0) { + logmsg("FAIL"); + goto out; + } + logmsg("PASS"); + + logmsg("Closing libtopo"); + topo_close(thp); + + logmsg("Reopening libtopo"); + if ((thp = topo_open(TOPO_VERSION, root, &err)) == NULL) { + logmsg("failed to get topo handle: %s", topo_strerror(err)); + goto out; + } + + logmsg("TEST: Deserialize directed graph topology (pass 2)"); + if ((tdg = test_deserialize(thp, out_path)) == NULL) { + logmsg("FAIL"); + goto out; + } + logmsg("PASS"); + + logmsg("TEST: Calculating paths between vertices"); + if (test_paths(thp, tdg) != 0) { + logmsg("FAIL"); + goto out; + } + logmsg("PASS"); + + logmsg("Closing libtopo"); + topo_close(thp); + + logmsg("Reopening libtopo"); + if ((thp = topo_open(TOPO_VERSION, root, &err)) == NULL) { + logmsg("failed to get topo handle: %s", topo_strerror(err)); + goto out; + } + + /* + * The following tests attempt to deserialize XML files that either + * violate the DTD or contain invalid attribute values. + * + * The expection is that topo_digraph_deserialize() should fail + * gracefully (i.e. not segfault) and topo_errno should be set. + */ + logmsg("TEST: Deserialize directed graph topology (bad scheme)"); + if ((tdg = test_deserialize(thp, TEST_HOME TEST_XML_IN_BADSCHEME)) != + NULL) { + logmsg("FAIL"); + goto out; + } else if (topo_hdl_errno(thp) == 0) { + logmsg("\texpected topo_errno to be non-zero"); + logmsg("FAIL"); + goto out; + } else { + logmsg("PASS"); + } + + logmsg("TEST: Deserialize directed graph topology (bad number)"); + if ((tdg = test_deserialize(thp, TEST_HOME TEST_XML_IN_BADNUM)) != + NULL) { + logmsg("FAIL"); + goto out; + } else if (topo_hdl_errno(thp) == 0) { + logmsg("\texpected topo_errno to be non-zero"); + logmsg("FAIL"); + goto out; + } else { + logmsg("PASS"); + } + + logmsg("TEST: Deserialize directed graph topology (bad edge)"); + if ((tdg = test_deserialize(thp, TEST_HOME TEST_XML_IN_BADEDGE)) != + NULL) { + logmsg("FAIL"); + goto out; + } else if (topo_hdl_errno(thp) == 0) { + logmsg("\texpected topo_errno to be non-zero"); + logmsg("FAIL"); + goto out; + } else { + logmsg("PASS"); + } + + logmsg("TEST: Deserialize directed graph topology (bad element)"); + if ((tdg = test_deserialize(thp, TEST_HOME TEST_XML_IN_BADELEMENT)) != + NULL) { + logmsg("FAIL"); + goto out; + } else if (topo_hdl_errno(thp) == 0) { + logmsg("\texpected topo_errno to be non-zero"); + logmsg("FAIL"); + goto out; + } else { + logmsg("PASS"); + } + + /* + * If any tests failed, we don't unlink the temp file, as its contents + * may be useful for root-causing the test failure. + */ + if (unlink(out_path) != 0) { + logmsg("Failed to unlink temp file: %s (%s)", out_path, + strerror(errno)); + } + status = EXIT_SUCCESS; +out: + if (thp != NULL) { + topo_close(thp); + } + if (out_path != NULL) { + free(out_path); + } + logmsg("digraph tests %s", + status == EXIT_SUCCESS ? "passed" : "failed"); + + if (abort_on_exit) { + abort(); + } + return (status); +} |