stress.c 6.1 KB
Newer Older
1
#include "clar_libgit2.h"
2 3

#include "filebuf.h"
4
#include "futils.h"
5 6
#include "posix.h"

7 8
#define TEST_CONFIG "git-test-config"

9 10
static git_buf buf = GIT_BUF_INIT;

11 12
void test_config_stress__initialize(void)
{
13
	git_filebuf file = GIT_FILEBUF_INIT;
14

15
	cl_git_pass(git_filebuf_open(&file, TEST_CONFIG, 0, 0666));
16 17 18 19

	git_filebuf_printf(&file, "[color]\n\tui = auto\n");
	git_filebuf_printf(&file, "[core]\n\teditor = \n");

20
	cl_git_pass(git_filebuf_commit(&file));
21 22 23 24
}

void test_config_stress__cleanup(void)
{
25
	git_buf_dispose(&buf);
26
	p_unlink(TEST_CONFIG);
27 28 29 30 31 32
}

void test_config_stress__dont_break_on_invalid_input(void)
{
	git_config *config;

33 34
	cl_assert(git_path_exists(TEST_CONFIG));
	cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG));
35

36 37
	cl_git_pass(git_config_get_string_buf(&buf, config, "color.ui"));
	cl_git_pass(git_config_get_string_buf(&buf, config, "core.editor"));
38 39 40

	git_config_free(config);
}
41

42 43 44 45 46 47 48
void assert_config_value(git_config *config, const char *key, const char *value)
{
	git_buf_clear(&buf);
	cl_git_pass(git_config_get_string_buf(&buf, config, key));
	cl_assert_equal_s(value, git_buf_cstr(&buf));
}

49 50 51 52
void test_config_stress__comments(void)
{
	git_config *config;

53
	cl_git_pass(git_config_open_ondisk(&config, cl_fixture("config/config12")));
54

55 56 57 58 59 60 61
	assert_config_value(config, "some.section.test2", "hello");
	assert_config_value(config, "some.section.test3", "welcome");
	assert_config_value(config, "some.section.other", "hello! \" ; ; ; ");
	assert_config_value(config, "some.section.other2", "cool! \" # # # ");
	assert_config_value(config, "some.section.multi", "hi, this is a ; multiline comment # with ;\n special chars and other stuff !@#");
	assert_config_value(config, "some.section.multi2", "good, this is a ; multiline comment # with ;\n special chars and other stuff !@#");
	assert_config_value(config, "some.section.back", "this is \ba phrase");
62 63 64 65 66
	assert_config_value(config, "some.section.dollar", "some $sign");
	assert_config_value(config, "some.section.multiquotes", "!ls  x                     ls  # comment2                     $HOME");
	assert_config_value(config, "some.section.multiquotes2", "!ls  x                      ls  \"# comment2                      $HOME\"");
	assert_config_value(config, "some.section.multiquotes3", "hi # ho there are # more quotes");
	assert_config_value(config, "some.section.quotecomment", "hi # ho there are # more");
67 68 69

	git_config_free(config);
}
70 71 72 73 74 75

void test_config_stress__escape_subsection_names(void)
{
	git_config *config;

	cl_assert(git_path_exists("git-test-config"));
76
	cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG));
77 78 79 80

	cl_git_pass(git_config_set_string(config, "some.sec\\tion.other", "foo"));
	git_config_free(config);

81
	cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG));
82

83 84
	assert_config_value(config, "some.sec\\tion.other", "foo");

85
	git_config_free(config);
86
}
87 88 89 90 91 92 93 94 95 96 97 98

void test_config_stress__trailing_backslash(void)
{
	git_config *config;
	const char *path =  "C:\\iam\\some\\windows\\path\\";

	cl_assert(git_path_exists("git-test-config"));
	cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG));
	cl_git_pass(git_config_set_string(config, "windows.path", path));
	git_config_free(config);

	cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG));
99 100
	assert_config_value(config, "windows.path", path);

101 102
	git_config_free(config);
}
103 104 105 106 107 108 109 110

void test_config_stress__complex(void)
{
	git_config *config;
	const char *path = "./config-immediate-multiline";

	cl_git_mkfile(path, "[imm]\n multi = \"\\\nfoo\"");
	cl_git_pass(git_config_open_ondisk(&config, path));
111 112
	assert_config_value(config, "imm.multi", "foo");

113 114
	git_config_free(config);
}
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130

void test_config_stress__quick_write(void)
{
	git_config *config_w, *config_r;
	const char *path = "./config-quick-write";
	const char *key = "quick.write";
	int32_t i;

	/* Create an external writer for one instance with the other one */
	cl_git_pass(git_config_open_ondisk(&config_w, path));
	cl_git_pass(git_config_open_ondisk(&config_r, path));

	/* Write and read in the same second (repeat to increase the chance of it happening) */
	for (i = 0; i < 10; i++) {
		int32_t val;
		cl_git_pass(git_config_set_int32(config_w, key, i));
131
		cl_msleep(1);
132 133 134
		cl_git_pass(git_config_get_int32(&val, config_r, key));
		cl_assert_equal_i(i, val);
	}
135 136 137

	git_config_free(config_r);
	git_config_free(config_w);
138
}
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183

static int foreach_cb(const git_config_entry *entry, void *payload)
{
	if (!strcmp(entry->name, "key.value")) {
		*(char **)payload = git__strdup(entry->value);
		return 0;
	}
	return -1;
}

void test_config_stress__foreach_refreshes(void)
{
	git_config *config_w, *config_r;
	char *value = NULL;

	cl_git_pass(git_config_open_ondisk(&config_w, "./cfg"));
	cl_git_pass(git_config_open_ondisk(&config_r, "./cfg"));

	cl_git_pass(git_config_set_string(config_w, "key.value", "1"));
	cl_git_pass(git_config_foreach_match(config_r, "key.value", foreach_cb, &value));

	cl_assert_equal_s(value, "1");

	git_config_free(config_r);
	git_config_free(config_w);
	git__free(value);
}

void test_config_stress__foreach_refreshes_snapshot(void)
{
	git_config *config, *snapshot;
	char *value = NULL;

	cl_git_pass(git_config_open_ondisk(&config, "./cfg"));

	cl_git_pass(git_config_set_string(config, "key.value", "1"));
	cl_git_pass(git_config_snapshot(&snapshot, config));
	cl_git_pass(git_config_foreach_match(snapshot, "key.value", foreach_cb, &value));

	cl_assert_equal_s(value, "1");

	git_config_free(snapshot);
	git_config_free(config);
	git__free(value);
}
184 185 186 187 188

void test_config_stress__huge_section_with_many_values(void)
{
	git_config *config;

189 190 191
	if (!cl_is_env_set("GITTEST_INVASIVE_SPEED"))
		cl_skip();

192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
	/*
	 * The config file is structured in such a way that is
	 * has a section header that is approximately 500kb of
	 * size followed by 40k entries. While the resulting
	 * configuration file itself is roughly 650kb in size and
	 * thus considered to be rather small, in the past we'd
	 * balloon to more than 20GB of memory (20000x500kb)
	 * while parsing the file. It thus was a trivial way to
	 * cause an out-of-memory situation and thus cause denial
	 * of service, e.g. via gitmodules.
	 */
	cl_git_pass(git_config_open_ondisk(&config, cl_fixture("config/config-oom")));

	git_config_free(config);
}