Browse Source

Add unit-testing for range-parser and fix the parser

personal/stbuehler/wip
Stefan Bühler 12 years ago
parent
commit
871a4dc8b5
  1. 1
      src/CMakeLists.txt
  2. 32
      src/main/http_range_parser.rl
  3. 106
      src/unittests/test-range-parser.c

1
src/CMakeLists.txt

@ -395,5 +395,6 @@ IF(BUILD_UNIT_TESTS)
ADD_TEST_BINARY(Utils-UnitTest test-utils unittests/test-utils.c)
ADD_TEST_BINARY(Chunk-UnitTest test-chunk unittests/test-chunk.c)
ADD_TEST_BINARY(RangeParser-UnitTest test-range-parser unittests/test-range-parser.c)
ENDIF(BUILD_UNIT_TESTS)

32
src/main/http_range_parser.rl

@ -33,18 +33,24 @@
}
action last_byte {
s->range_end = tmp;
found = TRUE;
}
action last_byte_empty {
s->range_end = s->limit;
s->range_end = s->limit - 1;
found = TRUE;
}
action suffix_range {
s->range_end = s->limit - 1;
s->range_start = s->limit - tmp;
found = TRUE;
}
action range_complete {
fbreak;
}
range = (int %first_byte "-" (int %last_byte | "" %last_byte_empty) | "-" int %suffix_range);
range = (int %first_byte ws* "-" ws** (int %last_byte | "" %last_byte_empty) | "-" ws* int %suffix_range) ;
main := ws* "bytes" "=" range ("," >{fbreak;} range)**;
main := ws* "bytes" ws* "=" (ws | ",")* range ( ws* "," >range_complete (ws | ",")* range)** (ws | ",")*;
write data;
}%%
@ -53,21 +59,33 @@ liParseHttpRangeResult li_parse_http_range_next(liParseHttpRangeState* s) {
const char *pe, *eof;
goffset tmp = 0;
if (s->cs == http_range_parser_error) {
return LI_PARSE_HTTP_RANGE_INVALID;
}
eof = pe = s->data->str + s->data->len;
for ( ;; ) {
if (s->cs >= http_range_parser_first_final) {
gboolean found = FALSE;
if (s->data_pos >= eof) {
return s->found_valid_range ? LI_PARSE_HTTP_RANGE_DONE : LI_PARSE_HTTP_RANGE_NOT_SATISFIABLE;
}
%% write exec;
if (s->cs >= http_range_parser_first_final) {
s->last_range = TRUE;
} else if (s->cs == http_range_parser_error) {
if (s->cs == http_range_parser_error) {
return LI_PARSE_HTTP_RANGE_INVALID;
}
if (s->data_pos >= eof) {
s->last_range = TRUE;
}
if (!found) {
return s->found_valid_range ? LI_PARSE_HTTP_RANGE_DONE : LI_PARSE_HTTP_RANGE_NOT_SATISFIABLE;
}
if (s->range_end >= s->limit) {
s->range_end = s->limit - 1;
}

106
src/unittests/test-range-parser.c

@ -0,0 +1,106 @@
#include <lighttpd/base.h>
#include <lighttpd/http_range_parser.h>
#define LIMIT_EXAMPLE (1409328ul)
typedef struct {
liParseHttpRangeResult res;
goffset start, end;
} rangeentry;
static const gchar* rangeresult_str(liParseHttpRangeResult res) {
switch (res) {
case LI_PARSE_HTTP_RANGE_OK: return "Range-OK";
case LI_PARSE_HTTP_RANGE_DONE: return "Range-Done";
case LI_PARSE_HTTP_RANGE_INVALID: return "Range-Invalid";
case LI_PARSE_HTTP_RANGE_NOT_SATISFIABLE: return "Range-NotSatisfiable";
default: return "RangeResult-Unknown";
}
}
#define range_error(fmt, ...) g_error("li_parse_http_range_next error in round %i for '%s' (remaining '%s'): " fmt, round, range->str, s.data_pos, __VA_ARGS__)
static void test_range(GString *range, goffset limit, const rangeentry *results) {
liParseHttpRangeState s;
liParseHttpRangeResult res = LI_PARSE_HTTP_RANGE_OK;
guint round = 1;
li_parse_http_range_init(&s, range, limit);
for ( ; res == LI_PARSE_HTTP_RANGE_OK; results++, round++ ) {
#if 0
g_print("Round %i, parse '%s', state: %i\n", round, s.data_pos, s.cs);
#endif
res = li_parse_http_range_next(&s);
if (res != results->res) {
range_error("unexpected parse result '%s' (expected '%s')", rangeresult_str(res), rangeresult_str(results->res));
}
if (res != LI_PARSE_HTTP_RANGE_OK) break;
if (s.range_length != s.range_end - s.range_start + 1) {
range_error("unexpected range length %"L_GOFFSET_FORMAT" (expected %"L_GOFFSET_FORMAT")", s.range_length, s.range_end - s.range_start + 1);
} else if (s.range_start != results->start) {
range_error("unexpected range start %"L_GOFFSET_FORMAT" (expected %"L_GOFFSET_FORMAT")", s.range_start, results->start);
} else if (s.range_end != results->end) {
range_error("unexpected range end %"L_GOFFSET_FORMAT" (expected %"L_GOFFSET_FORMAT")", s.range_end, results->end);
}
}
li_parse_http_range_clear(&s);
}
static void test_range_parser_ex1(void) {
static const rangeentry results[] = {
{ LI_PARSE_HTTP_RANGE_OK, LIMIT_EXAMPLE - 500, LIMIT_EXAMPLE - 1 },
{ LI_PARSE_HTTP_RANGE_OK, 10, LIMIT_EXAMPLE - 1 },
{ LI_PARSE_HTTP_RANGE_OK, 5, 9 },
{ LI_PARSE_HTTP_RANGE_DONE, -1, -1 }
};
GString range = li_const_gstring(CONST_STR_LEN("bytes=-500,,10-,5-9,"));
test_range(&range, LIMIT_EXAMPLE, results);
}
static void test_range_parser_ex2(void) {
static const rangeentry results[] = {
{ LI_PARSE_HTTP_RANGE_OK, LIMIT_EXAMPLE - 500, LIMIT_EXAMPLE - 1 },
{ LI_PARSE_HTTP_RANGE_OK, 10, LIMIT_EXAMPLE - 1 },
{ LI_PARSE_HTTP_RANGE_OK, 5, 9 },
{ LI_PARSE_HTTP_RANGE_DONE, -1, -1 }
};
GString range = li_const_gstring(CONST_STR_LEN("bytes = , -500, ,, ,10- ,5-9 ,,"));
test_range(&range, LIMIT_EXAMPLE, results);
}
static void test_range_parser_ex3(void) {
static const rangeentry results[] = {
{ LI_PARSE_HTTP_RANGE_NOT_SATISFIABLE, -1, -1 }
};
GString range = li_const_gstring(CONST_STR_LEN("bytes=0"));
test_range(&range, LIMIT_EXAMPLE, results);
}
static void test_range_parser_ex4(void) {
static const rangeentry results[] = {
{ LI_PARSE_HTTP_RANGE_OK, 0, LIMIT_EXAMPLE - 1 },
{ LI_PARSE_HTTP_RANGE_DONE, -1, -1 }
};
GString range = li_const_gstring(CONST_STR_LEN("bytes=0-"));
test_range(&range, LIMIT_EXAMPLE, results);
}
int main(int argc, char **argv) {
g_test_init(&argc, &argv, NULL);
g_test_add_func("/range-parser/range_example_1", test_range_parser_ex1);
g_test_add_func("/range-parser/range_example_2", test_range_parser_ex2);
g_test_add_func("/range-parser/range_example_3", test_range_parser_ex3);
g_test_add_func("/range-parser/range_example_4", test_range_parser_ex4);
return g_test_run();
}
Loading…
Cancel
Save