Commit b47349b8 by Russell Belfer

Port tests from PR 1683

This ports over some of the tests from
    https://github.com/libgit2/libgit2/pull/1683
by @yorah and @ethomson
parent 0e32635f
...@@ -55,6 +55,11 @@ typedef struct { ...@@ -55,6 +55,11 @@ typedef struct {
} git_buf; } git_buf;
/** /**
* Static initializer for git_buf from static buffer
*/
#define GIT_BUF_INIT_CONST(STR,LEN) { (char *)(STR), 0, (size_t)(LEN) }
/**
* Free the memory referred to by the git_buf. * Free the memory referred to by the git_buf.
* *
* Note that this does not free the `git_buf` itself, just the memory * Note that this does not free the `git_buf` itself, just the memory
......
...@@ -60,6 +60,19 @@ GIT_EXTERN(int) git_filter_list_push( ...@@ -60,6 +60,19 @@ GIT_EXTERN(int) git_filter_list_push(
git_filter_list *fl, git_filter *filter, void *payload); git_filter_list *fl, git_filter *filter, void *payload);
/** /**
* Look up how many filters are in the list
*
* We will attempt to apply all of these filters to any data passed in,
* but note that the filter apply action still has the option of skipping
* data that is passed in (for example, the CRLF filter will skip data
* that appears to be binary).
*
* @param fl A filter list
* @return The number of filters in the list
*/
GIT_EXTERN(size_t) git_filter_list_length(const git_filter_list *fl);
/**
* A filter source represents a file/blob to be processed * A filter source represents a file/blob to be processed
*/ */
typedef struct git_filter_source git_filter_source; typedef struct git_filter_source git_filter_source;
......
...@@ -548,6 +548,11 @@ int git_filter_list_push( ...@@ -548,6 +548,11 @@ int git_filter_list_push(
return 0; return 0;
} }
size_t git_filter_list_length(const git_filter_list *fl)
{
return fl ? git_array_size(fl->filters) : 0;
}
static int filter_list_out_buffer_from_raw( static int filter_list_out_buffer_from_raw(
git_buf *out, const void *ptr, size_t size) git_buf *out, const void *ptr, size_t size)
{ {
......
...@@ -5,10 +5,16 @@ static git_repository *g_repo = NULL; ...@@ -5,10 +5,16 @@ static git_repository *g_repo = NULL;
void test_filter_crlf__initialize(void) void test_filter_crlf__initialize(void)
{ {
git_config *cfg;
g_repo = cl_git_sandbox_init("crlf"); g_repo = cl_git_sandbox_init("crlf");
cl_git_mkfile("crlf/.gitattributes", cl_git_mkfile("crlf/.gitattributes",
"*.txt text\n*.bin binary\n*.crlf text eol=crlf\n*.lf text eol=lf\n"); "*.txt text\n*.bin binary\n*.crlf text eol=crlf\n*.lf text eol=lf\n");
cl_git_pass(git_repository_config(&cfg, g_repo));
cl_git_pass(git_config_set_string(cfg, "core.autocrlf", "true"));
git_config_free(cfg);
} }
void test_filter_crlf__cleanup(void) void test_filter_crlf__cleanup(void)
...@@ -22,13 +28,6 @@ void test_filter_crlf__to_worktree(void) ...@@ -22,13 +28,6 @@ void test_filter_crlf__to_worktree(void)
git_filter *crlf; git_filter *crlf;
git_buf in = { 0 }, out = { 0 }; git_buf in = { 0 }, out = { 0 };
{
git_config *cfg;
cl_git_pass(git_repository_config(&cfg, g_repo));
cl_git_pass(git_config_set_string(cfg, "core.autocrlf", "true"));
git_config_free(cfg);
}
cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_WORKTREE)); cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_WORKTREE));
crlf = git_filter_lookup(GIT_FILTER_CRLF); crlf = git_filter_lookup(GIT_FILTER_CRLF);
...@@ -57,13 +56,6 @@ void test_filter_crlf__to_odb(void) ...@@ -57,13 +56,6 @@ void test_filter_crlf__to_odb(void)
git_filter *crlf; git_filter *crlf;
git_buf in = { 0 }, out = { 0 }; git_buf in = { 0 }, out = { 0 };
{
git_config *cfg;
cl_git_pass(git_repository_config(&cfg, g_repo));
cl_git_pass(git_config_set_string(cfg, "core.autocrlf", "true"));
git_config_free(cfg);
}
cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_ODB)); cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_ODB));
crlf = git_filter_lookup(GIT_FILTER_CRLF); crlf = git_filter_lookup(GIT_FILTER_CRLF);
......
...@@ -22,5 +22,4 @@ ...@@ -22,5 +22,4 @@
#define MORE_CRLF_TEXT_AS_LF "crlf\ncrlf\nlf\ncrlf\ncrlf\n" #define MORE_CRLF_TEXT_AS_LF "crlf\ncrlf\nlf\ncrlf\ncrlf\n"
#define MORE_LF_TEXT_AS_LF "lf\nlf\ncrlf\nlf\nlf\n" #define MORE_LF_TEXT_AS_LF "lf\nlf\ncrlf\nlf\nlf\n"
#endif #endif
#include "clar_libgit2.h"
#include "posix.h"
#include "blob.h"
#include "filter.h"
#include "buf_text.h"
#include "git2/sys/filter.h"
#include "git2/sys/repository.h"
#define BITFLIP_FILTER_PRIORITY 20
#define REVERSE_FILTER_PRIORITY 25
#define VERY_SECURE_ENCRYPTION(b) ((b) ^ 0xff)
#ifdef GIT_WIN32
# define NEWLINE "\r\n"
#else
# define NEWLINE "\n"
#endif
static char workdir_data[] =
"some simple" NEWLINE
"data" NEWLINE
"that will be" NEWLINE
"trivially" NEWLINE
"scrambled." NEWLINE;
/* Represents the data above scrambled (bits flipped) after \r\n -> \n
* conversion, then bytewise reversed
*/
static unsigned char bitflipped_and_reversed_data[] =
{ 0xf5, 0xd1, 0x9b, 0x9a, 0x93, 0x9d, 0x92, 0x9e, 0x8d, 0x9c, 0x8c,
0xf5, 0x86, 0x93, 0x93, 0x9e, 0x96, 0x89, 0x96, 0x8d, 0x8b, 0xf5,
0x9a, 0x9d, 0xdf, 0x93, 0x93, 0x96, 0x88, 0xdf, 0x8b, 0x9e, 0x97,
0x8b, 0xf5, 0x9e, 0x8b, 0x9e, 0x9b, 0xf5, 0x9a, 0x93, 0x8f, 0x92,
0x96, 0x8c, 0xdf, 0x9a, 0x92, 0x90, 0x8c };
#define BITFLIPPED_AND_REVERSED_DATA_LEN 51
static git_repository *g_repo = NULL;
static void register_custom_filters(void);
void test_filter_custom__initialize(void)
{
register_custom_filters();
g_repo = cl_git_sandbox_init("empty_standard_repo");
cl_git_mkfile(
"empty_standard_repo/.gitattributes",
"hero* bitflip reverse\n"
"herofile text\n"
"heroflip -reverse\n");
}
void test_filter_custom__cleanup(void)
{
cl_git_sandbox_cleanup();
g_repo = NULL;
}
static int bitflip_filter_apply(
git_filter *self,
void **payload,
git_buf *to,
const git_buf *from,
const git_filter_source *source)
{
const unsigned char *src = (const unsigned char *)from->ptr;
unsigned char *dst;
size_t i;
GIT_UNUSED(self); GIT_UNUSED(payload);
/* verify that attribute path match worked as expected */
cl_assert_equal_i(
0, git__strncmp("hero", git_filter_source_path(source), 4));
if (!from->size)
return 0;
cl_git_pass(git_buf_grow(to, from->size));
dst = (unsigned char *)to->ptr;
for (i = 0; i < from->size; i++)
dst[i] = VERY_SECURE_ENCRYPTION(src[i]);
to->size = from->size;
return 0;
}
static void bitflip_filter_free(git_filter *f)
{
git__free(f);
}
static git_filter *create_bitflip_filter(void)
{
git_filter *filter = git__calloc(1, sizeof(git_filter));
cl_assert(filter);
filter->version = GIT_FILTER_VERSION;
filter->attributes = "+bitflip";
filter->shutdown = bitflip_filter_free;
filter->apply = bitflip_filter_apply;
return filter;
}
static int reverse_filter_apply(
git_filter *self,
void **payload,
git_buf *to,
const git_buf *from,
const git_filter_source *source)
{
const unsigned char *src = (const unsigned char *)from->ptr;
const unsigned char *end = src + from->size;
unsigned char *dst;
GIT_UNUSED(self); GIT_UNUSED(payload); GIT_UNUSED(source);
/* verify that attribute path match worked as expected */
cl_assert_equal_i(
0, git__strncmp("hero", git_filter_source_path(source), 4));
if (!from->size)
return 0;
cl_git_pass(git_buf_grow(to, from->size));
dst = (unsigned char *)to->ptr + from->size - 1;
while (src < end)
*dst-- = *src++;
to->size = from->size;
return 0;
}
static void reverse_filter_free(git_filter *f)
{
git__free(f);
}
static git_filter *create_reverse_filter(void)
{
git_filter *filter = git__calloc(1, sizeof(git_filter));
cl_assert(filter);
filter->version = GIT_FILTER_VERSION;
filter->attributes = "+reverse";
filter->shutdown = reverse_filter_free;
filter->apply = reverse_filter_apply;
return filter;
}
static void register_custom_filters(void)
{
static int filters_registered = 0;
if (!filters_registered) {
cl_git_pass(git_filter_register(
"bitflip", create_bitflip_filter(), BITFLIP_FILTER_PRIORITY));
cl_git_pass(git_filter_register(
"reverse", create_reverse_filter(), REVERSE_FILTER_PRIORITY));
filters_registered = 1;
}
}
void test_filter_custom__to_odb(void)
{
git_filter_list *fl;
git_buf out = { 0 };
git_buf in = GIT_BUF_INIT_CONST(workdir_data, strlen(workdir_data));
cl_git_pass(git_filter_list_load(
&fl, g_repo, NULL, "herofile", GIT_FILTER_TO_ODB));
cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
cl_assert_equal_i(BITFLIPPED_AND_REVERSED_DATA_LEN, out.size);
cl_assert_equal_i(
0, memcmp(bitflipped_and_reversed_data, out.ptr, out.size));
git_filter_list_free(fl);
git_buf_free(&out);
}
void test_filter_custom__to_workdir(void)
{
git_filter_list *fl;
git_buf out = { 0 };
git_buf in = GIT_BUF_INIT_CONST(
bitflipped_and_reversed_data, BITFLIPPED_AND_REVERSED_DATA_LEN);
cl_git_pass(git_filter_list_load(
&fl, g_repo, NULL, "herofile", GIT_FILTER_TO_WORKTREE));
cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
cl_assert_equal_i(strlen(workdir_data), out.size);
cl_assert_equal_i(
0, memcmp(workdir_data, out.ptr, out.size));
git_filter_list_free(fl);
git_buf_free(&out);
}
void test_filter_custom__can_register_a_custom_filter_in_the_repository(void)
{
git_filter_list *fl;
cl_git_pass(git_filter_list_load(
&fl, g_repo, NULL, "herofile", GIT_FILTER_TO_WORKTREE));
/* expect: bitflip, reverse, crlf */
cl_assert_equal_sz(3, git_filter_list_length(fl));
git_filter_list_free(fl);
cl_git_pass(git_filter_list_load(
&fl, g_repo, NULL, "herocorp", GIT_FILTER_TO_WORKTREE));
/* expect: bitflip, reverse */
cl_assert_equal_sz(2, git_filter_list_length(fl));
git_filter_list_free(fl);
cl_git_pass(git_filter_list_load(
&fl, g_repo, NULL, "heroflip", GIT_FILTER_TO_WORKTREE));
/* expect: bitflip (because of -reverse) */
cl_assert_equal_sz(1, git_filter_list_length(fl));
git_filter_list_free(fl);
cl_git_pass(git_filter_list_load(
&fl, g_repo, NULL, "doesntapplytome", GIT_FILTER_TO_WORKTREE));
/* expect: none */
cl_assert_equal_sz(0, git_filter_list_length(fl));
git_filter_list_free(fl);
}
...@@ -4,9 +4,10 @@ ...@@ -4,9 +4,10 @@
#include "buf_text.h" #include "buf_text.h"
static git_repository *g_repo = NULL; static git_repository *g_repo = NULL;
#define NUM_TEST_OBJECTS 9
static git_oid g_oids[NUM_TEST_OBJECTS]; #define CRLF_NUM_TEST_OBJECTS 9
static const char *g_raw[NUM_TEST_OBJECTS] = {
static const char *g_crlf_raw[CRLF_NUM_TEST_OBJECTS] = {
"", "",
"foo\nbar\n", "foo\nbar\n",
"foo\rbar\r", "foo\rbar\r",
...@@ -17,19 +18,14 @@ static const char *g_raw[NUM_TEST_OBJECTS] = { ...@@ -17,19 +18,14 @@ static const char *g_raw[NUM_TEST_OBJECTS] = {
"\xEF\xBB\xBF\xE3\x81\xBB\xE3\x81\x92\xE3\x81\xBB\xE3\x81\x92\r\n\xE3\x81\xBB\xE3\x81\x92\xE3\x81\xBB\xE3\x81\x92\r\n", "\xEF\xBB\xBF\xE3\x81\xBB\xE3\x81\x92\xE3\x81\xBB\xE3\x81\x92\r\n\xE3\x81\xBB\xE3\x81\x92\xE3\x81\xBB\xE3\x81\x92\r\n",
"\xFE\xFF\x00T\x00h\x00i\x00s\x00!" "\xFE\xFF\x00T\x00h\x00i\x00s\x00!"
}; };
static git_off_t g_len[NUM_TEST_OBJECTS] = { -1, -1, -1, -1, -1, 17, -1, -1, 12 };
static git_buf_text_stats g_stats[NUM_TEST_OBJECTS] = { static git_off_t g_crlf_raw_len[CRLF_NUM_TEST_OBJECTS] = {
{ 0, 0, 0, 0, 0, 0, 0 }, -1, -1, -1, -1, -1, 17, -1, -1, 12
{ 0, 0, 0, 2, 0, 6, 0 },
{ 0, 0, 2, 0, 0, 6, 0 },
{ 0, 0, 2, 2, 2, 6, 0 },
{ 0, 0, 4, 4, 1, 31, 0 },
{ 0, 1, 1, 2, 1, 9, 5 },
{ GIT_BOM_UTF8, 0, 0, 1, 0, 16, 0 },
{ GIT_BOM_UTF8, 0, 2, 2, 2, 27, 0 },
{ GIT_BOM_UTF16_BE, 5, 0, 0, 0, 7, 5 },
}; };
static git_buf g_crlf_filtered[NUM_TEST_OBJECTS] = {
static git_oid g_crlf_oids[CRLF_NUM_TEST_OBJECTS];
static git_buf g_crlf_filtered[CRLF_NUM_TEST_OBJECTS] = {
{ "", 0, 0 }, { "", 0, 0 },
{ "foo\nbar\n", 0, 8 }, { "foo\nbar\n", 0, 8 },
{ "foo\rbar\r", 0, 8 }, { "foo\rbar\r", 0, 8 },
...@@ -41,30 +37,36 @@ static git_buf g_crlf_filtered[NUM_TEST_OBJECTS] = { ...@@ -41,30 +37,36 @@ static git_buf g_crlf_filtered[NUM_TEST_OBJECTS] = {
{ "\xFE\xFF\x00T\x00h\x00i\x00s\x00!", 0, 12 } { "\xFE\xFF\x00T\x00h\x00i\x00s\x00!", 0, 12 }
}; };
static git_buf_text_stats g_crlf_filtered_stats[CRLF_NUM_TEST_OBJECTS] = {
{ 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 2, 0, 6, 0 },
{ 0, 0, 2, 0, 0, 6, 0 },
{ 0, 0, 2, 2, 2, 6, 0 },
{ 0, 0, 4, 4, 1, 31, 0 },
{ 0, 1, 1, 2, 1, 9, 5 },
{ GIT_BOM_UTF8, 0, 0, 1, 0, 16, 0 },
{ GIT_BOM_UTF8, 0, 2, 2, 2, 27, 0 },
{ GIT_BOM_UTF16_BE, 5, 0, 0, 0, 7, 5 },
};
void test_object_blob_filter__initialize(void) void test_object_blob_filter__initialize(void)
{ {
int i; int i;
cl_fixture_sandbox("empty_standard_repo"); g_repo = cl_git_sandbox_init("empty_standard_repo");
cl_git_pass(p_rename(
"empty_standard_repo/.gitted", "empty_standard_repo/.git"));
cl_git_pass(git_repository_open(&g_repo, "empty_standard_repo"));
for (i = 0; i < NUM_TEST_OBJECTS; i++) { for (i = 0; i < CRLF_NUM_TEST_OBJECTS; i++) {
size_t len = (g_len[i] < 0) ? strlen(g_raw[i]) : (size_t)g_len[i]; if (g_crlf_raw_len[i] < 0)
g_len[i] = (git_off_t)len; g_crlf_raw_len[i] = strlen(g_crlf_raw[i]);
cl_git_pass( cl_git_pass(git_blob_create_frombuffer(
git_blob_create_frombuffer(&g_oids[i], g_repo, g_raw[i], len) &g_crlf_oids[i], g_repo, g_crlf_raw[i], (size_t)g_crlf_raw_len[i]));
);
} }
} }
void test_object_blob_filter__cleanup(void) void test_object_blob_filter__cleanup(void)
{ {
git_repository_free(g_repo); cl_git_sandbox_cleanup();
g_repo = NULL;
cl_fixture_cleanup("empty_standard_repo");
} }
void test_object_blob_filter__unfiltered(void) void test_object_blob_filter__unfiltered(void)
...@@ -72,10 +74,15 @@ void test_object_blob_filter__unfiltered(void) ...@@ -72,10 +74,15 @@ void test_object_blob_filter__unfiltered(void)
int i; int i;
git_blob *blob; git_blob *blob;
for (i = 0; i < NUM_TEST_OBJECTS; i++) { for (i = 0; i < CRLF_NUM_TEST_OBJECTS; i++) {
cl_git_pass(git_blob_lookup(&blob, g_repo, &g_oids[i])); size_t raw_len = (size_t)g_crlf_raw_len[i];
cl_assert(g_len[i] == git_blob_rawsize(blob));
cl_assert(memcmp(git_blob_rawcontent(blob), g_raw[i], (size_t)g_len[i]) == 0); cl_git_pass(git_blob_lookup(&blob, g_repo, &g_crlf_oids[i]));
cl_assert_equal_sz(raw_len, (size_t)git_blob_rawsize(blob));
cl_assert_equal_i(
0, memcmp(g_crlf_raw[i], git_blob_rawcontent(blob), raw_len));
git_blob_free(blob); git_blob_free(blob);
} }
} }
...@@ -87,11 +94,12 @@ void test_object_blob_filter__stats(void) ...@@ -87,11 +94,12 @@ void test_object_blob_filter__stats(void)
git_buf buf = GIT_BUF_INIT; git_buf buf = GIT_BUF_INIT;
git_buf_text_stats stats; git_buf_text_stats stats;
for (i = 0; i < NUM_TEST_OBJECTS; i++) { for (i = 0; i < CRLF_NUM_TEST_OBJECTS; i++) {
cl_git_pass(git_blob_lookup(&blob, g_repo, &g_oids[i])); cl_git_pass(git_blob_lookup(&blob, g_repo, &g_crlf_oids[i]));
cl_git_pass(git_blob__getbuf(&buf, blob)); cl_git_pass(git_blob__getbuf(&buf, blob));
git_buf_text_gather_stats(&stats, &buf, false); git_buf_text_gather_stats(&stats, &buf, false);
cl_assert(memcmp(&g_stats[i], &stats, sizeof(stats)) == 0); cl_assert_equal_i(
0, memcmp(&g_crlf_filtered_stats[i], &stats, sizeof(stats)));
git_blob_free(blob); git_blob_free(blob);
} }
...@@ -116,14 +124,15 @@ void test_object_blob_filter__to_odb(void) ...@@ -116,14 +124,15 @@ void test_object_blob_filter__to_odb(void)
&fl, g_repo, NULL, "filename.txt", GIT_FILTER_TO_ODB)); &fl, g_repo, NULL, "filename.txt", GIT_FILTER_TO_ODB));
cl_assert(fl != NULL); cl_assert(fl != NULL);
for (i = 0; i < NUM_TEST_OBJECTS; i++) { for (i = 0; i < CRLF_NUM_TEST_OBJECTS; i++) {
cl_git_pass(git_blob_lookup(&blob, g_repo, &g_oids[i])); cl_git_pass(git_blob_lookup(&blob, g_repo, &g_crlf_oids[i]));
cl_git_pass(git_filter_list_apply_to_blob(&out, fl, blob)); cl_git_pass(git_filter_list_apply_to_blob(&out, fl, blob));
cl_assert(!memcmp( cl_assert_equal_sz(g_crlf_filtered[i].size, out.size);
out.ptr, g_crlf_filtered[i].ptr,
min(out.size, g_crlf_filtered[i].size))); cl_assert_equal_i(
0, memcmp(out.ptr, g_crlf_filtered[i].ptr, out.size));
git_blob_free(blob); git_blob_free(blob);
} }
...@@ -132,4 +141,3 @@ void test_object_blob_filter__to_odb(void) ...@@ -132,4 +141,3 @@ void test_object_blob_filter__to_odb(void)
git_buf_free(&out); git_buf_free(&out);
git_config_free(cfg); git_config_free(cfg);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment