Commit d4ad658a6917de6853088a811d058a64f070c217

Patrick Steinhardt 2018-10-29T17:24:47

tree: add various tests exercising the tree parser We currently don't have any tests that directly exercise the tree parser. This is due to the fact that the parsers for raw object data has only been recently introduce with commit ca4db5f4a (object: implement function to parse raw data, 2017-10-13), and previous to that the setup simply was too cumbersome as it always required going through the ODB. Now that we have the infrastructure, add a suite of tests that directly exercise the tree parser and various edge cases.

diff --git a/tests/object/tree/parse.c b/tests/object/tree/parse.c
new file mode 100644
index 0000000..6ac3a2d
--- /dev/null
+++ b/tests/object/tree/parse.c
@@ -0,0 +1,146 @@
+#include "clar_libgit2.h"
+#include "tree.h"
+#include "object.h"
+
+#define OID1_HEX \
+	"\xae\x90\xf1\x2e\xea\x69\x97\x29\xed\x24" \
+	"\x55\x5e\x40\xb9\xfd\x66\x9d\xa1\x2a\x12"
+#define OID1_STR "ae90f12eea699729ed24555e40b9fd669da12a12"
+
+#define OID2_HEX \
+	"\xe8\xbf\xe5\xaf\x39\x57\x9a\x7e\x48\x98" \
+	"\xbb\x23\xf3\xa7\x6a\x72\xc3\x68\xce\xe6"
+#define OID2_STR "e8bfe5af39579a7e4898bb23f3a76a72c368cee6"
+
+typedef struct {
+	const char *filename;
+	uint16_t attr;
+	const char *oid;
+} expected_entry;
+
+static void assert_tree_parses(const char *data, size_t datalen,
+	expected_entry *expected_entries, size_t expected_nentries)
+{
+	git_tree *tree;
+	size_t n;
+
+	if (!datalen)
+		datalen = strlen(data);
+	cl_git_pass(git_object__from_raw((git_object **) &tree, data, datalen, GIT_OBJ_TREE));
+
+	cl_assert_equal_i(git_tree_entrycount(tree), expected_nentries);
+
+	for (n = 0; n < expected_nentries; n++) {
+		expected_entry *expected = expected_entries + n;
+		const git_tree_entry *entry;
+		git_oid oid;
+
+		cl_git_pass(git_oid_fromstr(&oid, expected->oid));
+
+		cl_assert(entry = git_tree_entry_byname(tree, expected->filename));
+		cl_assert_equal_s(expected->filename, entry->filename);
+		cl_assert_equal_i(expected->attr, entry->attr);
+		cl_assert_equal_oid(&oid, entry->oid);
+	}
+
+	git_object_free(&tree->object);
+}
+
+static void assert_tree_fails(const char *data, size_t datalen)
+{
+	git_object *object;
+	if (!datalen)
+		datalen = strlen(data);
+	cl_git_fail(git_object__from_raw(&object, data, datalen, GIT_OBJ_TREE));
+}
+
+void test_object_tree_parse__single_blob_parses(void)
+{
+	expected_entry entries[] = {
+		{ "foo", 0100644, OID1_STR },
+	};
+	const char data[] = "100644 foo\x00" OID1_HEX;
+
+	assert_tree_parses(data, ARRAY_SIZE(data) - 1, entries, ARRAY_SIZE(entries));
+}
+
+void test_object_tree_parse__single_tree_parses(void)
+{
+	expected_entry entries[] = {
+		{ "foo", 040000, OID1_STR },
+	};
+	const char data[] = "040000 foo\x00" OID1_HEX;
+
+	assert_tree_parses(data, ARRAY_SIZE(data) - 1, entries, ARRAY_SIZE(entries));
+}
+
+void test_object_tree_parse__leading_filename_spaces_parse(void)
+{
+	expected_entry entries[] = {
+		{ "       bar", 0100644, OID1_STR },
+	};
+	const char data[] = "100644        bar\x00" OID1_HEX;
+
+	assert_tree_parses(data, ARRAY_SIZE(data) - 1, entries, ARRAY_SIZE(entries));
+}
+
+void test_object_tree_parse__multiple_entries_parse(void)
+{
+	expected_entry entries[] = {
+		{ "bar", 0100644, OID1_STR },
+		{ "foo", 040000,  OID2_STR },
+	};
+	const char data[] =
+	    "100644 bar\x00" OID1_HEX
+	    "040000 foo\x00" OID2_HEX;
+
+	assert_tree_parses(data, ARRAY_SIZE(data) - 1, entries, ARRAY_SIZE(entries));
+}
+
+void test_object_tree_parse__invalid_mode_fails(void)
+{
+	const char data[] = "10x644 bar\x00" OID1_HEX;
+	assert_tree_fails(data, ARRAY_SIZE(data) - 1);
+}
+
+void test_object_tree_parse__missing_mode_fails(void)
+{
+	const char data[] = " bar\x00" OID1_HEX;
+	assert_tree_fails(data, ARRAY_SIZE(data) - 1);
+}
+
+void test_object_tree_parse__missing_filename_separator_fails(void)
+{
+	const char data[] = "100644bar\x00" OID1_HEX;
+	assert_tree_fails(data, ARRAY_SIZE(data) - 1);
+}
+
+void test_object_tree_parse__missing_filename_terminator_fails(void)
+{
+	const char data[] = "100644 bar" OID1_HEX;
+	assert_tree_fails(data, ARRAY_SIZE(data) - 1);
+}
+
+void test_object_tree_parse__empty_filename_fails(void)
+{
+	const char data[] = "100644 \x00" OID1_HEX;
+	assert_tree_fails(data, ARRAY_SIZE(data) - 1);
+}
+
+void test_object_tree_parse__trailing_garbage_fails(void)
+{
+	const char data[] = "100644 bar\x00" OID1_HEX "x";
+	assert_tree_fails(data, ARRAY_SIZE(data) - 1);
+}
+
+void test_object_tree_parse__leading_space_fails(void)
+{
+	const char data[] = " 100644 bar\x00" OID1_HEX;
+	assert_tree_fails(data, ARRAY_SIZE(data) - 1);
+}
+
+void test_object_tree_parse__truncated_oid_fails(void)
+{
+	const char data[] = " 100644 bar\x00" OID1_HEX;
+	assert_tree_fails(data, ARRAY_SIZE(data) - 2);
+}