static fr_event_list_t *el = NULL;
+static char const *write_filename = NULL;
+static FILE *write_fp = NULL;
+
size_t process_line(command_result_t *result, command_file_ctx_t *cc, char *data, size_t data_used, char *in, size_t inlen);
static int process_file(bool *exit_now, TALLOC_CTX *ctx,
command_config_t const *config, const char *root_dir, char const *filename, fr_dlist_head_t *lines);
bool exit_now = false;
int ret;
+ if (write_fp) {
+ fprintf(stderr, "Can't do $INCLUDE with -w %s\n", write_filename);
+ RETURN_EXIT(1);
+ }
+
q = strrchr(cc->path, '/');
if (q) {
*q = '\0';
char *p, *name;
char *parent = NULL;
fr_cmd_table_t *table;
+ char buffer[8192];
table = talloc_zero(cc->tmp_ctx, fr_cmd_table_t);
- p = strchr(in, ':');
+ strcpy(buffer, in);
+
+ p = strchr(buffer, ':');
if (!p) {
fr_strerror_const("no ':name' specified");
RETURN_PARSE_ERROR(0);
ssize_t ret;
char *p, *next;
uint8_t *enc_p;
+ char buffer[8192];
- p = in;
+ strcpy(buffer, in);
+
+ p = buffer;
next = strchr(p, ',');
if (next) *next = 0;
char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
{
size_t len;
+ char buffer[8192];
+
+ strcpy(buffer, in);
- len = encode_rfc(in, cc->buffer_start, cc->buffer_end - cc->buffer_start);
+ len = encode_rfc(buffer, cc->buffer_start, cc->buffer_end - cc->buffer_start);
if (len <= 0) RETURN_PARSE_ERROR(0);
if (len >= (size_t)(cc->buffer_end - cc->buffer_start)) {
char *data, size_t data_used, char *in, size_t inlen)
{
if (strcmp(in, data) != 0) {
+ if (write_fp) {
+ strcpy(in, data);
+ RETURN_OK(data_used);
+ }
+
mismatch_print(cc, "match", in, inlen, data, data_used, true);
RETURN_MISMATCH(data_used);
}
p = in;
fr_skip_whitespace(p);
- if (*p == '\0') RETURN_NOOP(data_used);
+
+ /*
+ * Skip empty lines and comments.
+ */
+ if (!*p || (*p == '#')) {
+ /*
+ * Dump the input to the output.
+ */
+ if (write_fp) {
+ fputs(in, write_fp);
+ fputs("\n", write_fp);
+ }
+
+ RETURN_NOOP(data_used);
+ }
DEBUG2("%s[%d]: %s", cc->filename, cc->lineno, p);
RETURN_COMMAND_ERROR();
}
- /*
- * Skip processing the command
- */
- if (command->func == command_comment) RETURN_NOOP(data_used);
-
p += match_len; /* Jump to after the command */
fr_skip_whitespace(p); /* Skip any whitespace */
fr_table_str_by_value(command_rcode_table, result->rcode, "<INVALID>"));
}
+ /*
+ * Dump the input to the output.
+ */
+ if (write_fp) {
+ fputs(in, write_fp);
+ fputs("\n", write_fp);
+ };
+
talloc_free_children(cc->tmp_ctx);
return data_used;
INFO(" -M Show talloc memory report.");
INFO(" -p Allow xlat_purify");
INFO(" -r <receipt_file> Create the <receipt_file> as a 'success' exit.");
+ INFO(" -w <output_file> Write 'corrected' output to <output_file>.");
INFO("Where <filename> is a file containing one or more commands and '-' indicates commands should be read from stdin.");
INFO("Ranges of <lines> may be specified in the format <start>[-[<end>]][,]");
}
default_log.fd = STDOUT_FILENO;
default_log.print_level = false;
- while ((c = getopt(argc, argv, "cd:D:F:fxMhpr:")) != -1) switch (c) {
+ while ((c = getopt(argc, argv, "cd:D:F:fxMhpr:w:")) != -1) switch (c) {
case 'c':
do_commands = true;
break;
allow_purify = true;
break;
+ case 'w':
+ write_filename = optarg;
+ break;
+
case 'h':
default:
do_usage = true; /* Just set a flag, so we can process extra -x args */
* Read tests from stdin
*/
if (argc < 2) {
+ if (write_filename) {
+ ERROR("Can't use '-w' with stdin");
+ EXIT_WITH_FAILURE;
+ }
+
ret = process_file(&exit_now, autofree, &config, name, "-", NULL);
/*
} else {
int i;
+ if (write_filename) {
+ if (argc != 2) { /* program name and file to write */
+ ERROR("Can't use '-w' with multiple filenames");
+ EXIT_WITH_FAILURE;
+ }
+
+ write_fp = fopen(write_filename, "w");
+ if (!write_fp) {
+ ERROR("Failed opening %s: %s", write_filename, strerror(errno));
+ EXIT_WITH_FAILURE;
+ }
+ }
+
+ /*
+ * Loop over all input files.
+ */
for (i = 1; i < argc; i++) {
char *dir = NULL, *file;
fr_sbuff_t in = FR_SBUFF_IN(argv[i], strlen(argv[i]));
if ((ret != 0) || exit_now) break;
}
+
+ if (write_fp) {
+ fclose(write_fp);
+ if (rename(write_filename, argv[1]) < 0) {
+ ERROR("Failed renaming %s: %s", write_filename, strerror(errno));
+ EXIT_WITH_FAILURE;
+ }
+ }
}
/*
#
$(BUILD_DIR)/tests/unit/xlat/purify.txt $(filter $(BUILD_DIR)/tests/unit/xlat/cond_%,$(FILES.$(TEST))): PURIFY=-p
+#
+# For automatically fixing the tests when only the output has changed
+#
+# The unit_test_attribute program will copy the inputs to the outputs, and rewrite the "expected" output
+# with the "actual" output. But only for the "match" command. Everything is including comments and blank
+# lines is copied verbatim.
+#
+
+#REWRITE_FLAGS = -w $(BUILD_DIR)/tmp
+
#
# And the actual script to run each test.
#
$(OUTPUT)/%: $(DIR)/% $(TEST_BIN_DIR)/unit_test_attribute $(top_srcdir)/src/tests/unit/dictionary
$(eval DIR:=${top_srcdir}/src/tests/unit)
@echo "UNIT-TEST $(lastword $(subst /, ,$(dir $@))) $(basename $(notdir $@))"
- ${Q}if ! $(TEST_BIN)/unit_test_attribute $(PURIFY) -F ./src/tests/fuzzer-corpus -D ./share/dictionary -d $(DIR) -r "$@" $<; then \
+ ${Q}if ! $(TEST_BIN)/unit_test_attribute $(PURIFY) $(REWRITE_FLAGS) -F ./src/tests/fuzzer-corpus -D ./share/dictionary -d $(DIR) -r "$@" $<; then \
echo "TZ=GMT $(TEST_BIN)/unit_test_attribute $(PURIFY) -F ./src/tests/fuzzer-corpus -D ./share/dictionary -d $(DIR) -r \"$@\" $<"; \
rm -f $(BUILD_DIR)/tests/test.unit; \
exit 1; \