forked from vieter-v/libvieter
				
			test: started porting cron tests
							parent
							
								
									c018d8d86c
								
							
						
					
					
						commit
						30e086ad6b
					
				| 
						 | 
				
			
			@ -1,2 +1,3 @@
 | 
			
		|||
build/
 | 
			
		||||
compile_commands.json
 | 
			
		||||
.cache/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										4
									
								
								Makefile
								
								
								
								
							| 
						 | 
				
			
			@ -60,11 +60,11 @@ $(BUILD_DIR)/$(TEST_DIR)/%.c.o: $(TEST_DIR)/%.c
 | 
			
		|||
# =====MAINTENANCE=====
 | 
			
		||||
.PHONY: lint
 | 
			
		||||
lint:
 | 
			
		||||
	clang-format -n --Werror $(SRCS) $(SRCS_H) $(SRCS_TEST)
 | 
			
		||||
	clang-format -n --Werror $(SRCS) $(SRCS_H)
 | 
			
		||||
 | 
			
		||||
.PHONY: fmt
 | 
			
		||||
fmt:
 | 
			
		||||
	clang-format -i $(SRCS) $(SRCS_H) $(SRCS_TEST)
 | 
			
		||||
	clang-format -i $(SRCS) $(SRCS_H)
 | 
			
		||||
 | 
			
		||||
.PHONY: clean
 | 
			
		||||
clean:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,16 +7,16 @@
 | 
			
		|||
#include <string.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
typedef enum cron_parse_error {
 | 
			
		||||
  cron_parse_ok = 0,
 | 
			
		||||
  cron_parse_invalid_expression = 1,
 | 
			
		||||
  cron_parse_invalid_number = 2,
 | 
			
		||||
  cron_parse_out_of_range = 3,
 | 
			
		||||
  cron_parse_too_many_parts = 4,
 | 
			
		||||
  cron_parse_not_enough_parts = 5
 | 
			
		||||
} cron_parse_error;
 | 
			
		||||
typedef enum vieter_cron_parse_error {
 | 
			
		||||
  vieter_cron_parse_ok = 0,
 | 
			
		||||
  vieter_cron_parse_invalid_expression = 1,
 | 
			
		||||
  vieter_cron_parse_invalid_number = 2,
 | 
			
		||||
  vieter_cron_parse_out_of_range = 3,
 | 
			
		||||
  vieter_cron_parse_too_many_parts = 4,
 | 
			
		||||
  vieter_cron_parse_not_enough_parts = 5
 | 
			
		||||
} vieter_cron_parse_error;
 | 
			
		||||
 | 
			
		||||
typedef struct cron_expression {
 | 
			
		||||
typedef struct vieter_cron_expression {
 | 
			
		||||
  uint8_t *minutes;
 | 
			
		||||
  uint8_t *hours;
 | 
			
		||||
  uint8_t *days;
 | 
			
		||||
| 
						 | 
				
			
			@ -25,26 +25,29 @@ typedef struct cron_expression {
 | 
			
		|||
  uint8_t hour_count;
 | 
			
		||||
  uint8_t day_count;
 | 
			
		||||
  uint8_t month_count;
 | 
			
		||||
} cron_expression;
 | 
			
		||||
} vieter_cron_expression;
 | 
			
		||||
 | 
			
		||||
typedef struct cron_simple_time {
 | 
			
		||||
typedef struct vieter_cron_simple_time {
 | 
			
		||||
  int year;
 | 
			
		||||
  int month;
 | 
			
		||||
  int day;
 | 
			
		||||
  int hour;
 | 
			
		||||
  int minute;
 | 
			
		||||
} cron_simple_time;
 | 
			
		||||
} vieter_cron_simple_time;
 | 
			
		||||
 | 
			
		||||
cron_expression *ce_init();
 | 
			
		||||
vieter_cron_expression *ce_init();
 | 
			
		||||
 | 
			
		||||
void cron_ce_free(cron_expression *ce);
 | 
			
		||||
void vieter_cron_ce_free(vieter_cron_expression *ce);
 | 
			
		||||
 | 
			
		||||
void cron_ce_next(cron_simple_time *out, cron_expression *ce,
 | 
			
		||||
                  cron_simple_time *ref);
 | 
			
		||||
void vieter_cron_ce_next(vieter_cron_simple_time *out,
 | 
			
		||||
                         vieter_cron_expression *ce,
 | 
			
		||||
                         vieter_cron_simple_time *ref);
 | 
			
		||||
 | 
			
		||||
void cron_ce_next_from_now(cron_simple_time *out, cron_expression *ce);
 | 
			
		||||
void vieter_cron_ce_next_from_now(vieter_cron_simple_time *out,
 | 
			
		||||
                                  vieter_cron_expression *ce);
 | 
			
		||||
 | 
			
		||||
enum cron_parse_error cron_ce_parse_expression(cron_expression *out,
 | 
			
		||||
                                               const char *expression);
 | 
			
		||||
enum vieter_cron_parse_error
 | 
			
		||||
vieter_cron_parse_expression(vieter_cron_expression *out,
 | 
			
		||||
                             const char *expression);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,9 +3,11 @@
 | 
			
		|||
 | 
			
		||||
const uint8_t month_days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 | 
			
		||||
 | 
			
		||||
cron_expression *ce_init() { return malloc(sizeof(cron_expression)); }
 | 
			
		||||
vieter_cron_expression *vieter_cron_expression_init() {
 | 
			
		||||
  return malloc(sizeof(vieter_cron_expression));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ce_free(cron_expression *ce) {
 | 
			
		||||
void ce_free(vieter_cron_expression *ce) {
 | 
			
		||||
  free(ce->months);
 | 
			
		||||
  free(ce->days);
 | 
			
		||||
  free(ce->hours);
 | 
			
		||||
| 
						 | 
				
			
			@ -13,8 +15,8 @@ void ce_free(cron_expression *ce) {
 | 
			
		|||
  free(ce);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ce_next(cron_simple_time *out, cron_expression *ce,
 | 
			
		||||
             cron_simple_time *ref) {
 | 
			
		||||
void vieter_cron_next(vieter_cron_simple_time *out, vieter_cron_expression *ce,
 | 
			
		||||
                      vieter_cron_simple_time *ref) {
 | 
			
		||||
  // For all of these values, the rule is the following: if their value is
 | 
			
		||||
  // the length of their respective array in the CronExpression object, that
 | 
			
		||||
  // means we've looped back around. This means that the "bigger" value has
 | 
			
		||||
| 
						 | 
				
			
			@ -98,18 +100,19 @@ void ce_next(cron_simple_time *out, cron_expression *ce,
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ce_next_from_now(cron_simple_time *out, cron_expression *ce) {
 | 
			
		||||
void vieter_cron_next_from_now(vieter_cron_simple_time *out,
 | 
			
		||||
                               vieter_cron_expression *ce) {
 | 
			
		||||
  time_t t = time(NULL);
 | 
			
		||||
  struct tm gm;
 | 
			
		||||
  gmtime_r(&t, &gm);
 | 
			
		||||
 | 
			
		||||
  cron_simple_time ref = {// tm_year contains years since 1900
 | 
			
		||||
                          .year = 1900 + gm.tm_year,
 | 
			
		||||
                          // tm_mon goes from 0 to 11
 | 
			
		||||
                          .month = gm.tm_mon + 1,
 | 
			
		||||
                          .day = gm.tm_mday,
 | 
			
		||||
                          .hour = gm.tm_hour,
 | 
			
		||||
                          .minute = gm.tm_min};
 | 
			
		||||
  vieter_cron_simple_time ref = {// tm_year contains years since 1900
 | 
			
		||||
                                 .year = 1900 + gm.tm_year,
 | 
			
		||||
                                 // tm_mon goes from 0 to 11
 | 
			
		||||
                                 .month = gm.tm_mon + 1,
 | 
			
		||||
                                 .day = gm.tm_mday,
 | 
			
		||||
                                 .hour = gm.tm_hour,
 | 
			
		||||
                                 .minute = gm.tm_min};
 | 
			
		||||
 | 
			
		||||
  ce_next(out, ce, &ref);
 | 
			
		||||
  vieter_cron_next(out, ce, &ref);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,10 +16,10 @@ const uint8_t max_parts = 4;
 | 
			
		|||
#define SAFE_ATOI(v, s, min, max)                                              \
 | 
			
		||||
  int _##v = atoi(s);                                                          \
 | 
			
		||||
  if ((_##v) == 0 && strcmp((s), "0") != 0) {                                  \
 | 
			
		||||
    return cron_parse_invalid_number;                                          \
 | 
			
		||||
    return vieter_cron_parse_invalid_number;                                   \
 | 
			
		||||
  }                                                                            \
 | 
			
		||||
  if (((_##v) < (min)) || ((_##v) > (max))) {                                  \
 | 
			
		||||
    return cron_parse_out_of_range;                                            \
 | 
			
		||||
    return vieter_cron_parse_out_of_range;                                     \
 | 
			
		||||
  }                                                                            \
 | 
			
		||||
  v = (uint8_t)(_##v);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -41,8 +41,9 @@ const uint8_t max_parts = 4;
 | 
			
		|||
 * - a/c
 | 
			
		||||
 * - a-b/c
 | 
			
		||||
 */
 | 
			
		||||
cron_parse_error ce_parse_range(uint64_t *out, char *s, uint8_t min,
 | 
			
		||||
                                uint8_t max) {
 | 
			
		||||
vieter_cron_parse_error vieter_cron_expression_parse_range(uint64_t *out,
 | 
			
		||||
                                                           char *s, uint8_t min,
 | 
			
		||||
                                                           uint8_t max) {
 | 
			
		||||
  size_t slash_index = 0, dash_index = 0;
 | 
			
		||||
  size_t s_index = 0;
 | 
			
		||||
  char cur_char;
 | 
			
		||||
| 
						 | 
				
			
			@ -54,12 +55,12 @@ cron_parse_error ce_parse_range(uint64_t *out, char *s, uint8_t min,
 | 
			
		|||
                         (cur_char >= '0' && cur_char <= '9');
 | 
			
		||||
 | 
			
		||||
    if (!is_valid_character) {
 | 
			
		||||
      return cron_parse_invalid_expression;
 | 
			
		||||
      return vieter_cron_parse_invalid_expression;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (cur_char == '/') {
 | 
			
		||||
      if (s_index == 0 || slash_index != 0) {
 | 
			
		||||
        return cron_parse_invalid_expression;
 | 
			
		||||
        return vieter_cron_parse_invalid_expression;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      slash_index = s_index;
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +69,7 @@ cron_parse_error ce_parse_range(uint64_t *out, char *s, uint8_t min,
 | 
			
		|||
    } else if (cur_char == '-') {
 | 
			
		||||
      // At most one dash is allowed, and it must be before the slash
 | 
			
		||||
      if (s_index == 0 || dash_index != 0 || slash_index != 0) {
 | 
			
		||||
        return cron_parse_invalid_expression;
 | 
			
		||||
        return vieter_cron_parse_invalid_expression;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      dash_index = s_index;
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +86,7 @@ cron_parse_error ce_parse_range(uint64_t *out, char *s, uint8_t min,
 | 
			
		|||
 | 
			
		||||
  if (s[0] == '*') {
 | 
			
		||||
    if (s[1] != '\0' || dash_index != 0) {
 | 
			
		||||
      return cron_parse_invalid_expression;
 | 
			
		||||
      return vieter_cron_parse_invalid_expression;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    start = min;
 | 
			
		||||
| 
						 | 
				
			
			@ -112,7 +113,7 @@ cron_parse_error ce_parse_range(uint64_t *out, char *s, uint8_t min,
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return cron_parse_ok;
 | 
			
		||||
  return vieter_cron_parse_ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -120,19 +121,19 @@ cron_parse_error ce_parse_range(uint64_t *out, char *s, uint8_t min,
 | 
			
		|||
 * min-max range the part represents. A part consists of one or more range
 | 
			
		||||
 * expressions, separated by commas.
 | 
			
		||||
 */
 | 
			
		||||
cron_parse_error ce_parse_part(uint64_t *out, char *s, uint8_t min,
 | 
			
		||||
                               uint8_t max) {
 | 
			
		||||
vieter_cron_parse_error ce_parse_part(uint64_t *out, char *s, uint8_t min,
 | 
			
		||||
                                      uint8_t max) {
 | 
			
		||||
  *out = 0;
 | 
			
		||||
 | 
			
		||||
  char *next;
 | 
			
		||||
  cron_parse_error res;
 | 
			
		||||
  vieter_cron_parse_error res;
 | 
			
		||||
 | 
			
		||||
  while ((next = strchr(s, ',')) != NULL) {
 | 
			
		||||
    next[0] = '\0';
 | 
			
		||||
 | 
			
		||||
    res = ce_parse_range(out, s, min, max);
 | 
			
		||||
    res = vieter_cron_expression_parse_range(out, s, min, max);
 | 
			
		||||
 | 
			
		||||
    if (res != cron_parse_ok) {
 | 
			
		||||
    if (res != vieter_cron_parse_ok) {
 | 
			
		||||
      return res;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -140,7 +141,7 @@ cron_parse_error ce_parse_part(uint64_t *out, char *s, uint8_t min,
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  // Make sure to parse the final range as well
 | 
			
		||||
  return ce_parse_range(out, s, min, max);
 | 
			
		||||
  return vieter_cron_expression_parse_range(out, s, min, max);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -196,13 +197,14 @@ uint8_t bf_to_nums(uint8_t **out, uint64_t bf, uint8_t min, uint8_t max) {
 | 
			
		|||
/*
 | 
			
		||||
 * Parse a cron expression string into a cron_expression struct.
 | 
			
		||||
 */
 | 
			
		||||
cron_parse_error ce_parse_expression(cron_expression *out,
 | 
			
		||||
                                     const char *expression) {
 | 
			
		||||
vieter_cron_parse_error
 | 
			
		||||
vieter_cron_parse_expression(vieter_cron_expression *out,
 | 
			
		||||
                             const char *expression) {
 | 
			
		||||
  // The parsing functions modify the input string in-place
 | 
			
		||||
  char *s = strdup(expression);
 | 
			
		||||
  char *orig_s = s;
 | 
			
		||||
 | 
			
		||||
  cron_parse_error res = cron_parse_ok;
 | 
			
		||||
  vieter_cron_parse_error res = vieter_cron_parse_ok;
 | 
			
		||||
 | 
			
		||||
  // First we divide the input string into its parts, divided by spaces.
 | 
			
		||||
  // Each part is delimited by a NULL byte.
 | 
			
		||||
| 
						 | 
				
			
			@ -237,7 +239,7 @@ cron_parse_error ce_parse_expression(cron_expression *out,
 | 
			
		|||
  // s[0] isn't '\0', there's still another part before the end of the string.
 | 
			
		||||
  if (s[0] != '\0') {
 | 
			
		||||
    if (part_count == max_parts) {
 | 
			
		||||
      res = cron_parse_too_many_parts;
 | 
			
		||||
      res = vieter_cron_parse_too_many_parts;
 | 
			
		||||
      goto end;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -246,7 +248,7 @@ cron_parse_error ce_parse_expression(cron_expression *out,
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  if (part_count < min_parts) {
 | 
			
		||||
    res = cron_parse_not_enough_parts;
 | 
			
		||||
    res = vieter_cron_parse_not_enough_parts;
 | 
			
		||||
    goto end;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -259,7 +261,7 @@ cron_parse_error ce_parse_expression(cron_expression *out,
 | 
			
		|||
  if (part_count >= 4) {
 | 
			
		||||
    res = ce_parse_part(&bit_field, parts[3], min[3], max[3]);
 | 
			
		||||
 | 
			
		||||
    if (res != cron_parse_ok) {
 | 
			
		||||
    if (res != vieter_cron_parse_ok) {
 | 
			
		||||
      goto end;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -283,7 +285,7 @@ cron_parse_error ce_parse_expression(cron_expression *out,
 | 
			
		|||
 | 
			
		||||
    res = ce_parse_part(&bit_field, parts[2], min[2], max_day_value);
 | 
			
		||||
 | 
			
		||||
    if (res != cron_parse_ok) {
 | 
			
		||||
    if (res != vieter_cron_parse_ok) {
 | 
			
		||||
      free(out->months);
 | 
			
		||||
 | 
			
		||||
      goto end;
 | 
			
		||||
| 
						 | 
				
			
			@ -301,7 +303,7 @@ cron_parse_error ce_parse_expression(cron_expression *out,
 | 
			
		|||
 | 
			
		||||
  res = ce_parse_part(&bit_field, parts[1], min[1], max[1]);
 | 
			
		||||
 | 
			
		||||
  if (res != cron_parse_ok) {
 | 
			
		||||
  if (res != vieter_cron_parse_ok) {
 | 
			
		||||
    free(out->months);
 | 
			
		||||
    free(out->days);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -315,7 +317,7 @@ cron_parse_error ce_parse_expression(cron_expression *out,
 | 
			
		|||
 | 
			
		||||
  res = ce_parse_part(&bit_field, parts[0], min[0], max[0]);
 | 
			
		||||
 | 
			
		||||
  if (res != cron_parse_ok) {
 | 
			
		||||
  if (res != vieter_cron_parse_ok) {
 | 
			
		||||
    free(out->months);
 | 
			
		||||
    free(out->days);
 | 
			
		||||
    free(out->hours);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,69 +1,38 @@
 | 
			
		|||
#include "acutest.h"
 | 
			
		||||
#include "vieter_cron.h"
 | 
			
		||||
 | 
			
		||||
void test_tutorial(void) {
 | 
			
		||||
  void *mem;
 | 
			
		||||
void test_not_allowed() {
 | 
			
		||||
    char *expressions[] = {
 | 
			
		||||
        "4 *-7",
 | 
			
		||||
        "4 *-7/4",
 | 
			
		||||
        "4 7/*",
 | 
			
		||||
        "0 0 30 2",
 | 
			
		||||
        "0 /5",
 | 
			
		||||
        "0  ",
 | 
			
		||||
        "0",
 | 
			
		||||
        "      0",
 | 
			
		||||
        "       0      ",
 | 
			
		||||
        "1 2 3 4~9",
 | 
			
		||||
        "1 1-3-5",
 | 
			
		||||
        "0 5/2-5",
 | 
			
		||||
        "",
 | 
			
		||||
        "1 1/2/3",
 | 
			
		||||
        "*5 8",
 | 
			
		||||
        "x 8",
 | 
			
		||||
        NULL
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
  mem = malloc(10);
 | 
			
		||||
  TEST_CHECK(mem != NULL);
 | 
			
		||||
    int i = 0;
 | 
			
		||||
 | 
			
		||||
  mem = realloc(mem, 20);
 | 
			
		||||
  TEST_CHECK(mem != NULL);
 | 
			
		||||
    while (expressions[i] != NULL) {
 | 
			
		||||
        vieter_cron_expression out;
 | 
			
		||||
        TEST_CHECK_(vieter_cron_parse_expression(&out, expressions[i]) != vieter_cron_parse_ok, "%s should error", expressions[i]);
 | 
			
		||||
 | 
			
		||||
  free(mem);
 | 
			
		||||
        i++;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_fail(void) {
 | 
			
		||||
  int a, b;
 | 
			
		||||
 | 
			
		||||
  /* This condition is designed to fail so you can see what the failed test
 | 
			
		||||
   * output looks like. */
 | 
			
		||||
  a = 1;
 | 
			
		||||
  b = 2;
 | 
			
		||||
  TEST_CHECK(a + b == 5);
 | 
			
		||||
 | 
			
		||||
  /* Here is TEST_CHECK_ in action. */
 | 
			
		||||
  TEST_CHECK_(a + b == 5, "%d + %d == 5", a, b);
 | 
			
		||||
 | 
			
		||||
  /* We may also show more information about the failure. */
 | 
			
		||||
  if (!TEST_CHECK(a + b == 5)) {
 | 
			
		||||
    TEST_MSG("a: %d", a);
 | 
			
		||||
    TEST_MSG("b: %d", b);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* The macro TEST_MSG() only outputs something when the preceding
 | 
			
		||||
   * condition fails, so we can avoid the 'if' statement. */
 | 
			
		||||
  TEST_CHECK(a + b == 3);
 | 
			
		||||
  TEST_MSG("a: %d", a);
 | 
			
		||||
  TEST_MSG("b: %d", b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void helper(void) {
 | 
			
		||||
  /* Kill the current test with a condition which is never true. */
 | 
			
		||||
  TEST_ASSERT(1 == 2);
 | 
			
		||||
 | 
			
		||||
  /* This never happens because the test is aborted above. */
 | 
			
		||||
  TEST_CHECK(1 + 2 == 2 + 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_abort(void) {
 | 
			
		||||
  helper();
 | 
			
		||||
 | 
			
		||||
  /* This test never happens because the test is aborted inside the helper()
 | 
			
		||||
   * function. */
 | 
			
		||||
  TEST_CHECK(1 * 2 == 2 * 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_crash(void) {
 | 
			
		||||
  int *invalid = ((int *)NULL) + 0xdeadbeef;
 | 
			
		||||
 | 
			
		||||
  *invalid = 42;
 | 
			
		||||
  TEST_CHECK_(1 == 1, "This should never execute, due to a write into "
 | 
			
		||||
                      "an invalid address.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_LIST = {{"tutorial", test_tutorial},
 | 
			
		||||
             {"fail", test_fail},
 | 
			
		||||
             {"abort", test_abort},
 | 
			
		||||
             {"crash", test_crash},
 | 
			
		||||
             {NULL, NULL}};
 | 
			
		||||
TEST_LIST = {
 | 
			
		||||
    {"not_allowed", test_not_allowed},
 | 
			
		||||
    {NULL, NULL}
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue