mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
json: Add unit tests for error handling
Add cmocka unit tests to exercise the error handling in the JSON routines. Signed-off-by: Gary Lockyer <gary@catalyst.net.nz> Reviewed-by: Jeremy Allison <jra@samba.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
parent
79f494e51e
commit
6f4f8c51e0
869
lib/audit_logging/tests/audit_logging_error_test.c
Normal file
869
lib/audit_logging/tests/audit_logging_error_test.c
Normal file
@ -0,0 +1,869 @@
|
||||
/*
|
||||
* Unit tests for the audit_logging library.
|
||||
*
|
||||
* Copyright (C) Andrew Bartlett <abartlet@samba.org> 2018
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* from cmocka.c:
|
||||
* These headers or their equivalents should be included prior to
|
||||
* including
|
||||
* this header file.
|
||||
*
|
||||
* #include <stdarg.h>
|
||||
* #include <stddef.h>
|
||||
* #include <setjmp.h>
|
||||
*
|
||||
* This allows test applications to use custom definitions of C standard
|
||||
* library functions and types.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Unit tests for lib/audit_logging/audit_logging.c
|
||||
*
|
||||
* These tests exercise the error handling code and mock the jannson functions
|
||||
* to trigger errors.
|
||||
*
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <setjmp.h>
|
||||
#include <cmocka.h>
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "librpc/ndr/libndr.h"
|
||||
#include "lib/tsocket/tsocket.h"
|
||||
#include "libcli/security/dom_sid.h"
|
||||
#include "lib/messaging/messaging.h"
|
||||
#include "auth/common_auth.h"
|
||||
|
||||
#include "lib/audit_logging/audit_logging.h"
|
||||
|
||||
const int JANNASON_FAILURE = -1;
|
||||
const int CALL_ORIG = -2;
|
||||
|
||||
/*
|
||||
* cmocka wrappers for json_object
|
||||
*/
|
||||
json_t *__wrap_json_object(void);
|
||||
json_t *__real_json_object(void);
|
||||
json_t *__wrap_json_object(void)
|
||||
{
|
||||
|
||||
bool fail = (bool)mock();
|
||||
if (fail) {
|
||||
return NULL;
|
||||
}
|
||||
return __real_json_object();
|
||||
}
|
||||
|
||||
/*
|
||||
* cmocka wrappers for json_array
|
||||
*/
|
||||
json_t *__wrap_json_array(void);
|
||||
json_t *__real_json_array(void);
|
||||
json_t *__wrap_json_array(void)
|
||||
{
|
||||
|
||||
bool fail = (bool)mock();
|
||||
if (fail) {
|
||||
return NULL;
|
||||
}
|
||||
return __real_json_array();
|
||||
}
|
||||
|
||||
/*
|
||||
* cmoka wrappers for json_integer
|
||||
*/
|
||||
json_t *__wrap_json_integer(json_int_t value);
|
||||
json_t *__real_json_integer(json_int_t value);
|
||||
json_t *__wrap_json_integer(json_int_t value)
|
||||
{
|
||||
|
||||
bool fail = (bool)mock();
|
||||
if (fail) {
|
||||
return NULL;
|
||||
}
|
||||
return __real_json_integer(value);
|
||||
}
|
||||
|
||||
/*
|
||||
* cmocka wrappers for json_string
|
||||
*/
|
||||
json_t *__wrap_json_string(const char *value);
|
||||
json_t *__real_json_string(const char *value);
|
||||
json_t *__wrap_json_string(const char *value)
|
||||
{
|
||||
|
||||
bool fail = (bool)mock();
|
||||
if (fail) {
|
||||
return NULL;
|
||||
}
|
||||
return __real_json_string(value);
|
||||
}
|
||||
|
||||
/*
|
||||
* cmocka wrappers for json_dumps
|
||||
*/
|
||||
char *__wrap_json_dumps(const json_t *json, size_t flags);
|
||||
char *__real_json_dumps(const json_t *json, size_t flags);
|
||||
char *__wrap_json_dumps(const json_t *json, size_t flags)
|
||||
{
|
||||
|
||||
bool fail = (bool)mock();
|
||||
if (fail) {
|
||||
return NULL;
|
||||
}
|
||||
return __real_json_dumps(json, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* cmocka wrappers for json_object_set_new
|
||||
*/
|
||||
int __wrap_json_object_set_new(json_t *object, const char *key, json_t *value);
|
||||
int __real_json_object_set_new(json_t *object, const char *key, json_t *value);
|
||||
int __wrap_json_object_set_new(json_t *object, const char *key, json_t *value)
|
||||
{
|
||||
int rc = (int)mock();
|
||||
if (rc != CALL_ORIG) {
|
||||
return rc;
|
||||
}
|
||||
return __real_json_object_set_new(object, key, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* cmocka wrappers for json_array_append_new
|
||||
*/
|
||||
int __wrap_json_array_append_new(json_t *object,
|
||||
const char *key,
|
||||
json_t *value);
|
||||
int __real_json_array_append_new(json_t *object,
|
||||
const char *key,
|
||||
json_t *value);
|
||||
int __wrap_json_array_append_new(json_t *object, const char *key, json_t *value)
|
||||
{
|
||||
int rc = (int)mock();
|
||||
if (rc != CALL_ORIG) {
|
||||
return rc;
|
||||
}
|
||||
return __real_json_array_append_new(object, key, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* cmocka wrappers for json_array_extend
|
||||
*/
|
||||
int __wrap_json_array_extend(json_t *array, json_t *other_array);
|
||||
int __real_json_array_extend(json_t *array, json_t *other_array);
|
||||
int __wrap_json_array_extend(json_t *array, json_t *other_array)
|
||||
{
|
||||
|
||||
int rc = (int)mock();
|
||||
if (rc != CALL_ORIG) {
|
||||
return rc;
|
||||
}
|
||||
return __real_json_array_extend(array, other_array);
|
||||
}
|
||||
|
||||
/*
|
||||
* cmocka wrappers for json_object_update
|
||||
*/
|
||||
int __wrap_json_object_update(json_t *object, json_t *other_object);
|
||||
int __real_json_object_update(json_t *object, json_t *other_object);
|
||||
int __wrap_json_object_update(json_t *object, json_t *other_object)
|
||||
{
|
||||
|
||||
int rc = (int)mock();
|
||||
if (rc != CALL_ORIG) {
|
||||
return rc;
|
||||
}
|
||||
return __real_json_array_extend(object, other_object);
|
||||
}
|
||||
|
||||
/*
|
||||
* cmocka wrappers for gettimeofday
|
||||
*/
|
||||
int __wrap_gettimeofday(struct timeval *tv, struct timezone *tz);
|
||||
int __real_gettimeofday(struct timeval *tv, struct timezone *tz);
|
||||
int __wrap_gettimeofday(struct timeval *tv, struct timezone *tz)
|
||||
{
|
||||
|
||||
int rc = (int)mock();
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
return __real_gettimeofday(tv, tz);
|
||||
}
|
||||
|
||||
/*
|
||||
* cmocka wrappers for localtime
|
||||
*/
|
||||
struct tm *__wrap_localtime(const time_t *timep);
|
||||
struct tm *__real_localtime(const time_t *timep);
|
||||
struct tm *__wrap_localtime(const time_t *timep)
|
||||
{
|
||||
bool fail = (bool)mock();
|
||||
if (fail) {
|
||||
return NULL;
|
||||
}
|
||||
return __real_localtime(timep);
|
||||
}
|
||||
|
||||
/*
|
||||
* cmocka wrappers for talloc_named_const
|
||||
*/
|
||||
static const void *REAL_TALLOC = "Here";
|
||||
|
||||
void *__wrap_talloc_named_const(const void *context,
|
||||
size_t size,
|
||||
const char *name);
|
||||
void *__real_talloc_named_const(const void *context,
|
||||
size_t size,
|
||||
const char *name);
|
||||
void *__wrap_talloc_named_const(const void *context,
|
||||
size_t size,
|
||||
const char *name)
|
||||
{
|
||||
|
||||
void *ret = (void *)mock();
|
||||
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return __real_talloc_named_const(context, size, name);
|
||||
}
|
||||
|
||||
/*
|
||||
* cmocka wrappers for talloc_strdup
|
||||
*/
|
||||
char *__wrap_talloc_strdup(const void *t, const char *p);
|
||||
char *__real_talloc_strdup(const void *t, const char *p);
|
||||
char *__wrap_talloc_strdup(const void *t, const char *p)
|
||||
{
|
||||
|
||||
void *ret = (void *)mock();
|
||||
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return __real_talloc_strdup(t, p);
|
||||
}
|
||||
|
||||
char *__wrap_tsocket_address_string(const struct tsocket_address *addr,
|
||||
TALLOC_CTX *mem_ctx);
|
||||
char *__real_tsocket_address_string(const struct tsocket_address *addr,
|
||||
TALLOC_CTX *mem_ctx);
|
||||
char *__wrap_tsocket_address_string(const struct tsocket_address *addr,
|
||||
TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
|
||||
bool fail = (bool)mock();
|
||||
if (fail) {
|
||||
return NULL;
|
||||
}
|
||||
return __real_tsocket_address_string(addr, mem_ctx);
|
||||
}
|
||||
|
||||
static void test_json_add_int(void **state)
|
||||
{
|
||||
struct json_object object;
|
||||
int rc = 0;
|
||||
|
||||
will_return(__wrap_json_object, false);
|
||||
object = json_new_object();
|
||||
|
||||
/*
|
||||
* Test json integer failure
|
||||
*/
|
||||
will_return(__wrap_json_integer, true);
|
||||
rc = json_add_int(&object, "name", 2);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
/*
|
||||
* Test json object set new failure
|
||||
*/
|
||||
will_return(__wrap_json_integer, false);
|
||||
will_return(__wrap_json_object_set_new, JANNASON_FAILURE);
|
||||
rc = json_add_int(&object, "name", 2);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
json_free(&object);
|
||||
}
|
||||
|
||||
static void test_json_add_bool(void **state)
|
||||
{
|
||||
struct json_object object;
|
||||
int rc = 0;
|
||||
|
||||
will_return(__wrap_json_object, false);
|
||||
object = json_new_object();
|
||||
|
||||
/*
|
||||
* json_boolean does not return an error code.
|
||||
* Test json object set new failure
|
||||
*/
|
||||
will_return(__wrap_json_object_set_new, JANNASON_FAILURE);
|
||||
rc = json_add_bool(&object, "name", true);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
json_free(&object);
|
||||
}
|
||||
|
||||
static void test_json_add_string(void **state)
|
||||
{
|
||||
struct json_object object;
|
||||
int rc = 0;
|
||||
|
||||
will_return(__wrap_json_object, false);
|
||||
object = json_new_object();
|
||||
assert_false(json_is_invalid(&object));
|
||||
|
||||
/*
|
||||
* Test json string failure
|
||||
*/
|
||||
will_return(__wrap_json_string, true);
|
||||
rc = json_add_string(&object, "name", "value");
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
/*
|
||||
* Test json object set new failure
|
||||
*/
|
||||
will_return(__wrap_json_string, false);
|
||||
will_return(__wrap_json_object_set_new, JANNASON_FAILURE);
|
||||
rc = json_add_string(&object, "name", "value");
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
/*
|
||||
* Test json object set new failure for a NULL string
|
||||
*/
|
||||
will_return(__wrap_json_object_set_new, JANNASON_FAILURE);
|
||||
rc = json_add_string(&object, "null", NULL);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
json_free(&object);
|
||||
}
|
||||
|
||||
static void test_json_add_object(void **state)
|
||||
{
|
||||
struct json_object object;
|
||||
struct json_object value;
|
||||
int rc = 0;
|
||||
|
||||
will_return(__wrap_json_object, false);
|
||||
will_return(__wrap_json_object, false);
|
||||
|
||||
object = json_new_object();
|
||||
value = json_new_object();
|
||||
|
||||
/*
|
||||
* Test json object set new failure
|
||||
*/
|
||||
will_return(__wrap_json_object_set_new, JANNASON_FAILURE);
|
||||
rc = json_add_object(&object, "name", &value);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_false(json_is_invalid(&value));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
/*
|
||||
* Test json object set new failure for a NULL value
|
||||
*/
|
||||
will_return(__wrap_json_object_set_new, JANNASON_FAILURE);
|
||||
rc = json_add_object(&object, "null", NULL);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
json_free(&object);
|
||||
json_free(&value);
|
||||
}
|
||||
|
||||
static void test_json_add_to_array(void **state)
|
||||
{
|
||||
struct json_object array;
|
||||
struct json_object value;
|
||||
int rc = 0;
|
||||
|
||||
will_return(__wrap_json_array, false);
|
||||
will_return(__wrap_json_object, false);
|
||||
|
||||
array = json_new_array();
|
||||
value = json_new_object();
|
||||
|
||||
/*
|
||||
* Test json array append new failure
|
||||
*/
|
||||
will_return(__wrap_json_array_append_new, JANNASON_FAILURE);
|
||||
rc = json_add_object(&array, "name", &value);
|
||||
|
||||
assert_false(json_is_invalid(&array));
|
||||
assert_false(json_is_invalid(&value));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
/*
|
||||
* Test json append new failure with a NULL value
|
||||
*/
|
||||
will_return(__wrap_json_array_append_new, JANNASON_FAILURE);
|
||||
rc = json_add_object(&array, "null", NULL);
|
||||
|
||||
assert_false(json_is_invalid(&array));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
json_free(&array);
|
||||
json_free(&value);
|
||||
}
|
||||
|
||||
static void test_json_add_timestamp(void **state)
|
||||
{
|
||||
struct json_object object;
|
||||
int rc = 0;
|
||||
|
||||
will_return(__wrap_json_object, false);
|
||||
object = json_new_object();
|
||||
|
||||
/*
|
||||
* Test json string failure
|
||||
*/
|
||||
will_return(__wrap_gettimeofday, 0);
|
||||
will_return(__wrap_localtime, false);
|
||||
will_return(__wrap_json_string, true);
|
||||
rc = json_add_timestamp(&object);
|
||||
|
||||
/*
|
||||
* Test json_object_set_new failure
|
||||
*/
|
||||
will_return(__wrap_gettimeofday, 0);
|
||||
will_return(__wrap_localtime, false);
|
||||
will_return(__wrap_json_string, false);
|
||||
will_return(__wrap_json_object_set_new, JANNASON_FAILURE);
|
||||
rc = json_add_timestamp(&object);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
/*
|
||||
* Test gettimeofday failure
|
||||
*/
|
||||
will_return(__wrap_gettimeofday, -1);
|
||||
rc = json_add_timestamp(&object);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
/*
|
||||
* Test local time failure
|
||||
*/
|
||||
will_return(__wrap_gettimeofday, 0);
|
||||
will_return(__wrap_localtime, true);
|
||||
rc = json_add_timestamp(&object);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
json_free(&object);
|
||||
}
|
||||
|
||||
static void test_json_add_stringn(void **state)
|
||||
{
|
||||
struct json_object object;
|
||||
int rc = 0;
|
||||
|
||||
will_return(__wrap_json_object, false);
|
||||
object = json_new_object();
|
||||
assert_false(json_is_invalid(&object));
|
||||
|
||||
/*
|
||||
* Test json string failure
|
||||
*/
|
||||
will_return(__wrap_json_string, true);
|
||||
rc = json_add_stringn(&object, "name", "value", 3);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
/*
|
||||
* Test json object set new failure
|
||||
*/
|
||||
will_return(__wrap_json_string, false);
|
||||
will_return(__wrap_json_object_set_new, JANNASON_FAILURE);
|
||||
rc = json_add_stringn(&object, "name", "value", 3);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
/*
|
||||
* Test json object set new failure for a NULL string
|
||||
*/
|
||||
will_return(__wrap_json_object_set_new, JANNASON_FAILURE);
|
||||
rc = json_add_stringn(&object, "null", NULL, 2);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
/*
|
||||
* Test json object set new failure for a zero string size
|
||||
*/
|
||||
will_return(__wrap_json_object_set_new, JANNASON_FAILURE);
|
||||
rc = json_add_stringn(&object, "zero", "no value", 0);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
json_free(&object);
|
||||
}
|
||||
|
||||
static void test_json_add_version(void **state)
|
||||
{
|
||||
struct json_object object;
|
||||
int rc = 0;
|
||||
|
||||
/*
|
||||
* Fail creating the version object
|
||||
*/
|
||||
will_return(__wrap_json_object, false);
|
||||
object = json_new_object();
|
||||
|
||||
will_return(__wrap_json_object, true);
|
||||
rc = json_add_version(&object, 1, 11);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
json_free(&object);
|
||||
|
||||
/*
|
||||
* Fail adding the major version
|
||||
*/
|
||||
will_return(__wrap_json_object, false);
|
||||
object = json_new_object();
|
||||
|
||||
will_return(__wrap_json_object, false);
|
||||
will_return(__wrap_json_integer, false);
|
||||
will_return(__wrap_json_object_set_new, JANNASON_FAILURE);
|
||||
rc = json_add_version(&object, 2, 12);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
json_free(&object);
|
||||
|
||||
/*
|
||||
* Fail adding the minor version
|
||||
*/
|
||||
will_return(__wrap_json_object, false);
|
||||
object = json_new_object();
|
||||
|
||||
will_return(__wrap_json_object, false);
|
||||
will_return(__wrap_json_integer, false);
|
||||
will_return(__wrap_json_object_set_new, CALL_ORIG);
|
||||
will_return(__wrap_json_integer, false);
|
||||
will_return(__wrap_json_object_set_new, JANNASON_FAILURE);
|
||||
rc = json_add_version(&object, 3, 13);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
json_free(&object);
|
||||
|
||||
/*
|
||||
* Fail adding the version object
|
||||
*/
|
||||
will_return(__wrap_json_object, false);
|
||||
object = json_new_object();
|
||||
|
||||
will_return(__wrap_json_object, false);
|
||||
will_return(__wrap_json_integer, false);
|
||||
will_return(__wrap_json_object_set_new, CALL_ORIG);
|
||||
will_return(__wrap_json_integer, false);
|
||||
will_return(__wrap_json_object_set_new, JANNASON_FAILURE);
|
||||
rc = json_add_version(&object, 4, 14);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
json_free(&object);
|
||||
}
|
||||
|
||||
static void test_json_add_address(void **state)
|
||||
{
|
||||
struct json_object object;
|
||||
int rc = 0;
|
||||
struct tsocket_address *ip = NULL;
|
||||
|
||||
TALLOC_CTX *ctx = NULL;
|
||||
|
||||
will_return(__wrap_talloc_named_const, REAL_TALLOC);
|
||||
ctx = talloc_new(NULL);
|
||||
|
||||
/*
|
||||
* Add a null address
|
||||
*/
|
||||
will_return(__wrap_json_object, false);
|
||||
object = json_new_object();
|
||||
|
||||
will_return(__wrap_json_object_set_new, JANNASON_FAILURE);
|
||||
rc = json_add_address(&object, "name", NULL);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
/*
|
||||
* Add a non null address, json_object_set_new failure
|
||||
*/
|
||||
rc = tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 21, &ip);
|
||||
assert_int_equal(0, rc);
|
||||
|
||||
will_return(__wrap_talloc_named_const, REAL_TALLOC);
|
||||
will_return(__wrap_tsocket_address_string, false);
|
||||
will_return(__wrap_json_string, false);
|
||||
will_return(__wrap_json_object_set_new, JANNASON_FAILURE);
|
||||
rc = json_add_address(&object, "name", ip);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
/*
|
||||
* Add a non null address, with a talloc failure
|
||||
*/
|
||||
rc = tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 21, &ip);
|
||||
assert_int_equal(0, rc);
|
||||
|
||||
will_return(__wrap_talloc_named_const, NULL);
|
||||
rc = json_add_address(&object, "name", ip);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
/*
|
||||
* Add a non null address, tsocket_address_string failure
|
||||
*/
|
||||
rc = tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 21, &ip);
|
||||
assert_int_equal(0, rc);
|
||||
|
||||
will_return(__wrap_talloc_named_const, REAL_TALLOC);
|
||||
will_return(__wrap_tsocket_address_string, true);
|
||||
rc = json_add_address(&object, "name", ip);
|
||||
|
||||
assert_false(json_is_invalid(&object));
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
TALLOC_FREE(ctx);
|
||||
json_free(&object);
|
||||
}
|
||||
|
||||
static void test_json_add_sid(void **state)
|
||||
{
|
||||
struct json_object object;
|
||||
const char *SID = "S-1-5-21-2470180966-3899876309-2637894779";
|
||||
struct dom_sid sid;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Add a null SID
|
||||
*/
|
||||
will_return(__wrap_json_object, false);
|
||||
object = json_new_object();
|
||||
|
||||
will_return(__wrap_json_object_set_new, JANNASON_FAILURE);
|
||||
rc = json_add_sid(&object, "null", NULL);
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
/*
|
||||
* Add a non null SID
|
||||
*/
|
||||
assert_true(string_to_sid(&sid, SID));
|
||||
will_return(__wrap_json_string, false);
|
||||
will_return(__wrap_json_object_set_new, JANNASON_FAILURE);
|
||||
rc = json_add_sid(&object, "sid", &sid);
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
json_free(&object);
|
||||
}
|
||||
|
||||
static void test_json_add_guid(void **state)
|
||||
{
|
||||
struct json_object object;
|
||||
const char *GUID = "3ab88633-1e57-4c1a-856c-d1bc4b15bbb1";
|
||||
struct GUID guid;
|
||||
NTSTATUS status;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Add a null GUID
|
||||
*/
|
||||
will_return(__wrap_json_object, false);
|
||||
object = json_new_object();
|
||||
|
||||
will_return(__wrap_json_object_set_new, JANNASON_FAILURE);
|
||||
rc = json_add_guid(&object, "null", NULL);
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
/*
|
||||
* Add a non null GUID
|
||||
*/
|
||||
status = GUID_from_string(GUID, &guid);
|
||||
assert_true(NT_STATUS_IS_OK(status));
|
||||
will_return(__wrap_json_string, false);
|
||||
will_return(__wrap_json_object_set_new, JANNASON_FAILURE);
|
||||
rc = json_add_guid(&object, "guid", &guid);
|
||||
assert_int_equal(JSON_ERROR, rc);
|
||||
|
||||
json_free(&object);
|
||||
}
|
||||
|
||||
static void test_json_to_string(void **state)
|
||||
{
|
||||
struct json_object object;
|
||||
char *s = NULL;
|
||||
TALLOC_CTX *ctx = NULL;
|
||||
|
||||
will_return(__wrap_talloc_named_const, REAL_TALLOC);
|
||||
ctx = talloc_new(NULL);
|
||||
|
||||
will_return(__wrap_json_object, false);
|
||||
object = json_new_object();
|
||||
|
||||
/*
|
||||
* json_dumps failure
|
||||
*/
|
||||
will_return(__wrap_json_dumps, true);
|
||||
s = json_to_string(ctx, &object);
|
||||
assert_null(s);
|
||||
|
||||
/*
|
||||
* talloc failure
|
||||
*/
|
||||
will_return(__wrap_json_dumps, false);
|
||||
will_return(__wrap_talloc_strdup, NULL);
|
||||
s = json_to_string(ctx, &object);
|
||||
assert_null(s);
|
||||
TALLOC_FREE(ctx);
|
||||
json_free(&object);
|
||||
}
|
||||
|
||||
static void test_json_get_array(void **state)
|
||||
{
|
||||
struct json_object object;
|
||||
struct json_object stored_array;
|
||||
struct json_object array;
|
||||
|
||||
int rc;
|
||||
|
||||
will_return(__wrap_json_object, false);
|
||||
object = json_new_object();
|
||||
assert_false(json_is_invalid(&object));
|
||||
|
||||
will_return(__wrap_json_array, false);
|
||||
stored_array = json_new_array();
|
||||
assert_false(json_is_invalid(&stored_array));
|
||||
|
||||
will_return(__wrap_json_object_set_new, CALL_ORIG);
|
||||
rc = json_add_object(&object, "array", &stored_array);
|
||||
assert_int_equal(0, rc);
|
||||
|
||||
/*
|
||||
* json array failure
|
||||
*/
|
||||
will_return(__wrap_json_array, true);
|
||||
array = json_get_array(&object, "array");
|
||||
assert_true(json_is_invalid(&array));
|
||||
|
||||
/*
|
||||
* json array extend failure
|
||||
*/
|
||||
will_return(__wrap_json_array, false);
|
||||
will_return(__wrap_json_array_extend, true);
|
||||
array = json_get_array(&object, "array");
|
||||
assert_true(json_is_invalid(&array));
|
||||
|
||||
json_free(&stored_array);
|
||||
json_free(&object);
|
||||
}
|
||||
|
||||
static void test_json_get_object(void **state)
|
||||
{
|
||||
struct json_object object;
|
||||
struct json_object stored;
|
||||
struct json_object retreived;
|
||||
|
||||
int rc;
|
||||
|
||||
will_return(__wrap_json_object, false);
|
||||
object = json_new_object();
|
||||
assert_false(json_is_invalid(&object));
|
||||
|
||||
will_return(__wrap_json_object, false);
|
||||
stored = json_new_object();
|
||||
assert_false(json_is_invalid(&stored));
|
||||
|
||||
will_return(__wrap_json_object_set_new, CALL_ORIG);
|
||||
rc = json_add_object(&object, "stored", &stored);
|
||||
assert_int_equal(0, rc);
|
||||
|
||||
/*
|
||||
* json object update failure
|
||||
*/
|
||||
will_return(__wrap_json_object, false);
|
||||
will_return(__wrap_json_object_update, true);
|
||||
retreived = json_get_object(&object, "stored");
|
||||
assert_true(json_is_invalid(&retreived));
|
||||
|
||||
json_free(&object);
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(test_json_add_int),
|
||||
cmocka_unit_test(test_json_add_bool),
|
||||
cmocka_unit_test(test_json_add_string),
|
||||
cmocka_unit_test(test_json_add_object),
|
||||
cmocka_unit_test(test_json_add_to_array),
|
||||
cmocka_unit_test(test_json_add_timestamp),
|
||||
cmocka_unit_test(test_json_add_stringn),
|
||||
cmocka_unit_test(test_json_add_version),
|
||||
cmocka_unit_test(test_json_add_address),
|
||||
cmocka_unit_test(test_json_add_sid),
|
||||
cmocka_unit_test(test_json_add_guid),
|
||||
cmocka_unit_test(test_json_to_string),
|
||||
cmocka_unit_test(test_json_get_array),
|
||||
cmocka_unit_test(test_json_get_object),
|
||||
};
|
||||
|
||||
cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
@ -23,3 +23,34 @@ if bld.AD_DC_BUILD_IS_ENABLED() and bld.CONFIG_GET('ENABLE_SELFTEST'):
|
||||
''',
|
||||
install=False
|
||||
)
|
||||
|
||||
if bld.AD_DC_BUILD_IS_ENABLED() and bld.CONFIG_GET('ENABLE_SELFTEST'):
|
||||
bld.SAMBA_BINARY(
|
||||
'audit_logging_error_test',
|
||||
source='tests/audit_logging_error_test.c',
|
||||
deps='''
|
||||
audit_logging
|
||||
jansson
|
||||
cmocka
|
||||
talloc
|
||||
samba-util
|
||||
LIBTSOCKET
|
||||
''',
|
||||
install=False,
|
||||
ldflags='''
|
||||
-Wl,--wrap,json_object_set_new
|
||||
-Wl,--wrap,json_object_update
|
||||
-Wl,--wrap,json_array_append_new
|
||||
-Wl,--wrap,json_array_extend
|
||||
-Wl,--wrap,json_object
|
||||
-Wl,--wrap,json_string
|
||||
-Wl,--wrap,json_integer
|
||||
-Wl,--wrap,json_array
|
||||
-Wl,--wrap,json_dumps
|
||||
-Wl,--wrap,gettimeofday
|
||||
-Wl,--wrap,localtime
|
||||
-Wl,--wrap,talloc_named_const
|
||||
-Wl,--wrap,talloc_strdup
|
||||
-Wl,--wrap,tsocket_address_string
|
||||
'''
|
||||
)
|
||||
|
639
source4/dsdb/samdb/ldb_modules/tests/test_audit_log_errors.c
Normal file
639
source4/dsdb/samdb/ldb_modules/tests/test_audit_log_errors.c
Normal file
@ -0,0 +1,639 @@
|
||||
/*
|
||||
Unit tests for the dsdb audit logging code code in audit_log.c
|
||||
|
||||
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2018
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These tests exercise the error handling code
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <setjmp.h>
|
||||
#include <unistd.h>
|
||||
#include <cmocka.h>
|
||||
|
||||
int ldb_audit_log_module_init(const char *version);
|
||||
#include "../audit_log.c"
|
||||
#include "lib/ldb/include/ldb_private.h"
|
||||
|
||||
/*
|
||||
* cmocka wrappers for json_new_object
|
||||
*/
|
||||
struct json_object __wrap_json_new_object(void);
|
||||
struct json_object __real_json_new_object(void);
|
||||
struct json_object __wrap_json_new_object(void)
|
||||
{
|
||||
|
||||
bool use_real = (bool)mock();
|
||||
if (!use_real) {
|
||||
return json_empty_object;
|
||||
}
|
||||
return __real_json_new_object();
|
||||
}
|
||||
|
||||
/*
|
||||
* cmocka wrappers for json_add_version
|
||||
*/
|
||||
int __wrap_json_add_version(struct json_object *object, int major, int minor);
|
||||
int __real_json_add_version(struct json_object *object, int major, int minor);
|
||||
int __wrap_json_add_version(struct json_object *object, int major, int minor)
|
||||
{
|
||||
|
||||
int ret = (int)mock();
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
return __real_json_add_version(object, major, minor);
|
||||
}
|
||||
|
||||
/*
|
||||
* cmocka wrappers for json_add_version
|
||||
*/
|
||||
int __wrap_json_add_timestamp(struct json_object *object);
|
||||
int __real_json_add_timestamp(struct json_object *object);
|
||||
int __wrap_json_add_timestamp(struct json_object *object)
|
||||
{
|
||||
|
||||
int ret = (int)mock();
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
return __real_json_add_timestamp(object);
|
||||
}
|
||||
/*
|
||||
* unit test of operation_json, that ensures that all the expected
|
||||
* attributes and objects are in the json object.
|
||||
*/
|
||||
static void test_operation_json(void **state)
|
||||
{
|
||||
struct ldb_context *ldb = NULL;
|
||||
struct ldb_module *module = NULL;
|
||||
struct ldb_request *req = NULL;
|
||||
struct ldb_reply *reply = NULL;
|
||||
struct audit_private *audit_private = NULL;
|
||||
|
||||
struct tsocket_address *ts = NULL;
|
||||
|
||||
struct auth_session_info *sess = NULL;
|
||||
struct security_token *token = NULL;
|
||||
struct dom_sid sid;
|
||||
const char *const SID = "S-1-5-21-2470180966-3899876309-2637894779";
|
||||
const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
|
||||
struct GUID session_id;
|
||||
|
||||
struct GUID transaction_id;
|
||||
const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
|
||||
|
||||
struct ldb_dn *dn = NULL;
|
||||
const char *const DN = "dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG";
|
||||
|
||||
struct ldb_message *msg = NULL;
|
||||
|
||||
struct json_object json;
|
||||
|
||||
|
||||
/*
|
||||
* Test setup
|
||||
*/
|
||||
TALLOC_CTX *ctx = talloc_new(NULL);
|
||||
|
||||
ldb = ldb_init(ctx, NULL);
|
||||
|
||||
audit_private = talloc_zero(ctx, struct audit_private);
|
||||
GUID_from_string(TRANSACTION, &transaction_id);
|
||||
audit_private->transaction_guid = transaction_id;
|
||||
|
||||
module = talloc_zero(ctx, struct ldb_module);
|
||||
module->ldb = ldb;
|
||||
ldb_module_set_private(module, audit_private);
|
||||
|
||||
tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
|
||||
ldb_set_opaque(ldb, "remoteAddress", ts);
|
||||
|
||||
sess = talloc_zero(ctx, struct auth_session_info);
|
||||
token = talloc_zero(ctx, struct security_token);
|
||||
string_to_sid(&sid, SID);
|
||||
token->num_sids = 1;
|
||||
token->sids = &sid;
|
||||
sess->security_token = token;
|
||||
GUID_from_string(SESSION, &session_id);
|
||||
sess->unique_session_token = session_id;
|
||||
ldb_set_opaque(ldb, DSDB_SESSION_INFO, sess);
|
||||
|
||||
msg = talloc_zero(ctx, struct ldb_message);
|
||||
dn = ldb_dn_new(ctx, ldb, DN);
|
||||
msg->dn = dn;
|
||||
ldb_msg_add_string(msg, "attribute", "the-value");
|
||||
|
||||
req = talloc_zero(ctx, struct ldb_request);
|
||||
req->operation = LDB_ADD;
|
||||
req->op.add.message = msg;
|
||||
|
||||
reply = talloc_zero(ctx, struct ldb_reply);
|
||||
reply->error = LDB_ERR_OPERATIONS_ERROR;
|
||||
|
||||
/*
|
||||
* Fail on the creation of the audit json object
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, false);
|
||||
|
||||
json = operation_json(module, req, reply);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Fail adding the version object .
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, JSON_ERROR);
|
||||
|
||||
json = operation_json(module, req, reply);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Fail on creation of the wrapper.
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, 0);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_new_object, false);
|
||||
|
||||
json = operation_json(module, req, reply);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Fail adding the timestamp to the wrapper object.
|
||||
*/
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, 0);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_timestamp, JSON_ERROR);
|
||||
|
||||
json = operation_json(module, req, reply);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Now test the happy path
|
||||
*/
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, 0);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_timestamp, 0);
|
||||
|
||||
json = operation_json(module, req, reply);
|
||||
assert_false(json_is_invalid(&json));
|
||||
json_free(&json);
|
||||
|
||||
TALLOC_FREE(ctx);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* minimal unit test of password_change_json, that ensures that all the expected
|
||||
* attributes and objects are in the json object.
|
||||
*/
|
||||
static void test_password_change_json(void **state)
|
||||
{
|
||||
struct ldb_context *ldb = NULL;
|
||||
struct ldb_module *module = NULL;
|
||||
struct ldb_request *req = NULL;
|
||||
struct ldb_reply *reply = NULL;
|
||||
struct audit_private *audit_private = NULL;
|
||||
|
||||
struct tsocket_address *ts = NULL;
|
||||
|
||||
struct auth_session_info *sess = NULL;
|
||||
struct security_token *token = NULL;
|
||||
struct dom_sid sid;
|
||||
const char *const SID = "S-1-5-21-2470180966-3899876309-2637894779";
|
||||
const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
|
||||
struct GUID session_id;
|
||||
|
||||
struct GUID transaction_id;
|
||||
const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
|
||||
|
||||
struct ldb_dn *dn = NULL;
|
||||
const char *const DN = "dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG";
|
||||
|
||||
struct ldb_message *msg = NULL;
|
||||
|
||||
struct json_object json;
|
||||
|
||||
TALLOC_CTX *ctx = talloc_new(NULL);
|
||||
|
||||
ldb = ldb_init(ctx, NULL);
|
||||
|
||||
audit_private = talloc_zero(ctx, struct audit_private);
|
||||
GUID_from_string(TRANSACTION, &transaction_id);
|
||||
audit_private->transaction_guid = transaction_id;
|
||||
|
||||
module = talloc_zero(ctx, struct ldb_module);
|
||||
module->ldb = ldb;
|
||||
ldb_module_set_private(module, audit_private);
|
||||
|
||||
tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
|
||||
ldb_set_opaque(ldb, "remoteAddress", ts);
|
||||
|
||||
sess = talloc_zero(ctx, struct auth_session_info);
|
||||
token = talloc_zero(ctx, struct security_token);
|
||||
string_to_sid(&sid, SID);
|
||||
token->num_sids = 1;
|
||||
token->sids = &sid;
|
||||
sess->security_token = token;
|
||||
GUID_from_string(SESSION, &session_id);
|
||||
sess->unique_session_token = session_id;
|
||||
ldb_set_opaque(ldb, DSDB_SESSION_INFO, sess);
|
||||
|
||||
msg = talloc_zero(ctx, struct ldb_message);
|
||||
dn = ldb_dn_new(ctx, ldb, DN);
|
||||
msg->dn = dn;
|
||||
ldb_msg_add_string(msg, "planTextPassword", "super-secret");
|
||||
|
||||
req = talloc_zero(ctx, struct ldb_request);
|
||||
req->operation = LDB_ADD;
|
||||
req->op.add.message = msg;
|
||||
reply = talloc_zero(ctx, struct ldb_reply);
|
||||
reply->error = LDB_SUCCESS;
|
||||
|
||||
|
||||
/*
|
||||
* Fail on the creation of the audit json object
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, false);
|
||||
json = password_change_json(module, req, reply);
|
||||
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Fail adding the version object .
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, JSON_ERROR);
|
||||
|
||||
json = password_change_json(module, req, reply);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Fail on creation of the wrapper.
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, 0);
|
||||
will_return(__wrap_json_new_object, false);
|
||||
|
||||
json = password_change_json(module, req, reply);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Fail on creation of the time stamp.
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, 0);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_timestamp, JSON_ERROR);
|
||||
|
||||
json = password_change_json(module, req, reply);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Now test the happy path
|
||||
*/
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, 0);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_timestamp, 0);
|
||||
|
||||
json = password_change_json(module, req, reply);
|
||||
assert_false(json_is_invalid(&json));
|
||||
json_free(&json);
|
||||
|
||||
TALLOC_FREE(ctx);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* minimal unit test of transaction_json, that ensures that all the expected
|
||||
* attributes and objects are in the json object.
|
||||
*/
|
||||
static void test_transaction_json(void **state)
|
||||
{
|
||||
|
||||
struct GUID guid;
|
||||
const char * const GUID = "7130cb06-2062-6a1b-409e-3514c26b1773";
|
||||
|
||||
struct json_object json;
|
||||
|
||||
GUID_from_string(GUID, &guid);
|
||||
|
||||
|
||||
/*
|
||||
* Fail on the creation of the audit json object
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, false);
|
||||
|
||||
json = transaction_json("delete", &guid, 10000099);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Fail adding the version object .
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, JSON_ERROR);
|
||||
|
||||
json = transaction_json("delete", &guid, 10000099);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Fail on creation of the wrapper.
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, 0);
|
||||
will_return(__wrap_json_new_object, false);
|
||||
|
||||
json = transaction_json("delete", &guid, 10000099);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Fail on creation of the time stamp.
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, 0);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_timestamp, JSON_ERROR);
|
||||
|
||||
json = transaction_json("delete", &guid, 10000099);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Now test the happy path
|
||||
*/
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, 0);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_timestamp, 0);
|
||||
|
||||
json = transaction_json("delete", &guid, 10000099);
|
||||
assert_false(json_is_invalid(&json));
|
||||
json_free(&json);
|
||||
}
|
||||
|
||||
/*
|
||||
* minimal unit test of commit_failure_json, that ensures that all the
|
||||
* expected attributes and objects are in the json object.
|
||||
*/
|
||||
static void test_commit_failure_json(void **state)
|
||||
{
|
||||
|
||||
struct GUID guid;
|
||||
const char * const GUID = "7130cb06-2062-6a1b-409e-3514c26b1773";
|
||||
|
||||
struct json_object json;
|
||||
|
||||
GUID_from_string(GUID, &guid);
|
||||
|
||||
|
||||
/*
|
||||
* Fail on the creation of the audit json object
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, false);
|
||||
|
||||
json = commit_failure_json(
|
||||
"prepare",
|
||||
987876,
|
||||
LDB_ERR_OPERATIONS_ERROR,
|
||||
"because",
|
||||
&guid);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Fail adding the version object .
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, JSON_ERROR);
|
||||
|
||||
json = commit_failure_json(
|
||||
"prepare",
|
||||
987876,
|
||||
LDB_ERR_OPERATIONS_ERROR,
|
||||
"because",
|
||||
&guid);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Fail on creation of the wrapper.
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, 0);
|
||||
will_return(__wrap_json_new_object, false);
|
||||
|
||||
json = commit_failure_json(
|
||||
"prepare",
|
||||
987876,
|
||||
LDB_ERR_OPERATIONS_ERROR,
|
||||
"because",
|
||||
&guid);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Fail on creation of the time stamp.
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, 0);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_timestamp, JSON_ERROR);
|
||||
|
||||
json = commit_failure_json(
|
||||
"prepare",
|
||||
987876,
|
||||
LDB_ERR_OPERATIONS_ERROR,
|
||||
"because",
|
||||
&guid);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Now test the happy path
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, 0);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_timestamp, 0);
|
||||
|
||||
json = commit_failure_json(
|
||||
"prepare",
|
||||
987876,
|
||||
LDB_ERR_OPERATIONS_ERROR,
|
||||
"because",
|
||||
&guid);
|
||||
assert_false(json_is_invalid(&json));
|
||||
json_free(&json);
|
||||
}
|
||||
|
||||
/*
|
||||
* unit test of replicated_update_json, that ensures that all the expected
|
||||
* attributes and objects are in the json object.
|
||||
*/
|
||||
static void test_replicated_update_json(void **state)
|
||||
{
|
||||
struct ldb_context *ldb = NULL;
|
||||
struct ldb_module *module = NULL;
|
||||
struct ldb_request *req = NULL;
|
||||
struct ldb_reply *reply = NULL;
|
||||
struct audit_private *audit_private = NULL;
|
||||
struct dsdb_extended_replicated_objects *ro = NULL;
|
||||
struct repsFromTo1 *source_dsa = NULL;
|
||||
|
||||
struct GUID transaction_id;
|
||||
const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
|
||||
|
||||
struct ldb_dn *dn = NULL;
|
||||
const char *const DN = "dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG";
|
||||
|
||||
struct GUID source_dsa_obj_guid;
|
||||
const char *const SOURCE_DSA = "7130cb06-2062-6a1b-409e-3514c26b1793";
|
||||
|
||||
struct GUID invocation_id;
|
||||
const char *const INVOCATION_ID =
|
||||
"7130cb06-2062-6a1b-409e-3514c26b1893";
|
||||
struct json_object json;
|
||||
|
||||
TALLOC_CTX *ctx = talloc_new(NULL);
|
||||
|
||||
ldb = ldb_init(ctx, NULL);
|
||||
|
||||
audit_private = talloc_zero(ctx, struct audit_private);
|
||||
GUID_from_string(TRANSACTION, &transaction_id);
|
||||
audit_private->transaction_guid = transaction_id;
|
||||
|
||||
module = talloc_zero(ctx, struct ldb_module);
|
||||
module->ldb = ldb;
|
||||
ldb_module_set_private(module, audit_private);
|
||||
|
||||
dn = ldb_dn_new(ctx, ldb, DN);
|
||||
GUID_from_string(SOURCE_DSA, &source_dsa_obj_guid);
|
||||
GUID_from_string(INVOCATION_ID, &invocation_id);
|
||||
source_dsa = talloc_zero(ctx, struct repsFromTo1);
|
||||
source_dsa->source_dsa_obj_guid = source_dsa_obj_guid;
|
||||
source_dsa->source_dsa_invocation_id = invocation_id;
|
||||
|
||||
ro = talloc_zero(ctx, struct dsdb_extended_replicated_objects);
|
||||
ro->source_dsa = source_dsa;
|
||||
ro->num_objects = 808;
|
||||
ro->linked_attributes_count = 2910;
|
||||
ro->partition_dn = dn;
|
||||
ro->error = WERR_NOT_SUPPORTED;
|
||||
|
||||
|
||||
req = talloc_zero(ctx, struct ldb_request);
|
||||
req->op.extended.data = ro;
|
||||
req->operation = LDB_EXTENDED;
|
||||
|
||||
reply = talloc_zero(ctx, struct ldb_reply);
|
||||
reply->error = LDB_ERR_NO_SUCH_OBJECT;
|
||||
|
||||
|
||||
/*
|
||||
* Fail on the creation of the audit json object
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, false);
|
||||
|
||||
json = replicated_update_json(module, req, reply);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Fail adding the version object .
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, JSON_ERROR);
|
||||
|
||||
json = replicated_update_json(module, req, reply);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Fail on creation of the wrapper.
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, 0);
|
||||
will_return(__wrap_json_new_object, false);
|
||||
|
||||
json = replicated_update_json(module, req, reply);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Fail on creation of the time stamp.
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, 0);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_timestamp, JSON_ERROR);
|
||||
|
||||
json = replicated_update_json(module, req, reply);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Now test the happy path.
|
||||
*/
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, 0);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_timestamp, 0);
|
||||
|
||||
json = replicated_update_json(module, req, reply);
|
||||
assert_false(json_is_invalid(&json));
|
||||
json_free(&json);
|
||||
|
||||
TALLOC_FREE(ctx);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(test_operation_json),
|
||||
cmocka_unit_test(test_password_change_json),
|
||||
cmocka_unit_test(test_transaction_json),
|
||||
cmocka_unit_test(test_commit_failure_json),
|
||||
cmocka_unit_test(test_replicated_update_json),
|
||||
};
|
||||
|
||||
cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
265
source4/dsdb/samdb/ldb_modules/tests/test_group_audit_errors.c
Normal file
265
source4/dsdb/samdb/ldb_modules/tests/test_group_audit_errors.c
Normal file
@ -0,0 +1,265 @@
|
||||
/*
|
||||
Unit tests for the dsdb group auditing code in group_audit.c
|
||||
|
||||
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2018
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These tests exercise the error handling routines.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <setjmp.h>
|
||||
#include <unistd.h>
|
||||
#include <cmocka.h>
|
||||
|
||||
int ldb_group_audit_log_module_init(const char *version);
|
||||
#include "../group_audit.c"
|
||||
|
||||
#include "lib/ldb/include/ldb_private.h"
|
||||
|
||||
/*
|
||||
* cmocka wrappers for json_new_object
|
||||
*/
|
||||
struct json_object __wrap_json_new_object(void);
|
||||
struct json_object __real_json_new_object(void);
|
||||
struct json_object __wrap_json_new_object(void)
|
||||
{
|
||||
|
||||
bool use_real = (bool)mock();
|
||||
if (!use_real) {
|
||||
return json_empty_object;
|
||||
}
|
||||
return __real_json_new_object();
|
||||
}
|
||||
|
||||
/*
|
||||
* cmocka wrappers for json_add_version
|
||||
*/
|
||||
int __wrap_json_add_version(struct json_object *object, int major, int minor);
|
||||
int __real_json_add_version(struct json_object *object, int major, int minor);
|
||||
int __wrap_json_add_version(struct json_object *object, int major, int minor)
|
||||
{
|
||||
|
||||
int ret = (int)mock();
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
return __real_json_add_version(object, major, minor);
|
||||
}
|
||||
|
||||
/*
|
||||
* cmocka wrappers for json_add_version
|
||||
*/
|
||||
int __wrap_json_add_timestamp(struct json_object *object);
|
||||
int __real_json_add_timestamp(struct json_object *object);
|
||||
int __wrap_json_add_timestamp(struct json_object *object)
|
||||
{
|
||||
|
||||
int ret = (int)mock();
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
return __real_json_add_timestamp(object);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test helper to add a session id and user SID
|
||||
*/
|
||||
static void add_session_data(
|
||||
TALLOC_CTX *ctx,
|
||||
struct ldb_context *ldb,
|
||||
const char *session,
|
||||
const char *user_sid)
|
||||
{
|
||||
struct auth_session_info *sess = NULL;
|
||||
struct security_token *token = NULL;
|
||||
struct dom_sid *sid = NULL;
|
||||
struct GUID session_id;
|
||||
bool ok;
|
||||
|
||||
sess = talloc_zero(ctx, struct auth_session_info);
|
||||
token = talloc_zero(ctx, struct security_token);
|
||||
sid = talloc_zero(ctx, struct dom_sid);
|
||||
ok = string_to_sid(sid, user_sid);
|
||||
assert_true(ok);
|
||||
token->sids = sid;
|
||||
sess->security_token = token;
|
||||
GUID_from_string(session, &session_id);
|
||||
sess->unique_session_token = session_id;
|
||||
ldb_set_opaque(ldb, DSDB_SESSION_INFO, sess);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test helper to insert a transaction_id into a request.
|
||||
*/
|
||||
static void add_transaction_id(struct ldb_request *req, const char *id)
|
||||
{
|
||||
struct GUID guid;
|
||||
struct dsdb_control_transaction_identifier *transaction_id = NULL;
|
||||
|
||||
transaction_id = talloc_zero(
|
||||
req,
|
||||
struct dsdb_control_transaction_identifier);
|
||||
assert_non_null(transaction_id);
|
||||
GUID_from_string(id, &guid);
|
||||
transaction_id->transaction_guid = guid;
|
||||
ldb_request_add_control(
|
||||
req,
|
||||
DSDB_CONTROL_TRANSACTION_IDENTIFIER_OID,
|
||||
false,
|
||||
transaction_id);
|
||||
}
|
||||
|
||||
static void test_audit_group_json(void **state)
|
||||
{
|
||||
struct ldb_context *ldb = NULL;
|
||||
struct ldb_module *module = NULL;
|
||||
struct ldb_request *req = NULL;
|
||||
|
||||
struct tsocket_address *ts = NULL;
|
||||
|
||||
const char *const SID = "S-1-5-21-2470180966-3899876309-2637894779";
|
||||
const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
|
||||
|
||||
struct GUID transaction_id;
|
||||
const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
|
||||
|
||||
|
||||
struct json_object json;
|
||||
|
||||
TALLOC_CTX *ctx = talloc_new(NULL);
|
||||
|
||||
ldb = ldb_init(ctx, NULL);
|
||||
|
||||
GUID_from_string(TRANSACTION, &transaction_id);
|
||||
|
||||
module = talloc_zero(ctx, struct ldb_module);
|
||||
module->ldb = ldb;
|
||||
|
||||
tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
|
||||
ldb_set_opaque(ldb, "remoteAddress", ts);
|
||||
|
||||
add_session_data(ctx, ldb, SESSION, SID);
|
||||
|
||||
req = talloc_zero(ctx, struct ldb_request);
|
||||
req->operation = LDB_ADD;
|
||||
add_transaction_id(req, TRANSACTION);
|
||||
|
||||
/*
|
||||
* Fail on the creation of the audit json object
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, false);
|
||||
|
||||
json = audit_group_json(
|
||||
module,
|
||||
req,
|
||||
"the-action",
|
||||
"the-user-name",
|
||||
"the-group-name",
|
||||
LDB_ERR_OPERATIONS_ERROR);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Fail adding the version object .
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, JSON_ERROR);
|
||||
|
||||
json = audit_group_json(
|
||||
module,
|
||||
req,
|
||||
"the-action",
|
||||
"the-user-name",
|
||||
"the-group-name",
|
||||
LDB_ERR_OPERATIONS_ERROR);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Fail on creation of the wrapper.
|
||||
*/
|
||||
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, 0);
|
||||
will_return(__wrap_json_new_object, false);
|
||||
|
||||
json = audit_group_json(
|
||||
module,
|
||||
req,
|
||||
"the-action",
|
||||
"the-user-name",
|
||||
"the-group-name",
|
||||
LDB_ERR_OPERATIONS_ERROR);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
/*
|
||||
* Fail adding the timestamp to the wrapper object.
|
||||
*/
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, 0);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_timestamp, JSON_ERROR);
|
||||
|
||||
json = audit_group_json(
|
||||
module,
|
||||
req,
|
||||
"the-action",
|
||||
"the-user-name",
|
||||
"the-group-name",
|
||||
LDB_ERR_OPERATIONS_ERROR);
|
||||
assert_true(json_is_invalid(&json));
|
||||
|
||||
|
||||
/*
|
||||
* Now test the happy path
|
||||
*/
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_version, 0);
|
||||
will_return(__wrap_json_new_object, true);
|
||||
will_return(__wrap_json_add_timestamp, 0);
|
||||
|
||||
json = audit_group_json(
|
||||
module,
|
||||
req,
|
||||
"the-action",
|
||||
"the-user-name",
|
||||
"the-group-name",
|
||||
LDB_ERR_OPERATIONS_ERROR);
|
||||
assert_false(json_is_invalid(&json));
|
||||
|
||||
json_free(&json);
|
||||
TALLOC_FREE(ctx);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: to run under valgrind us:
|
||||
* valgrind --suppressions=test_group_audit.valgrind bin/test_group_audit
|
||||
* This suppresses the errors generated because the ldb_modules are not
|
||||
* de-registered.
|
||||
*
|
||||
*/
|
||||
int main(void) {
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(test_audit_group_json),
|
||||
};
|
||||
|
||||
cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
@ -37,6 +37,25 @@ bld.SAMBA_BINARY('test_audit_log',
|
||||
''',
|
||||
install=False)
|
||||
|
||||
bld.SAMBA_BINARY('test_audit_log_errors',
|
||||
source='tests/test_audit_log_errors.c',
|
||||
deps='''
|
||||
talloc
|
||||
samba-util
|
||||
samdb-common
|
||||
samdb
|
||||
cmocka
|
||||
audit_logging
|
||||
DSDB_MODULE_HELPERS
|
||||
DSDB_MODULE_HELPERS_AUDIT
|
||||
''',
|
||||
ldflags='''
|
||||
-Wl,--wrap,json_new_object
|
||||
-Wl,--wrap,json_add_version
|
||||
-Wl,--wrap,json_add_timestamp
|
||||
''',
|
||||
install=False)
|
||||
|
||||
bld.SAMBA_BINARY('test_group_audit',
|
||||
source='tests/test_group_audit.c',
|
||||
deps='''
|
||||
@ -51,6 +70,25 @@ bld.SAMBA_BINARY('test_group_audit',
|
||||
''',
|
||||
install=False)
|
||||
|
||||
bld.SAMBA_BINARY('test_group_audit_errors',
|
||||
source='tests/test_group_audit_errors.c',
|
||||
deps='''
|
||||
talloc
|
||||
samba-util
|
||||
samdb-common
|
||||
samdb
|
||||
cmocka
|
||||
audit_logging
|
||||
DSDB_MODULE_HELPERS
|
||||
DSDB_MODULE_HELPERS_AUDIT
|
||||
''',
|
||||
ldflags='''
|
||||
-Wl,--wrap,json_new_object
|
||||
-Wl,--wrap,json_add_version
|
||||
-Wl,--wrap,json_add_timestamp
|
||||
''',
|
||||
install=False)
|
||||
|
||||
bld.SAMBA_MODULE('ldb_samba_dsdb',
|
||||
source='samba_dsdb.c',
|
||||
subsystem='ldb',
|
||||
|
@ -1114,7 +1114,7 @@ for env in ["ad_dc_ntvfs", "ad_dc", "fl2000dc", "fl2003dc", "fl2008r2dc",
|
||||
'renamedc', 'labdc']:
|
||||
plantestsuite("samba4.blackbox.dbcheck(%s)" % env, env + ":local" , ["PYTHON=%s" % python, os.path.join(bbdir, "dbcheck.sh"), '$PREFIX/provision', configuration])
|
||||
|
||||
# cmocka tests not requiring a specific encironment
|
||||
# cmocka tests not requiring a specific environment
|
||||
#
|
||||
plantestsuite("samba4.dsdb.samdb.ldb_modules.unique_object_sids" , "none",
|
||||
[os.path.join(bindir(), "test_unique_object_sids")])
|
||||
@ -1122,7 +1122,15 @@ plantestsuite("samba4.dsdb.samdb.ldb_modules.encrypted_secrets", "none",
|
||||
[os.path.join(bindir(), "test_encrypted_secrets")])
|
||||
plantestsuite("lib.audit_logging.audit_logging", "none",
|
||||
[os.path.join(bindir(), "audit_logging_test")])
|
||||
plantestsuite("lib.audit_logging.audit_logging.errors", "none",
|
||||
[os.path.join(bindir(), "audit_logging_error_test")])
|
||||
plantestsuite("samba4.dsdb.samdb.ldb_modules.audit_util", "none",
|
||||
[os.path.join(bindir(), "test_audit_util")])
|
||||
plantestsuite("samba4.dsdb.samdb.ldb_modules.audit_log", "none",
|
||||
[os.path.join(bindir(), "test_audit_log")])
|
||||
plantestsuite("samba4.dsdb.samdb.ldb_modules.audit_log.errors", "none",
|
||||
[os.path.join(bindir(), "test_audit_log_errors")])
|
||||
plantestsuite("samba4.dsdb.samdb.ldb_modules.group_audit", "none",
|
||||
[os.path.join(bindir(), "test_group_audit")])
|
||||
plantestsuite("samba4.dsdb.samdb.ldb_modules.group_audit.errors", "none",
|
||||
[os.path.join(bindir(), "test_group_audit_errors")])
|
||||
|
Loading…
Reference in New Issue
Block a user