Skip to content

Instantly share code, notes, and snippets.

@tj
Created December 1, 2009 04:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tj/246057 to your computer and use it in GitHub Desktop.
Save tj/246057 to your computer and use it in GitHub Desktop.
#include <time.h>
#include "yamp.h"
#include "cspec.h"
#define fixture(N) \
if (!(fd = fopen("spec/fixtures/" N, "r"))) \
fprintf(stderr, "failed to open fixture `%s'\n", N), exit(1);
#define parse \
root = Yamp_parse(fd);
#define parse_fixture(N) \
fixture(N ".html"); parse;
#define parse_xml_fixture(N) \
fixture(N ".xml"); parse;
#define match_have_name(A, E) \
(strcmp(((Element *) A)->name, E) == 0)
#define match_have_parent(A, E) \
(A->parent == E)
#define match_have_n_children(A, E) \
(A->nchildren == E)
#define match_have_n_attrs(A, E) \
(children_of_type(A, tAttr) == E)
#define match_have_text(A, E) \
(strcmp(((Text *) A)->val, E) == 0)
#define match_be_type(A, E) \
(A->type == E)
#define match_include_text(A, E) \
strstr(((Text *) A)->val, E)
#define at(I) \
(node ? node->children[I] : root->children[I])
#define bm_start \
clock_t start = clock();
#define bm_stop \
printf("\n duration: %0.6f ms\n", (float) (clock() - start) / CLOCKS_PER_SEC);
static int
children_of_type(Node *self, NodeType type) {
int c = 0;
for (int i = 0; i < self->nchildren; ++i)
if (self->children[i]->type == type)
++c;
return c;
}
static FILE *fd;
static Node *root = NULL;
static Node *node = NULL;
describe "Yamp_parse()"
it "should return the root element"
parse_fixture("nested.ws");
root should have_name "html";
root should have_parent NULL;
end
it "should parse elements with child elements"
parse_fixture("nested");
root should have_n_children 1;
at(0) should have_name "body";
end
it "should parse elements with child elements disregarding whitespace"
parse_fixture("nested.ws");
root should have_n_children 1;
at(0) should have_name "body";
end
it "should parse reset parent elements"
parse_fixture("nested");
node = at(0);
node should have_n_children 2;
at(0) should have_name "h1";
at(1) should have_name "p";
end
it "should parse reset parent elements disregarding whitespace"
parse_fixture("nested.ws");
node = at(0);
node should have_n_children 2;
at(0) should have_name "h1";
at(1) should have_name "p";
end
it "should parse self-closing elements"
parse_fixture("self-closing");
root should have_n_children 4;
at(0) should have_name "input";
at(1) should have_name "link";
at(2) should have_name "br";
at(3) should have_name "a";
end
it "should parse attributes"
parse_fixture("attrs");
root should have_n_attrs 2;
node = root->children[0];
at(0) should have_text "lang";
at(1) should have_text "en";
node = root->children[1];
at(0) should have_text "class";
at(1) should have_text "im some classes";
end
it "should parse attributes with whitespace before / after keys and values"
parse_fixture("attrs.ws");
root should have_n_attrs 2;
node = root->children[0];
at(0) should have_text "lang";
at(1) should have_text "en";
node = root->children[1];
at(0) should have_text "class";
at(1) should have_text "im some classes";
end
it "should parse single-quoted attributes"
parse_fixture("attrs.single");
root should have_n_attrs 1;
node = at(0);
at(0) should have_text "lang";
at(1) should have_text "en";
end
it "should parse empty attributes but not push as a node"
parse_fixture("attrs.empty");
root should have_n_children 0;
end
it "should parse empty attributes but not push as a node when whitespace is present"
parse_fixture("attrs.empty.ws");
root should have_n_children 0;
end
it "should parse text"
parse_fixture("text");
at(0) should have_text "foo bar";
end
it "should ignore processing instructions"
parse_xml_fixture("po");
end
it "should parse mixed element and text nodes"
parse_fixture("text.mixed");
node = root->children[0];
node should have_text "foo";
node = root->children[1];
node should have_name "h1";
at(0) should have_text "bar";
node = root->children[2];
node should have_text "baz";
node = root->children[3];
node should have_name "h2";
at(0) should have_text "that";
node = root->children[4];
node should have_text "is dope";
end
it "should ignore comments"
parse_fixture("comments");
at(0) should have_text "foo";
end
it "should ignore comments when mixed with elements"
parse_fixture("comments.mixed");
root should have_n_children 2;
node = root->children[0];
node should have_name "p";
at(0) should have_text "foo";
node = root->children[1];
node should have_name "p";
at(0) should have_text "bar";
end
it "should parse CDATA sections"
parse_fixture("cdata");
node = root;
node should have_name "code";
node = at(0);
node should be_type tCDATA;
node = at(0);
node should include_text "(function(){";
node should include_text "})()";
end
it "should parse script retaining its contents"
parse_fixture("script");
node = root;
node should have_name "script";
node = at(0);
node should include_text "(function(){";
node should include_text "})()";
end
it "should parse style retaining its contents"
parse_fixture("style");
node = root;
node should have_name "style";
node = at(0);
node should include_text "body {";
node should include_text "background: url";
node should include_text "}";
end
it "should ignore doctypes"
parse_fixture("doctype");
root should have_name "html";
end
it "benchmark 200,000 elements"
bm_start;
parse_fixture("huge");
bm_stop;
end
it "benchmark 1000 elements with many text nodes"
bm_start;
parse_fixture("huge.text");
bm_stop;
end
it "benchmark 600 deep nested elements"
bm_start;
parse_fixture("huge.nested");
bm_stop;
end
it "benchmark 1000 elements with lots of attributes"
bm_start;
parse_fixture("huge.attrs");
bm_stop;
end
after_each
node = NULL;
if (fclose(fd) < 0)
perror("failed to close fixture file");
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment