libgit2/tests-clay/attr/lookup.c
Russell Belfer 73b51450a3 Add support for macros and cache flush API.
Add support for git attribute macro definitions.  Also, add
support for cache flush API to clear the attribute file content
cache when needed.

Additionally, improved the handling of global and system files,
making common utility functions in fileops and converting config
and attr to both use the common functions.

Adds a bunch more tests and fixed some memory leaks.  Note that
adding macros required me to use refcounted attribute assignment
definitions, which complicated, but probably improved memory usage.
2011-12-29 00:01:10 -08:00

258 lines
8.5 KiB
C

#include "clay_libgit2.h"
#include "attr_file.h"
void test_attr_lookup__simple(void)
{
git_attr_file *file = NULL;
git_attr_path path;
const char *value = NULL;
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr0"), &file));
cl_assert_strequal(cl_fixture("attr/attr0"), file->path);
cl_assert(file->rules.length == 1);
cl_git_pass(git_attr_path__init(&path, "test"));
cl_assert_strequal("test", path.path);
cl_assert_strequal("test", path.basename);
cl_assert(!path.is_dir);
cl_git_pass(git_attr_file__lookup_one(file,&path,"binary",&value));
cl_assert(value == GIT_ATTR_TRUE);
cl_git_pass(git_attr_file__lookup_one(file,&path,"missing",&value));
cl_assert(!value);
git_attr_file__free(file);
}
typedef struct {
const char *path;
const char *attr;
const char *expected;
int use_strcmp;
int force_dir;
} test_case;
static void run_test_cases(git_attr_file *file, test_case *cases)
{
git_attr_path path;
const char *value = NULL;
test_case *c;
int error;
for (c = cases; c->path != NULL; c++) {
cl_git_pass(git_attr_path__init(&path, c->path));
if (c->force_dir)
path.is_dir = 1;
error = git_attr_file__lookup_one(file,&path,c->attr,&value);
if (error != GIT_SUCCESS)
fprintf(stderr, "failure with %s %s %s\n", c->path, c->attr, c->expected);
cl_git_pass(error);
if (c->use_strcmp)
cl_assert_strequal(c->expected, value);
else
cl_assert(c->expected == value);
}
}
void test_attr_lookup__match_variants(void)
{
git_attr_file *file = NULL;
git_attr_path path;
test_case cases[] = {
/* pat0 -> simple match */
{ "pat0", "attr0", GIT_ATTR_TRUE, 0, 0 },
{ "/testing/for/pat0", "attr0", GIT_ATTR_TRUE, 0, 0 },
{ "relative/to/pat0", "attr0", GIT_ATTR_TRUE, 0, 0 },
{ "this-contains-pat0-inside", "attr0", NULL, 0, 0 },
{ "this-aint-right", "attr0", NULL, 0, 0 },
{ "/this/pat0/dont/match", "attr0", NULL, 0, 0 },
/* negative match */
{ "pat0", "attr1", GIT_ATTR_TRUE, 0, 0 },
{ "pat1", "attr1", NULL, 0, 0 },
{ "/testing/for/pat1", "attr1", NULL, 0, 0 },
{ "/testing/for/pat0", "attr1", GIT_ATTR_TRUE, 0, 0 },
{ "/testing/for/pat1/inside", "attr1", GIT_ATTR_TRUE, 0, 0 },
{ "misc", "attr1", GIT_ATTR_TRUE, 0, 0 },
/* dir match */
{ "pat2", "attr2", NULL, 0, 0 },
{ "pat2", "attr2", GIT_ATTR_TRUE, 0, 1 },
{ "/testing/for/pat2", "attr2", NULL, 0, 0 },
{ "/testing/for/pat2", "attr2", GIT_ATTR_TRUE, 0, 1 },
{ "/not/pat2/yousee", "attr2", NULL, 0, 0 },
{ "/not/pat2/yousee", "attr2", NULL, 0, 1 },
/* path match */
{ "pat3file", "attr3", NULL, 0, 0 },
{ "/pat3dir/pat3file", "attr3", NULL, 0, 0 },
{ "pat3dir/pat3file", "attr3", GIT_ATTR_TRUE, 0, 0 },
/* pattern* match */
{ "pat4.txt", "attr4", GIT_ATTR_TRUE, 0, 0 },
{ "/fun/fun/fun/pat4.c", "attr4", GIT_ATTR_TRUE, 0, 0 },
{ "pat4.", "attr4", GIT_ATTR_TRUE, 0, 0 },
{ "pat4", "attr4", NULL, 0, 0 },
{ "/fun/fun/fun/pat4.dir", "attr4", GIT_ATTR_TRUE, 0, 1 },
/* *pattern match */
{ "foo.pat5", "attr5", GIT_ATTR_TRUE, 0, 0 },
{ "foo.pat5", "attr5", GIT_ATTR_TRUE, 0, 1 },
{ "/this/is/ok.pat5", "attr5", GIT_ATTR_TRUE, 0, 0 },
{ "/this/is/bad.pat5/yousee.txt", "attr5", NULL, 0, 0 },
{ "foo.pat5", "attr100", NULL, 0, 0 },
/* glob match with slashes */
{ "foo.pat6", "attr6", NULL, 0, 0 },
{ "pat6/pat6/foobar.pat6", "attr6", GIT_ATTR_TRUE, 0, 0 },
{ "pat6/pat6/.pat6", "attr6", GIT_ATTR_TRUE, 0, 0 },
{ "pat6/pat6/extra/foobar.pat6", "attr6", NULL, 0, 0 },
{ "/prefix/pat6/pat6/foobar.pat6", "attr6", NULL, 0, 0 },
{ "/pat6/pat6/foobar.pat6", "attr6", NULL, 0, 0 },
/* complex pattern */
{ "pat7a12z", "attr7", GIT_ATTR_TRUE, 0, 0 },
{ "pat7e__x", "attr7", GIT_ATTR_TRUE, 0, 0 },
{ "pat7b/1y", "attr7", NULL, 0, 0 }, /* ? does not match / */
{ "pat7e_x", "attr7", NULL, 0, 0 },
{ "pat7aaaa", "attr7", NULL, 0, 0 },
{ "pat7zzzz", "attr7", NULL, 0, 0 },
{ "/this/can/be/anything/pat7a12z", "attr7", GIT_ATTR_TRUE, 0, 0 },
{ "but/it/still/must/match/pat7aaaa", "attr7", NULL, 0, 0 },
{ "pat7aaay.fail", "attr7", NULL, 0, 0 },
/* pattern with spaces */
{ "pat8 with spaces", "attr8", GIT_ATTR_TRUE, 0, 0 },
{ "/gotta love/pat8 with spaces", "attr8", GIT_ATTR_TRUE, 0, 0 },
{ "failing pat8 with spaces", "attr8", NULL, 0, 0 },
{ "spaces", "attr8", NULL, 0, 0 },
/* pattern at eof */
{ "pat9", "attr9", GIT_ATTR_TRUE, 0, 0 },
{ "/eof/pat9", "attr9", GIT_ATTR_TRUE, 0, 0 },
{ "pat", "attr9", NULL, 0, 0 },
{ "at9", "attr9", NULL, 0, 0 },
{ "pat9.fail", "attr9", NULL, 0, 0 },
/* sentinel at end */
{ NULL, NULL, NULL, 0, 0 }
};
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr1"), &file));
cl_assert_strequal(cl_fixture("attr/attr1"), file->path);
cl_assert(file->rules.length == 10);
cl_git_pass(git_attr_path__init(&path, "/testing/for/pat0"));
cl_assert_strequal("pat0", path.basename);
run_test_cases(file, cases);
git_attr_file__free(file);
}
void test_attr_lookup__assign_variants(void)
{
git_attr_file *file = NULL;
test_case cases[] = {
/* pat0 -> simple assign */
{ "pat0", "simple", GIT_ATTR_TRUE, 0, 0 },
{ "/testing/pat0", "simple", GIT_ATTR_TRUE, 0, 0 },
{ "pat0", "fail", NULL, 0, 0 },
{ "/testing/pat0", "fail", NULL, 0, 0 },
/* negative assign */
{ "pat1", "neg", GIT_ATTR_FALSE, 0, 0 },
{ "/testing/pat1", "neg", GIT_ATTR_FALSE, 0, 0 },
{ "pat1", "fail", NULL, 0, 0 },
{ "/testing/pat1", "fail", NULL, 0, 0 },
/* forced undef */
{ "pat1", "notundef", GIT_ATTR_TRUE, 0, 0 },
{ "pat2", "notundef", NULL, 0, 0 },
{ "/lead/in/pat1", "notundef", GIT_ATTR_TRUE, 0, 0 },
{ "/lead/in/pat2", "notundef", NULL, 0, 0 },
/* assign value */
{ "pat3", "assigned", "test-value", 1, 0 },
{ "pat3", "notassigned", NULL, 0, 0 },
/* assign value */
{ "pat4", "rule-with-more-chars", "value-with-more-chars", 1, 0 },
{ "pat4", "notassigned-rule-with-more-chars", NULL, 0, 0 },
/* empty assignments */
{ "pat5", "empty", GIT_ATTR_TRUE, 0, 0 },
{ "pat6", "negempty", GIT_ATTR_FALSE, 0, 0 },
/* multiple assignment */
{ "pat7", "multiple", GIT_ATTR_TRUE, 0, 0 },
{ "pat7", "single", GIT_ATTR_FALSE, 0, 0 },
{ "pat7", "values", "1", 1, 0 },
{ "pat7", "also", "a-really-long-value/*", 1, 0 },
{ "pat7", "happy", "yes!", 1, 0 },
{ "pat8", "again", GIT_ATTR_TRUE, 0, 0 },
{ "pat8", "another", "12321", 1, 0 },
/* bad assignment */
{ "patbad0", "simple", NULL, 0, 0 },
{ "patbad0", "notundef", GIT_ATTR_TRUE, 0, 0 },
{ "patbad1", "simple", NULL, 0, 0 },
/* eof assignment */
{ "pat9", "at-eof", GIT_ATTR_FALSE, 0, 0 },
/* sentinel at end */
{ NULL, NULL, NULL, 0, 0 }
};
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr2"), &file));
cl_assert(file->rules.length == 11);
run_test_cases(file, cases);
git_attr_file__free(file);
}
void test_attr_lookup__check_attr_examples(void)
{
git_attr_file *file = NULL;
test_case cases[] = {
{ "foo.java", "diff", "java", 1, 0 },
{ "foo.java", "crlf", GIT_ATTR_FALSE, 0, 0 },
{ "foo.java", "myAttr", GIT_ATTR_TRUE, 0, 0 },
{ "foo.java", "other", NULL, 0, 0 },
{ "/prefix/dir/foo.java", "diff", "java", 1, 0 },
{ "/prefix/dir/foo.java", "crlf", GIT_ATTR_FALSE, 0, 0 },
{ "/prefix/dir/foo.java", "myAttr", GIT_ATTR_TRUE, 0, 0 },
{ "/prefix/dir/foo.java", "other", NULL, 0, 0 },
{ "NoMyAttr.java", "crlf", GIT_ATTR_FALSE, 0, 0 },
{ "NoMyAttr.java", "myAttr", NULL, 0, 0 },
{ "NoMyAttr.java", "other", NULL, 0, 0 },
{ "/prefix/dir/NoMyAttr.java", "crlf", GIT_ATTR_FALSE, 0, 0 },
{ "/prefix/dir/NoMyAttr.java", "myAttr", NULL, 0, 0 },
{ "/prefix/dir/NoMyAttr.java", "other", NULL, 0, 0 },
{ "README", "caveat", "unspecified", 1, 0 },
{ "/specific/path/README", "caveat", "unspecified", 1, 0 },
{ "README", "missing", NULL, 0, 0 },
{ "/specific/path/README", "missing", NULL, 0, 0 },
/* sentinel at end */
{ NULL, NULL, NULL, 0, 0 }
};
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr3"), &file));
cl_assert(file->rules.length == 3);
run_test_cases(file, cases);
git_attr_file__free(file);
}
void test_attr_lookup__from_buffer(void)
{
git_attr_file *file = NULL;
test_case cases[] = {
{ "abc", "foo", GIT_ATTR_TRUE, 0, 0 },
{ "abc", "bar", GIT_ATTR_TRUE, 0, 0 },
{ "abc", "baz", GIT_ATTR_TRUE, 0, 0 },
{ "aaa", "foo", GIT_ATTR_TRUE, 0, 0 },
{ "aaa", "bar", NULL, 0, 0 },
{ "aaa", "baz", GIT_ATTR_TRUE, 0, 0 },
{ "qqq", "foo", NULL, 0, 0 },
{ "qqq", "bar", NULL, 0, 0 },
{ "qqq", "baz", GIT_ATTR_TRUE, 0, 0 },
{ NULL, NULL, NULL, 0, 0 }
};
cl_git_pass(git_attr_file__from_buffer(NULL, "a* foo\nabc bar\n* baz", &file));
cl_assert(file->rules.length == 3);
run_test_cases(file, cases);
git_attr_file__free(file);
}