]>
Commit | Line | Data |
---|---|---|
b47349b8 RB |
1 | #include "clar_libgit2.h" |
2 | #include "posix.h" | |
3 | #include "blob.h" | |
4 | #include "filter.h" | |
5 | #include "buf_text.h" | |
6 | #include "git2/sys/filter.h" | |
7 | #include "git2/sys/repository.h" | |
8 | ||
9 | #define BITFLIP_FILTER_PRIORITY 20 | |
10 | #define REVERSE_FILTER_PRIORITY 25 | |
11 | ||
12 | #define VERY_SECURE_ENCRYPTION(b) ((b) ^ 0xff) | |
13 | ||
14 | #ifdef GIT_WIN32 | |
15 | # define NEWLINE "\r\n" | |
16 | #else | |
17 | # define NEWLINE "\n" | |
18 | #endif | |
19 | ||
20 | static char workdir_data[] = | |
21 | "some simple" NEWLINE | |
22 | "data" NEWLINE | |
23 | "that will be" NEWLINE | |
24 | "trivially" NEWLINE | |
25 | "scrambled." NEWLINE; | |
26 | ||
27 | /* Represents the data above scrambled (bits flipped) after \r\n -> \n | |
28 | * conversion, then bytewise reversed | |
29 | */ | |
30 | static unsigned char bitflipped_and_reversed_data[] = | |
31 | { 0xf5, 0xd1, 0x9b, 0x9a, 0x93, 0x9d, 0x92, 0x9e, 0x8d, 0x9c, 0x8c, | |
32 | 0xf5, 0x86, 0x93, 0x93, 0x9e, 0x96, 0x89, 0x96, 0x8d, 0x8b, 0xf5, | |
33 | 0x9a, 0x9d, 0xdf, 0x93, 0x93, 0x96, 0x88, 0xdf, 0x8b, 0x9e, 0x97, | |
34 | 0x8b, 0xf5, 0x9e, 0x8b, 0x9e, 0x9b, 0xf5, 0x9a, 0x93, 0x8f, 0x92, | |
35 | 0x96, 0x8c, 0xdf, 0x9a, 0x92, 0x90, 0x8c }; | |
36 | ||
37 | #define BITFLIPPED_AND_REVERSED_DATA_LEN 51 | |
38 | ||
39 | static git_repository *g_repo = NULL; | |
40 | ||
41 | static void register_custom_filters(void); | |
42 | ||
43 | void test_filter_custom__initialize(void) | |
44 | { | |
45 | register_custom_filters(); | |
46 | ||
47 | g_repo = cl_git_sandbox_init("empty_standard_repo"); | |
48 | ||
49 | cl_git_mkfile( | |
50 | "empty_standard_repo/.gitattributes", | |
51 | "hero* bitflip reverse\n" | |
52 | "herofile text\n" | |
53 | "heroflip -reverse\n"); | |
54 | } | |
55 | ||
56 | void test_filter_custom__cleanup(void) | |
57 | { | |
58 | cl_git_sandbox_cleanup(); | |
59 | g_repo = NULL; | |
60 | } | |
61 | ||
62 | static int bitflip_filter_apply( | |
63 | git_filter *self, | |
64 | void **payload, | |
65 | git_buf *to, | |
66 | const git_buf *from, | |
67 | const git_filter_source *source) | |
68 | { | |
69 | const unsigned char *src = (const unsigned char *)from->ptr; | |
70 | unsigned char *dst; | |
71 | size_t i; | |
72 | ||
73 | GIT_UNUSED(self); GIT_UNUSED(payload); | |
74 | ||
75 | /* verify that attribute path match worked as expected */ | |
76 | cl_assert_equal_i( | |
77 | 0, git__strncmp("hero", git_filter_source_path(source), 4)); | |
78 | ||
79 | if (!from->size) | |
80 | return 0; | |
81 | ||
82 | cl_git_pass(git_buf_grow(to, from->size)); | |
83 | ||
84 | dst = (unsigned char *)to->ptr; | |
85 | ||
86 | for (i = 0; i < from->size; i++) | |
87 | dst[i] = VERY_SECURE_ENCRYPTION(src[i]); | |
88 | ||
89 | to->size = from->size; | |
90 | ||
91 | return 0; | |
92 | } | |
93 | ||
94 | static void bitflip_filter_free(git_filter *f) | |
95 | { | |
96 | git__free(f); | |
97 | } | |
98 | ||
99 | static git_filter *create_bitflip_filter(void) | |
100 | { | |
101 | git_filter *filter = git__calloc(1, sizeof(git_filter)); | |
102 | cl_assert(filter); | |
103 | ||
104 | filter->version = GIT_FILTER_VERSION; | |
105 | filter->attributes = "+bitflip"; | |
106 | filter->shutdown = bitflip_filter_free; | |
107 | filter->apply = bitflip_filter_apply; | |
108 | ||
109 | return filter; | |
110 | } | |
111 | ||
112 | ||
113 | static int reverse_filter_apply( | |
114 | git_filter *self, | |
115 | void **payload, | |
116 | git_buf *to, | |
117 | const git_buf *from, | |
118 | const git_filter_source *source) | |
119 | { | |
120 | const unsigned char *src = (const unsigned char *)from->ptr; | |
121 | const unsigned char *end = src + from->size; | |
122 | unsigned char *dst; | |
123 | ||
124 | GIT_UNUSED(self); GIT_UNUSED(payload); GIT_UNUSED(source); | |
125 | ||
126 | /* verify that attribute path match worked as expected */ | |
127 | cl_assert_equal_i( | |
128 | 0, git__strncmp("hero", git_filter_source_path(source), 4)); | |
129 | ||
130 | if (!from->size) | |
131 | return 0; | |
132 | ||
133 | cl_git_pass(git_buf_grow(to, from->size)); | |
134 | ||
135 | dst = (unsigned char *)to->ptr + from->size - 1; | |
136 | ||
137 | while (src < end) | |
138 | *dst-- = *src++; | |
139 | ||
140 | to->size = from->size; | |
141 | ||
142 | return 0; | |
143 | } | |
144 | ||
145 | static void reverse_filter_free(git_filter *f) | |
146 | { | |
147 | git__free(f); | |
148 | } | |
149 | ||
150 | static git_filter *create_reverse_filter(void) | |
151 | { | |
152 | git_filter *filter = git__calloc(1, sizeof(git_filter)); | |
153 | cl_assert(filter); | |
154 | ||
155 | filter->version = GIT_FILTER_VERSION; | |
156 | filter->attributes = "+reverse"; | |
157 | filter->shutdown = reverse_filter_free; | |
158 | filter->apply = reverse_filter_apply; | |
159 | ||
160 | return filter; | |
161 | } | |
162 | ||
163 | static void register_custom_filters(void) | |
164 | { | |
165 | static int filters_registered = 0; | |
166 | ||
167 | if (!filters_registered) { | |
168 | cl_git_pass(git_filter_register( | |
169 | "bitflip", create_bitflip_filter(), BITFLIP_FILTER_PRIORITY)); | |
170 | ||
171 | cl_git_pass(git_filter_register( | |
172 | "reverse", create_reverse_filter(), REVERSE_FILTER_PRIORITY)); | |
173 | ||
174 | filters_registered = 1; | |
175 | } | |
176 | } | |
177 | ||
178 | ||
179 | void test_filter_custom__to_odb(void) | |
180 | { | |
181 | git_filter_list *fl; | |
182 | git_buf out = { 0 }; | |
183 | git_buf in = GIT_BUF_INIT_CONST(workdir_data, strlen(workdir_data)); | |
184 | ||
185 | cl_git_pass(git_filter_list_load( | |
186 | &fl, g_repo, NULL, "herofile", GIT_FILTER_TO_ODB)); | |
187 | ||
188 | cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in)); | |
189 | ||
190 | cl_assert_equal_i(BITFLIPPED_AND_REVERSED_DATA_LEN, out.size); | |
191 | ||
192 | cl_assert_equal_i( | |
193 | 0, memcmp(bitflipped_and_reversed_data, out.ptr, out.size)); | |
194 | ||
195 | git_filter_list_free(fl); | |
196 | git_buf_free(&out); | |
197 | } | |
198 | ||
199 | void test_filter_custom__to_workdir(void) | |
200 | { | |
201 | git_filter_list *fl; | |
202 | git_buf out = { 0 }; | |
203 | git_buf in = GIT_BUF_INIT_CONST( | |
204 | bitflipped_and_reversed_data, BITFLIPPED_AND_REVERSED_DATA_LEN); | |
205 | ||
206 | cl_git_pass(git_filter_list_load( | |
207 | &fl, g_repo, NULL, "herofile", GIT_FILTER_TO_WORKTREE)); | |
208 | ||
209 | cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in)); | |
210 | ||
211 | cl_assert_equal_i(strlen(workdir_data), out.size); | |
212 | ||
213 | cl_assert_equal_i( | |
214 | 0, memcmp(workdir_data, out.ptr, out.size)); | |
215 | ||
216 | git_filter_list_free(fl); | |
217 | git_buf_free(&out); | |
218 | } | |
219 | ||
220 | void test_filter_custom__can_register_a_custom_filter_in_the_repository(void) | |
221 | { | |
222 | git_filter_list *fl; | |
223 | ||
224 | cl_git_pass(git_filter_list_load( | |
225 | &fl, g_repo, NULL, "herofile", GIT_FILTER_TO_WORKTREE)); | |
226 | /* expect: bitflip, reverse, crlf */ | |
227 | cl_assert_equal_sz(3, git_filter_list_length(fl)); | |
228 | git_filter_list_free(fl); | |
229 | ||
230 | cl_git_pass(git_filter_list_load( | |
231 | &fl, g_repo, NULL, "herocorp", GIT_FILTER_TO_WORKTREE)); | |
232 | /* expect: bitflip, reverse */ | |
233 | cl_assert_equal_sz(2, git_filter_list_length(fl)); | |
234 | git_filter_list_free(fl); | |
235 | ||
236 | cl_git_pass(git_filter_list_load( | |
237 | &fl, g_repo, NULL, "heroflip", GIT_FILTER_TO_WORKTREE)); | |
238 | /* expect: bitflip (because of -reverse) */ | |
239 | cl_assert_equal_sz(1, git_filter_list_length(fl)); | |
240 | git_filter_list_free(fl); | |
241 | ||
242 | cl_git_pass(git_filter_list_load( | |
243 | &fl, g_repo, NULL, "doesntapplytome", GIT_FILTER_TO_WORKTREE)); | |
244 | /* expect: none */ | |
245 | cl_assert_equal_sz(0, git_filter_list_length(fl)); | |
246 | git_filter_list_free(fl); | |
247 | } |