|
@@ -40,6 +40,36 @@ typedef enum config_type_t {
|
|
|
CONFIG_TYPE_OBSOLETE, /**< Obsolete (ignored) option. */
|
|
|
} config_type_t;
|
|
|
|
|
|
+#ifdef TOR_UNIT_TESTS
|
|
|
+/**
|
|
|
+ * Union used when building in test mode typechecking the members of a type
|
|
|
+ * used with confparse.c. See CONF_CHECK_VAR_TYPE for a description of how
|
|
|
+ * it is used. */
|
|
|
+typedef union {
|
|
|
+ char **STRING;
|
|
|
+ char **FILENAME;
|
|
|
+ int *UINT; /* yes, really: Even though the confparse type is called
|
|
|
+ * "UINT", it still uses the C int type -- it just enforces that
|
|
|
+ * the values are in range [0,INT_MAX].
|
|
|
+ */
|
|
|
+ int *INT;
|
|
|
+ int *PORT;
|
|
|
+ int *INTERVAL;
|
|
|
+ int *MSEC_INTERVAL;
|
|
|
+ uint64_t *MEMUNIT;
|
|
|
+ double *DOUBLE;
|
|
|
+ int *BOOL;
|
|
|
+ int *AUTOBOOL;
|
|
|
+ time_t *ISOTIME;
|
|
|
+ smartlist_t **CSV;
|
|
|
+ smartlist_t **CSV_INTERVAL;
|
|
|
+ config_line_t **LINELIST;
|
|
|
+ config_line_t **LINELIST_S;
|
|
|
+ config_line_t **LINELIST_V;
|
|
|
+ routerset_t **ROUTERSET;
|
|
|
+} confparse_dummy_values_t;
|
|
|
+#endif
|
|
|
+
|
|
|
/** An abbreviation for a configuration option allowed on the command line. */
|
|
|
typedef struct config_abbrev_t {
|
|
|
const char *abbreviated;
|
|
@@ -64,8 +94,50 @@ typedef struct config_var_t {
|
|
|
* value. */
|
|
|
off_t var_offset; /**< Offset of the corresponding member of or_options_t. */
|
|
|
const char *initvalue; /**< String (or null) describing initial value. */
|
|
|
+
|
|
|
+#ifdef TOR_UNIT_TESTS
|
|
|
+ /** Used for compiler-magic to typecheck the corresponding field in the
|
|
|
+ * corresponding struct. Only used in unit test mode, at compile-time. */
|
|
|
+ confparse_dummy_values_t var_ptr_dummy;
|
|
|
+#endif
|
|
|
} config_var_t;
|
|
|
|
|
|
+/* Macros to define extra members inside config_var_t fields, and at the
|
|
|
+ * end of a list of them.
|
|
|
+ */
|
|
|
+#ifdef TOR_UNIT_TESTS
|
|
|
+/* This is a somewhat magic type-checking macro for users of confparse.c.
|
|
|
+ * It initializes a union member "confparse_dummy_values_t.conftype" with
|
|
|
+ * the address of a static member "tp_dummy.member". This
|
|
|
+ * will give a compiler warning unless the member field is of the correct
|
|
|
+ * type.
|
|
|
+ *
|
|
|
+ * (This warning is mandatory, because a type mismatch here violates the type
|
|
|
+ * compatibility constraint for simple assignment, and requires a diagnostic,
|
|
|
+ * according to the C spec.)
|
|
|
+ *
|
|
|
+ * For example, suppose you say:
|
|
|
+ * "CONF_CHECK_VAR_TYPE(or_options_t, STRING, Address)".
|
|
|
+ * Then this macro will evaluate to:
|
|
|
+ * { .STRING = &or_options_t_dummy.Address }
|
|
|
+ * And since confparse_dummy_values_t.STRING has type "char **", that
|
|
|
+ * expression will create a warning unless or_options_t.Address also
|
|
|
+ * has type "char *".
|
|
|
+ */
|
|
|
+#define CONF_CHECK_VAR_TYPE(tp, conftype, member) \
|
|
|
+ { . conftype = &tp ## _dummy . member }
|
|
|
+#define CONF_TEST_MEMBERS(tp, conftype, member) \
|
|
|
+ , CONF_CHECK_VAR_TYPE(tp, conftype, member)
|
|
|
+#define END_OF_CONFIG_VARS \
|
|
|
+ { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL, { .INT=NULL } }
|
|
|
+#define DUMMY_TYPECHECK_INSTANCE(tp) \
|
|
|
+ static tp tp ## _dummy
|
|
|
+#else
|
|
|
+#define CONF_TEST_MEMBERS(tp, conftype, member)
|
|
|
+#define END_OF_CONFIG_VARS { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
|
|
|
+#define DUMMY_TYPECHECK_INSTANCE(tp)
|
|
|
+#endif
|
|
|
+
|
|
|
/** Type of a callback to validate whether a given configuration is
|
|
|
* well-formed and consistent. See options_trial_assign() for documentation
|
|
|
* of arguments. */
|