Back out regex use in python tests, filter the output instead.

This makes it possible to regenerate the test output again.
Also adds an update_test_data target to the Makefile.
This commit is contained in:
Todd C. Miller
2020-11-11 19:04:01 -07:00
parent b2ccbb3a90
commit d688f4d34e
23 changed files with 84 additions and 75 deletions

View File

@@ -223,6 +223,11 @@ check: $(TEST_PROGS)
./check_python_examples ".libs/python_plugin.so"; \
fi
update_test_data: $(TEST_PROGS)
@if test X"$(cross_compiling)" != X"yes"; then \
UPDATE_TESTDATA=1 ./check_python_examples ".libs/python_plugin.so"; \
fi
check_python_examples: $(CHECK_PYTHON_EXAMPLES_OBJS) $(LIBPYTHONPLUGIN)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_PYTHON_EXAMPLES_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)

View File

@@ -145,10 +145,9 @@ py_log_last_error(const char *context_message)
char *message = py_message ? py_create_string_rep(py_message) : NULL;
py_sudo_log(SUDO_CONV_ERROR_MSG, "%s%s(%s) %s\n",
py_sudo_log(SUDO_CONV_ERROR_MSG, "%s%s%s\n",
context_message ? context_message : "",
context_message && *context_message ? ": " : "",
py_type ? ((PyTypeObject *)py_type)->tp_name : "None",
message ? message : "(NULL)");
free(message);

View File

@@ -469,6 +469,7 @@ _python_plugin_get_class(const char *plugin_path, PyObject *py_module, const cha
py_class = PyObject_GetAttrString(py_module, plugin_class);
if (py_class == NULL) {
py_sudo_log(SUDO_CONV_ERROR_MSG, "Failed to find plugin class '%s'\n", plugin_class);
PyErr_Clear();
goto cleanup;
}

View File

@@ -22,7 +22,6 @@
#include "config.h"
#include "sudo_compat.h"
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

View File

@@ -1,6 +1,6 @@
sudo.debug was called with arguments: (<DEBUG.ERROR: 2>, 'My demo purpose plugin shows this ERROR level debug message')
sudo.debug was called with arguments: (<DEBUG.INFO: 6>, 'My demo purpose plugin shows this INFO level debug message')
LogHandler.emit was called with arguments: (<.*sudo.LogHandler.*
LogHandler.emit was called with arguments: (<.*sudo.LogHandler.*
LogHandler.emit was called
LogHandler.emit was called
sudo.options_as_dict was called with arguments: (('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin'),)
sudo.options_as_dict returned result: \[('ClassName', 'DebugDemoPlugin'), ('ModulePath', 'SRC_DIR/example_debugging.py')\]
sudo.options_as_dict returned result: [('ClassName', 'DebugDemoPlugin'), ('ModulePath', 'SRC_DIR/example_debugging.py')]

View File

@@ -2,10 +2,10 @@ __init__ @ SRC_DIR/example_debugging.py:58 calls C function:
sudo.debug was called with arguments: (<DEBUG.ERROR: 2>, 'My demo purpose plugin shows this ERROR level debug message')
__init__ @ SRC_DIR/example_debugging.py:63 calls C function:
sudo.debug was called with arguments: (<DEBUG.INFO: 6>, 'My demo purpose plugin shows this INFO level debug message')
handle @ .*/logging/__init__.py:[0-9]* calls C function:
LogHandler.emit was called with arguments: (<.*sudo.LogHandler.*
handle @ .*/logging/__init__.py:[0-9]* calls C function:
LogHandler.emit was called with arguments: (<.*sudo.LogHandler.*
handle @ logging/__init__.py calls C function:
LogHandler.emit was called
handle @ logging/__init__.py calls C function:
LogHandler.emit was called
__init__ @ SRC_DIR/example_debugging.py:85 calls C function:
sudo.options_as_dict was called with arguments: (('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin'),)
sudo.options_as_dict returned result: \[('ClassName', 'DebugDemoPlugin'), ('ModulePath', 'SRC_DIR/example_debugging.py')\]
sudo.options_as_dict returned result: [('ClassName', 'DebugDemoPlugin'), ('ModulePath', 'SRC_DIR/example_debugging.py')]

View File

@@ -2,7 +2,7 @@ __init__ @ SRC_DIR/example_debugging.py:58 debugs:
My demo purpose plugin shows this ERROR level debug message
__init__ @ SRC_DIR/example_debugging.py:63 debugs:
My demo purpose plugin shows this INFO level debug message
handle @ .*/logging/__init__.py:[0-9]* debugs:
handle @ logging/__init__.py debugs:
Python log system shows this ERROR level debug message
handle @ .*/logging/__init__.py:[0-9]* debugs:
handle @ logging/__init__.py debugs:
Python log system shows this INFO level debug message

View File

@@ -1,2 +1,2 @@
DebugDemoPlugin.__init__ was called with arguments: () \[('plugin_options', ('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin')), ('settings', ('debug_flags=/tmp/sudo_check_python_exampleXXXXXX/debug.log py_calls@diag', 'plugin_path=python_plugin.so')), ('user_env', ()), ('user_info', ()), ('version', '1.0')\]
DebugDemoPlugin.__init__ was called with arguments: () [('plugin_options', ('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin')), ('settings', ('debug_flags=/tmp/sudo_check_python_exampleXXXXXX/debug.log py_calls@diag', 'plugin_path=python_plugin.so')), ('user_env', ()), ('user_info', ()), ('version', '1.0')]
DebugDemoPlugin.__init__ returned result: <example_debugging.DebugDemoPlugin object>

View File

@@ -1,4 +1,4 @@
DebugDemoPlugin.__init__ was called with arguments: () \[('plugin_options', ('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin')), ('settings', ('debug_flags=/tmp/sudo_check_python_exampleXXXXXX/debug.log py_calls@info', 'plugin_path=python_plugin.so')), ('user_env', ()), ('user_info', ()), ('version', '1.0')\]
DebugDemoPlugin.__init__ was called with arguments: () [('plugin_options', ('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin')), ('settings', ('debug_flags=/tmp/sudo_check_python_exampleXXXXXX/debug.log py_calls@info', 'plugin_path=python_plugin.so')), ('user_env', ()), ('user_info', ()), ('version', '1.0')]
DebugDemoPlugin.__init__ returned result: <example_debugging.DebugDemoPlugin object>
DebugDemoPlugin function 'log_ttyin' is not implemented
DebugDemoPlugin function 'log_ttyout' is not implemented

View File

@@ -1,4 +1,4 @@
.*
SudoGroupPlugin.__init__ was called with arguments: () [('args', ('ModulePath=SRC_DIR/example_group_plugin.py', 'ClassName=SudoGroupPlugin')), ('version', '1.0')]
SudoGroupPlugin.__init__ returned result: <example_group_plugin.SudoGroupPlugin object>
SudoGroupPlugin.query was called with arguments: ('user', 'group', ('pw_name', 'pw_passwd', 1001, 101, 'pw_gecos', 'pw_dir', 'pw_shell'))
SudoGroupPlugin.query returned result: RC.REJECT

View File

@@ -1,9 +1,9 @@
-- Plugin STARTED --
EXEC id --help
EXEC info \[
EXEC info [
"command=/bin/id",
"runas_uid=0"
\]
]
STD IN some standard input
STD OUT some standard output
STD ERR some standard error

View File

@@ -1,9 +1,9 @@
-- Plugin STARTED --
EXEC id --help
EXEC info \[
EXEC info [
"command=/bin/id",
"runas_uid=0"
\]
]
STD IN stdin for plugin 1
STD OUT stdout for plugin 1
STD ERR stderr for plugin 1

View File

@@ -1,9 +1,9 @@
-- Plugin STARTED --
EXEC whoami
EXEC info \[
EXEC info [
"command=/bin/whoami",
"runas_uid=1"
\]
]
STD IN stdin for plugin 2
STD OUT stdout for plugin 2
STD ERR stderr for plugin 2

View File

@@ -1,8 +1,8 @@
-- Plugin STARTED --
EXEC cmd
EXEC info \[
EXEC info [
"command=/usr/share/cmd",
"runas_uid=0"
\]
]
CLOSE Failed to execute, execve returned 1 (EPERM)
-- Plugin DESTROYED --

View File

@@ -1 +1 @@
Failed to construct plugin instance: (FileNotFoundError) \[Errno 2\] No such file or directory: '/some/not/writable/directory/sudo.log'
Failed to construct plugin instance: [Errno 2] No such file or directory: '/some/not/writable/directory/sudo.log'

View File

@@ -1,4 +1,4 @@
SudoPolicyPlugin.__init__ was called with arguments: () \[('plugin_options', ('ModulePath=SRC_DIR/example_policy_plugin.py', 'ClassName=SudoPolicyPlugin')), ('settings', ()), ('user_env', ()), ('user_info', ()), ('version', '1.0')\]
SudoPolicyPlugin.__init__ was called with arguments: () [('plugin_options', ('ModulePath=SRC_DIR/example_policy_plugin.py', 'ClassName=SudoPolicyPlugin')), ('settings', ()), ('user_env', ()), ('user_info', ()), ('version', '1.0')]
SudoPolicyPlugin.__init__ returned result: <example_policy_plugin.SudoPolicyPlugin object>
SudoPolicyPlugin.validate was called with arguments: ()
SudoPolicyPlugin.validate returned result: None

View File

@@ -1 +1 @@
Failed during loading plugin class: (ImportError) File 'SRC_DIR/example_debugging.py' must be owned by uid 0
Failed during loading plugin class: File 'SRC_DIR/example_debugging.py' must be owned by uid 0

View File

@@ -1,2 +1,2 @@
Failed to find plugin class 'MispelledPluginName'
Failed during loading plugin class: (AttributeError) .* has no attribute 'MispelledPluginName'
Failed during loading plugin class

View File

@@ -1 +1 @@
Failed during loading plugin class: ([^)]*) No module named 'wrong_path'
Failed during loading plugin class: No module named 'wrong_path'

View File

@@ -1,61 +1,61 @@
(APPROVAL 1) Constructed:
{
"_id": "(APPROVAL 1)",
"plugin_options": \[
"plugin_options": [
"ModulePath=SRC_DIR/regress/plugin_approval_test.py",
"ClassName=ApprovalTestPlugin",
"Id=1"
\],
"settings": \[
],
"settings": [
"SETTING1=VALUE1",
"setting2=value2"
\],
"submit_argv": \[
],
"submit_argv": [
"sudo",
"-u",
"user",
"whoami",
"--help"
\],
],
"submit_optind": 3,
"user_env": \[
"user_env": [
"USER_ENV1=VALUE1",
"USER_ENV2=value2"
\],
"user_info": \[
],
"user_info": [
"INFO1=VALUE1",
"info2=value2"
\],
],
"version": "1.17"
}
(APPROVAL 2) Constructed:
{
"_id": "(APPROVAL 2)",
"plugin_options": \[
"plugin_options": [
"ModulePath=SRC_DIR/regress/plugin_approval_test.py",
"ClassName=ApprovalTestPlugin",
"Id=2"
\],
"settings": \[
],
"settings": [
"SETTING1=VALUE1",
"setting2=value2"
\],
"submit_argv": \[
],
"submit_argv": [
"sudo",
"-u",
"user",
"whoami",
"--help"
\],
],
"submit_optind": 3,
"user_env": \[
"user_env": [
"USER_ENV1=VALUE1",
"USER_ENV2=value2"
\],
"user_info": \[
],
"user_info": [
"INFO1=VALUE1",
"info2=value2"
\],
],
"version": "1.17"
}
(APPROVAL 1) Show version was called with arguments: (0,)

View File

@@ -1,4 +1,4 @@
PATH before: \[\] (should be empty)
PATH set: \['path_for_first_plugin'\]
PATH before: \[\] (should be empty)
PATH set: \['path_for_second_plugin'\]
PATH before: [] (should be empty)
PATH set: ['path_for_first_plugin']
PATH before: [] (should be empty)
PATH set: ['path_for_second_plugin']

View File

@@ -190,7 +190,7 @@ verify_log_lines(const char *reference_path)
char line[1024] = "";
char stored_str[MAX_OUTPUT] = "";
while(fgets(line, sizeof(line), file) != NULL) {
const char *line_data = strstr(line, "] "); // this skips the timestamp and pid at the beginning
char *line_data = strstr(line, "] "); // this skips the timestamp and pid at the beginning
VERIFY_NOT_NULL(line_data); // malformed log line
line_data += 2;
@@ -198,6 +198,28 @@ verify_log_lines(const char *reference_path)
if (line_end)
snprintf(line_end, sizeof(line) - (line_end - line), " object>\n");
if (strncmp(line_data, "handle @ /", sizeof("handle @ /") - 1) == 0) {
char *start = line_data + sizeof("handle @ ") - 1;
// normalize path to logging/__init__.py
char *logging = strstr(start, "logging/");
if (logging != NULL) {
memmove(start, logging, strlen(logging) + 1);
}
// remove line number
char *colon = strchr(start, ':');
if (colon != NULL) {
size_t len = strspn(colon + 1, "0123456789");
if (len != 0)
memmove(colon, colon + len + 1, strlen(colon + len + 1) + 1);
}
} else if (strncmp(line_data, "LogHandler.emit was called ", 27) == 0) {
// LogHandler.emit argument details vary based on python version
line_data[26] = '\n';
line_data[27] = '\0';
}
VERIFY_TRUE(strlcat(stored_str, line_data, sizeof(stored_str)) < sizeof(stored_str)); // we have enough space in buffer
}

View File

@@ -111,27 +111,10 @@ char ** create_str_array(size_t count, ...);
#define VERIFY_STR(actual, expected) \
do { \
const char *actual_str = actual; \
regex_t regex; \
int result = 0; \
if (!actual_str) { \
result = -1; \
} else if (*expected == '\0') { \
result = strcmp(actual_str, expected); \
} else { \
if ((result = regcomp(&regex, expected, REG_NOSUB)) != 0) { \
char errbuf[1024]; \
regerror(result, &regex, errbuf, sizeof(errbuf)); \
fprintf(stderr, "regcomp failed at %s:%d: %s\npattern: %s\n", \
__FILE__, __LINE__, errbuf, expected); \
} else { \
result = regexec(&regex, actual_str, 0, NULL, 0); \
regfree(&regex); \
} \
} \
if (result != 0) { \
VERIFY_PRINT_MSG("%s", #actual, actual_str ? actual_str : "(null)", #expected, expected, "expected to be"); \
return false; \
} \
if (!actual_str || strcmp(actual_str, expected) != 0) { \
VERIFY_PRINT_MSG("%s", #actual, actual_str ? actual_str : "(null)", #expected, expected, "expected to be"); \
return false; \
} \
} while(false)
#define VERIFY_STR_CONTAINS(actual, expected) \