Commit 4c738e563d0a52c7f06902a6bdac37fe3472b86b

Patrick Steinhardt 2018-10-19T09:44:14

tests: add tests that exercise tag parsing While the tests in object::tag::read exercises reading and parsing valid tags from the ODB, they barely try to verify that the parser fails in a sane way when parsing invalid tags. Create a new test suite object::tag::parse that directly exercise the parser by using `git_object__from_raw` and add various tests for valid and invalid tags.

diff --git a/tests/object/tag/parse.c b/tests/object/tag/parse.c
new file mode 100644
index 0000000..7e58ed1
--- /dev/null
+++ b/tests/object/tag/parse.c
@@ -0,0 +1,200 @@
+#include "clar_libgit2.h"
+#include "object.h"
+#include "signature.h"
+#include "tag.h"
+
+static void assert_tag_parses(const char *data, size_t datalen,
+	const char *expected_oid,
+	const char *expected_name,
+	const char *expected_tagger,
+	const char *expected_message)
+{
+	git_tag *tag;
+
+	if (!datalen)
+		datalen = strlen(data);
+
+	cl_git_pass(git_object__from_raw((git_object **) &tag, data, datalen, GIT_OBJ_TAG));
+	cl_assert_equal_i(tag->type, GIT_OBJ_TAG);
+
+	if (expected_oid) {
+		git_oid oid;
+		cl_git_pass(git_oid_fromstr(&oid, expected_oid));
+		cl_assert_equal_oid(&oid, &tag->target);
+	}
+
+	if (expected_name)
+		cl_assert_equal_s(expected_name, tag->tag_name);
+	else
+		cl_assert_equal_s(tag->message, NULL);
+
+	if (expected_tagger) {
+		git_signature *tagger;
+		cl_git_pass(git_signature_from_buffer(&tagger, expected_tagger));
+		cl_assert_equal_s(tagger->name, tag->tagger->name);
+		cl_assert_equal_s(tagger->email, tag->tagger->email);
+		cl_assert_equal_i(tagger->when.time, tag->tagger->when.time);
+		cl_assert_equal_i(tagger->when.offset, tag->tagger->when.offset);
+		cl_assert_equal_i(tagger->when.sign, tag->tagger->when.sign);
+		git_signature_free(tagger);
+	} else {
+		cl_assert_equal_s(tag->tagger, NULL);
+	}
+
+	if (expected_message)
+		cl_assert_equal_s(expected_message, tag->message);
+	else
+		cl_assert_equal_s(tag->message, NULL);
+
+	git_object__free(&tag->object);
+}
+
+static void assert_tag_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_TAG));
+}
+
+void test_object_tag_parse__valid_tag_parses(void)
+{
+	const char *tag =
+		"object a8d447f68076d1520f69649bb52629941be7031f\n"
+		"type tag\n"
+		"tag tagname\n"
+		"tagger Taggy Mr. Taggart <taggy@taggart.com>\n"
+		"\n"
+		"Message";
+	assert_tag_parses(tag, 0,
+		"a8d447f68076d1520f69649bb52629941be7031f",
+		"tagname",
+		"Taggy Mr. Taggart <taggy@taggart.com>",
+		"Message");
+}
+
+void test_object_tag_parse__missing_tagger_parses(void)
+{
+	const char *tag =
+		"object a8d447f68076d1520f69649bb52629941be7031f\n"
+		"type tag\n"
+		"tag tagname\n"
+		"\n"
+		"Message";
+	assert_tag_parses(tag, 0,
+		"a8d447f68076d1520f69649bb52629941be7031f",
+		"tagname",
+		NULL,
+		"Message");
+}
+
+void test_object_tag_parse__missing_message_parses(void)
+{
+	const char *tag =
+		"object a8d447f68076d1520f69649bb52629941be7031f\n"
+		"type tag\n"
+		"tag tagname\n"
+		"tagger Taggy Mr. Taggart <taggy@taggart.com>\n";
+	assert_tag_parses(tag, 0,
+		"a8d447f68076d1520f69649bb52629941be7031f",
+		"tagname",
+		"Taggy Mr. Taggart <taggy@taggart.com>",
+		NULL);
+}
+
+void test_object_tag_parse__unknown_field_parses(void)
+{
+	const char *tag =
+		"object a8d447f68076d1520f69649bb52629941be7031f\n"
+		"type tag\n"
+		"tag tagname\n"
+		"tagger Taggy Mr. Taggart <taggy@taggart.com>\n"
+		"foo bar\n"
+		"frubble frabble\n"
+		"\n"
+		"Message";
+	assert_tag_parses(tag, 0,
+		"a8d447f68076d1520f69649bb52629941be7031f",
+		"tagname",
+		"Taggy Mr. Taggart <taggy@taggart.com>",
+		"Message");
+}
+
+void test_object_tag_parse__missing_object_fails(void)
+{
+	const char *tag =
+		"type tag\n"
+		"tag tagname\n"
+		"tagger Taggy Mr. Taggart <taggy@taggart.com>\n"
+		"\n"
+		"Message";
+	assert_tag_fails(tag, 0);
+}
+
+void test_object_tag_parse__malformatted_object_fails(void)
+{
+	const char *tag =
+		"object a8d447f68076d15xxxxxxxxxxxxxxxx41be7031f\n"
+		"type tag\n"
+		"tag tagname\n"
+		"tagger Taggy Mr. Taggart <taggy@taggart.com>\n"
+		"\n"
+		"Message";
+	assert_tag_fails(tag, 0);
+}
+
+void test_object_tag_parse__missing_type_fails(void)
+{
+	const char *tag =
+		"object a8d447f68076d1520f69649bb52629941be7031f\n"
+		"tag tagname\n"
+		"tagger Taggy Mr. Taggart <taggy@taggart.com>\n"
+		"\n"
+		"Message";
+	assert_tag_fails(tag, 0);
+}
+
+void test_object_tag_parse__invalid_type_fails(void)
+{
+	const char *tag =
+		"object a8d447f68076d1520f69649bb52629941be7031f\n"
+		"type garbage\n"
+		"tag tagname\n"
+		"tagger Taggy Mr. Taggart <taggy@taggart.com>\n"
+		"\n"
+		"Message";
+	assert_tag_fails(tag, 0);
+}
+
+void test_object_tag_parse__missing_tagname_fails(void)
+{
+	const char *tag =
+		"object a8d447f68076d1520f69649bb52629941be7031f\n"
+		"type tag\n"
+		"tagger Taggy Mr. Taggart <taggy@taggart.com>\n"
+		"\n"
+		"Message";
+	assert_tag_fails(tag, 0);
+}
+
+void test_object_tag_parse__misformatted_tagger_fails(void)
+{
+	const char *tag =
+		"object a8d447f68076d1520f69649bb52629941be7031f\n"
+		"type tag\n"
+		"tag Tag\n"
+		"tagger taggy@taggart.com>\n"
+		"\n"
+		"Message";
+	assert_tag_fails(tag, 0);
+}
+
+void test_object_tag_parse__missing_message_fails(void)
+{
+	const char *tag =
+		"object a8d447f68076d1520f69649bb52629941be7031f\n"
+		"type tag\n"
+		"tag Tag\n"
+		"tagger taggy@taggart.com>\n";
+	assert_tag_fails(tag, 0);
+}