146283Sdfr/*-
246283Sdfr * Copyright (c) 2017 Enji Cooper <ngie@freebsd.org>
3130803Smarcel *
498944Sobrien * Redistribution and use in source and binary forms, with or without
546283Sdfr * modification, are permitted provided that the following conditions
698944Sobrien * are met:
746283Sdfr * 1. Redistributions of source code must retain the above copyright
898944Sobrien *    notice, this list of conditions and the following disclaimer.
998944Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1098944Sobrien *    notice, this list of conditions and the following disclaimer in the
1198944Sobrien *    documentation and/or other materials provided with the distribution.
1246283Sdfr *
1398944Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1498944Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1598944Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1698944Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1746283Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1898944Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1998944Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2098944Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2198944Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2298944Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2346283Sdfr * SUCH DAMAGE.
2446283Sdfr */
2546283Sdfr
2646283Sdfr#include <sys/cdefs.h>
2746283Sdfr__FBSDID("$FreeBSD: stable/11/lib/libkvm/tests/kvm_geterr_test.c 346920 2019-04-29 19:36:46Z ngie $");
2846283Sdfr
2946283Sdfr#include <sys/param.h>
3046283Sdfr#include <errno.h>
3146283Sdfr#include <fcntl.h>
3246283Sdfr#include <kvm.h>
3398944Sobrien#include <limits.h>
3498944Sobrien#include <signal.h>
3598944Sobrien#include <stdio.h>
3698944Sobrien#include <stdlib.h>
3798944Sobrien
3898944Sobrien#include <atf-c.h>
3998944Sobrien
40130803Smarcel#include "kvm_private.h"
41130803Smarcel
4246283Sdfr#include "kvm_test_common.h"
4346283Sdfr
4446283SdfrATF_TC(kvm_geterr_negative_test_NULL);
4546283SdfrATF_TC_HEAD(kvm_geterr_negative_test_NULL, tc)
4646283Sdfr{
47130803Smarcel
48130803Smarcel	atf_tc_set_md_var(tc, "descr",
4946283Sdfr	    "test that kvm_geterr(NULL) returns NULL");
5046283Sdfr}
5146283Sdfr
5246283SdfrATF_TC_BODY(kvm_geterr_negative_test_NULL, tc)
5346283Sdfr{
5446283Sdfr
5546283Sdfr	ATF_REQUIRE(!errbuf_has_error(kvm_geterr(NULL)));
5646283Sdfr}
5746283Sdfr
5846283Sdfr/* 1100090 was where kvm_open2(3) was introduced. */
5946283Sdfr#if __FreeBSD_version >= 1100091
6046283SdfrATF_TC(kvm_geterr_positive_test_error);
6146283SdfrATF_TC_HEAD(kvm_geterr_positive_test_error, tc)
6298944Sobrien{
6346283Sdfr
6446283Sdfr	atf_tc_set_md_var(tc, "descr",
6546283Sdfr	    "test that kvm_geterr(kd) when kd doesn't contain an error returns \"\"");
6646283Sdfr	atf_tc_set_md_var(tc, "require.user", "root");
6746283Sdfr}
6898944Sobrien
6998944SobrienATF_TC_BODY(kvm_geterr_positive_test_error, tc)
7098944Sobrien{
7198944Sobrien	kvm_t *kd;
7298944Sobrien	char *error_msg;
7346283Sdfr
7498944Sobrien	errbuf_clear();
7598944Sobrien	kd = kvm_open2(NULL, NULL, O_RDONLY, errbuf, NULL);
7698944Sobrien	ATF_CHECK(!errbuf_has_error(errbuf));
7798944Sobrien	ATF_REQUIRE_MSG(kd != NULL, "kvm_open2 failed: %s", errbuf);
7898944Sobrien	ATF_REQUIRE_MSG(kvm_write(kd, 0, NULL, 0) == -1,
7946283Sdfr	    "kvm_write succeeded unexpectedly on an O_RDONLY file descriptor");
8046283Sdfr	error_msg = kvm_geterr(kd);
8146283Sdfr	ATF_CHECK(errbuf_has_error(error_msg));
8246283Sdfr	ATF_REQUIRE_MSG(kvm_close(kd) == 0, "kvm_close failed: %s",
8346283Sdfr	    strerror(errno));
8446283Sdfr}
8546283Sdfr
8646283SdfrATF_TC(kvm_geterr_positive_test_no_error);
8746283SdfrATF_TC_HEAD(kvm_geterr_positive_test_no_error, tc)
8846283Sdfr{
8946283Sdfr
9046283Sdfr	atf_tc_set_md_var(tc, "descr",
9146283Sdfr	    "test that kvm_geterr(kd) when kd contains an error returns an error message");
9246283Sdfr	atf_tc_set_md_var(tc, "require.user", "root");
9346283Sdfr}
9446283Sdfr
9546283SdfrATF_TC_BODY(kvm_geterr_positive_test_no_error, tc)
9646283Sdfr{
9746283Sdfr#define	ALL_IS_WELL	"that ends well"
9846283Sdfr	kvm_t *kd;
9946283Sdfr	char *error_msg;
10046283Sdfr	struct nlist nl[] = {
10146283Sdfr#define	SYMNAME	"_mp_maxcpus"
10298944Sobrien#define	X_MAXCPUS	0
10346283Sdfr		{ SYMNAME, 0, 0, 0, 0 },
10446283Sdfr		{ NULL, 0, 0, 0, 0 },
10546283Sdfr	};
10646283Sdfr	ssize_t rc;
10746283Sdfr	int mp_maxcpus, retcode;
10846283Sdfr
10946283Sdfr	errbuf_clear();
11046283Sdfr	kd = kvm_open2(NULL, NULL, O_RDONLY, errbuf, NULL);
11146283Sdfr	ATF_CHECK(!errbuf_has_error(errbuf));
11246283Sdfr	ATF_REQUIRE_MSG(kd != NULL, "kvm_open2 failed: %s", errbuf);
11346283Sdfr	retcode = kvm_nlist(kd, nl);
11446283Sdfr	ATF_REQUIRE_MSG(retcode != -1,
11546283Sdfr	    "kvm_nlist failed (returned %d): %s", retcode, kvm_geterr(kd));
11646283Sdfr	if (nl[X_MAXCPUS].n_type == 0)
11746283Sdfr		atf_tc_skip("symbol (\"%s\") couldn't be found", SYMNAME);
11846283Sdfr	_kvm_err(kd, NULL, "%s", ALL_IS_WELL); /* XXX: internal API */
11946283Sdfr	rc = kvm_read(kd, nl[X_MAXCPUS].n_value, &mp_maxcpus,
12046283Sdfr	    sizeof(mp_maxcpus));
12146283Sdfr
12246283Sdfr	ATF_REQUIRE_MSG(rc != -1, "kvm_read failed: %s", kvm_geterr(kd));
12346283Sdfr	error_msg = kvm_geterr(kd);
12446283Sdfr	ATF_REQUIRE_MSG(strcmp(error_msg, ALL_IS_WELL) == 0,
12546283Sdfr	    "error message changed: %s", error_msg);
12646283Sdfr	ATF_REQUIRE_MSG(kvm_close(kd) == 0, "kvm_close failed: %s",
12746283Sdfr	    strerror(errno));
12846283Sdfr}
12998944Sobrien#endif
13098944Sobrien
13198944SobrienATF_TP_ADD_TCS(tp)
13298944Sobrien{
13398944Sobrien
13498944Sobrien	ATF_TP_ADD_TC(tp, kvm_geterr_negative_test_NULL);
13598944Sobrien#if __FreeBSD_version >= 1100091
13698944Sobrien	ATF_TP_ADD_TC(tp, kvm_geterr_positive_test_error);
13798944Sobrien	ATF_TP_ADD_TC(tp, kvm_geterr_positive_test_no_error);
13898944Sobrien#endif
13998944Sobrien
14098944Sobrien	return (atf_no_error());
14198944Sobrien}
14298944Sobrien