mirror of
				https://git.proxmox.com/git/libgit2
				synced 2025-10-31 09:30:46 +00:00 
			
		
		
		
	 4afe536ba1
			
		
	
	
		4afe536ba1
		
	
	
	
	
		
			
			Use legitimate (existing) object IDs in tests so that we have the ability to turn on strict object validation when running tests.
		
			
				
	
	
		
			259 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			259 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "clar_libgit2.h"
 | |
| #include "buffer.h"
 | |
| #include "posix.h"
 | |
| #include "index.h"
 | |
| 
 | |
| static git_repository *g_repo = NULL;
 | |
| 
 | |
| void test_index_filemodes__initialize(void)
 | |
| {
 | |
| 	g_repo = cl_git_sandbox_init("filemodes");
 | |
| }
 | |
| 
 | |
| void test_index_filemodes__cleanup(void)
 | |
| {
 | |
| 	cl_git_sandbox_cleanup();
 | |
| }
 | |
| 
 | |
| void test_index_filemodes__read(void)
 | |
| {
 | |
| 	git_index *index;
 | |
| 	unsigned int i;
 | |
| 	static bool expected[6] = { 0, 1, 0, 1, 0, 1 };
 | |
| 
 | |
| 	cl_git_pass(git_repository_index(&index, g_repo));
 | |
| 	cl_assert_equal_i(6, (int)git_index_entrycount(index));
 | |
| 
 | |
| 	for (i = 0; i < 6; ++i) {
 | |
| 		const git_index_entry *entry = git_index_get_byindex(index, i);
 | |
| 		cl_assert(entry != NULL);
 | |
| 		cl_assert(((entry->mode & 0100) ? 1 : 0) == expected[i]);
 | |
| 	}
 | |
| 
 | |
| 	git_index_free(index);
 | |
| }
 | |
| 
 | |
| static void replace_file_with_mode(
 | |
| 	const char *filename, const char *backup, unsigned int create_mode)
 | |
| {
 | |
| 	git_buf path = GIT_BUF_INIT, content = GIT_BUF_INIT;
 | |
| 
 | |
| 	cl_git_pass(git_buf_joinpath(&path, "filemodes", filename));
 | |
| 	cl_git_pass(git_buf_printf(&content, "%s as %08u (%d)",
 | |
| 		filename, create_mode, rand()));
 | |
| 
 | |
| 	cl_git_pass(p_rename(path.ptr, backup));
 | |
| 	cl_git_write2file(
 | |
| 		path.ptr, content.ptr, content.size,
 | |
| 		O_WRONLY|O_CREAT|O_TRUNC, create_mode);
 | |
| 
 | |
| 	git_buf_free(&path);
 | |
| 	git_buf_free(&content);
 | |
| }
 | |
| 
 | |
| #define add_and_check_mode(I,F,X) add_and_check_mode_(I,F,X,__FILE__,__LINE__)
 | |
| 
 | |
| static void add_and_check_mode_(
 | |
| 	git_index *index, const char *filename, unsigned int expect_mode,
 | |
| 	const char *file, int line)
 | |
| {
 | |
| 	size_t pos;
 | |
| 	const git_index_entry *entry;
 | |
| 
 | |
| 	cl_git_pass(git_index_add_bypath(index, filename));
 | |
| 
 | |
| 	clar__assert(!git_index_find(&pos, index, filename),
 | |
| 		file, line, "Cannot find index entry", NULL, 1);
 | |
| 
 | |
| 	entry = git_index_get_byindex(index, pos);
 | |
| 
 | |
| 	clar__assert_equal(file, line, "Expected mode does not match index",
 | |
| 		1, "%07o", (unsigned int)entry->mode, (unsigned int)expect_mode);
 | |
| }
 | |
| 
 | |
| void test_index_filemodes__untrusted(void)
 | |
| {
 | |
| 	git_index *index;
 | |
| 
 | |
| 	cl_repo_set_bool(g_repo, "core.filemode", false);
 | |
| 
 | |
| 	cl_git_pass(git_repository_index(&index, g_repo));
 | |
| 	cl_assert((git_index_caps(index) & GIT_INDEXCAP_NO_FILEMODE) != 0);
 | |
| 
 | |
| 	/* 1 - add 0644 over existing 0644 -> expect 0644 */
 | |
| 	replace_file_with_mode("exec_off", "filemodes/exec_off.0", 0644);
 | |
| 	add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB);
 | |
| 
 | |
| 	/* 2 - add 0644 over existing 0755 -> expect 0755 */
 | |
| 	replace_file_with_mode("exec_on", "filemodes/exec_on.0", 0644);
 | |
| 	add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE);
 | |
| 
 | |
| 	/* 3 - add 0755 over existing 0644 -> expect 0644 */
 | |
| 	replace_file_with_mode("exec_off", "filemodes/exec_off.1", 0755);
 | |
| 	add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB);
 | |
| 
 | |
| 	/* 4 - add 0755 over existing 0755 -> expect 0755 */
 | |
| 	replace_file_with_mode("exec_on", "filemodes/exec_on.1", 0755);
 | |
| 	add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE);
 | |
| 
 | |
| 	/*  5 - add new 0644 -> expect 0644 */
 | |
| 	cl_git_write2file("filemodes/new_off", "blah", 0,
 | |
| 		O_WRONLY | O_CREAT | O_TRUNC, 0644);
 | |
| 	add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB);
 | |
| 
 | |
| 	/* 6 - add new 0755 -> expect 0644 if core.filemode == false */
 | |
| 	cl_git_write2file("filemodes/new_on", "blah", 0,
 | |
| 		O_WRONLY | O_CREAT | O_TRUNC, 0755);
 | |
| 	add_and_check_mode(index, "new_on", GIT_FILEMODE_BLOB);
 | |
| 
 | |
| 	git_index_free(index);
 | |
| }
 | |
| 
 | |
| void test_index_filemodes__trusted(void)
 | |
| {
 | |
| 	git_index *index;
 | |
| 
 | |
| 	/* Only run these tests on platforms where I can actually
 | |
| 	 * chmod a file and get the stat results I expect!
 | |
| 	 */
 | |
| 	if (!cl_is_chmod_supported())
 | |
| 		return;
 | |
| 
 | |
| 	cl_repo_set_bool(g_repo, "core.filemode", true);
 | |
| 
 | |
| 	cl_git_pass(git_repository_index(&index, g_repo));
 | |
| 	cl_assert((git_index_caps(index) & GIT_INDEXCAP_NO_FILEMODE) == 0);
 | |
| 
 | |
| 	/* 1 - add 0644 over existing 0644 -> expect 0644 */
 | |
| 	replace_file_with_mode("exec_off", "filemodes/exec_off.0", 0644);
 | |
| 	add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB);
 | |
| 
 | |
| 	/* 2 - add 0644 over existing 0755 -> expect 0644 */
 | |
| 	replace_file_with_mode("exec_on", "filemodes/exec_on.0", 0644);
 | |
| 	add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB);
 | |
| 
 | |
| 	/* 3 - add 0755 over existing 0644 -> expect 0755 */
 | |
| 	replace_file_with_mode("exec_off", "filemodes/exec_off.1", 0755);
 | |
| 	add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB_EXECUTABLE);
 | |
| 
 | |
| 	/* 4 - add 0755 over existing 0755 -> expect 0755 */
 | |
| 	replace_file_with_mode("exec_on", "filemodes/exec_on.1", 0755);
 | |
| 	add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE);
 | |
| 
 | |
| 	/*  5 - add new 0644 -> expect 0644 */
 | |
| 	cl_git_write2file("filemodes/new_off", "blah", 0,
 | |
| 		O_WRONLY | O_CREAT | O_TRUNC, 0644);
 | |
| 	add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB);
 | |
| 
 | |
| 	/* 6 - add 0755 -> expect 0755 */
 | |
| 	cl_git_write2file("filemodes/new_on", "blah", 0,
 | |
| 		O_WRONLY | O_CREAT | O_TRUNC, 0755);
 | |
| 	add_and_check_mode(index, "new_on", GIT_FILEMODE_BLOB_EXECUTABLE);
 | |
| 
 | |
| 	git_index_free(index);
 | |
| }
 | |
| 
 | |
| #define add_entry_and_check_mode(I,FF,X) add_entry_and_check_mode_(I,FF,X,__FILE__,__LINE__)
 | |
| 
 | |
| static void add_entry_and_check_mode_(
 | |
| 	git_index *index, bool from_file, git_filemode_t mode,
 | |
| 	const char *file, int line)
 | |
| {
 | |
| 	size_t pos;
 | |
| 	const git_index_entry* entry;
 | |
| 	git_index_entry new_entry;
 | |
| 
 | |
| 	/* If old_filename exists, we copy that to the new file, and test
 | |
| 	 * git_index_add(), otherwise create a new entry testing git_index_add_frombuffer
 | |
| 	 */
 | |
| 	if (from_file)
 | |
| 	{
 | |
| 		clar__assert(!git_index_find(&pos, index, "exec_off"),
 | |
| 			file, line, "Cannot find original index entry", NULL, 1);
 | |
| 
 | |
| 		entry = git_index_get_byindex(index, pos);
 | |
| 
 | |
| 		memcpy(&new_entry, entry, sizeof(new_entry));
 | |
| 	}
 | |
| 	else
 | |
| 		memset(&new_entry, 0x0, sizeof(git_index_entry));
 | |
| 
 | |
| 	new_entry.path = "filemodes/explicit_test";
 | |
| 	new_entry.mode = mode;
 | |
| 
 | |
| 	if (from_file)
 | |
| 	{
 | |
| 		clar__assert(!git_index_add(index, &new_entry),
 | |
| 			file, line, "Cannot add index entry", NULL, 1);
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		const char *content = "hey there\n";
 | |
| 		clar__assert(!git_index_add_frombuffer(index, &new_entry, content, strlen(content)),
 | |
| 			file, line, "Cannot add index entry from buffer", NULL, 1);
 | |
| 	}
 | |
| 
 | |
| 	clar__assert(!git_index_find(&pos, index, "filemodes/explicit_test"),
 | |
| 		file, line, "Cannot find new index entry", NULL, 1);
 | |
| 
 | |
| 	entry = git_index_get_byindex(index, pos);
 | |
| 
 | |
| 	clar__assert_equal(file, line, "Expected mode does not match index",
 | |
| 		1, "%07o", (unsigned int)entry->mode, (unsigned int)mode);
 | |
| }
 | |
| 
 | |
| void test_index_filemodes__explicit(void)
 | |
| {
 | |
| 	git_index *index;
 | |
| 
 | |
| 	/* These tests should run and work everywhere, as the filemode is
 | |
| 	 * given explicitly to git_index_add or git_index_add_frombuffer
 | |
| 	 */
 | |
| 	cl_repo_set_bool(g_repo, "core.filemode", false);
 | |
| 
 | |
| 	cl_git_pass(git_repository_index(&index, g_repo));
 | |
| 
 | |
| 	/* Each of these tests keeps overwriting the same file in the index. */
 | |
| 	/* 1 - add new 0644 entry  */
 | |
| 	add_entry_and_check_mode(index, true, GIT_FILEMODE_BLOB);
 | |
| 
 | |
| 	/* 2 - add 0755 entry over existing 0644 */
 | |
| 	add_entry_and_check_mode(index, true, GIT_FILEMODE_BLOB_EXECUTABLE);
 | |
| 
 | |
| 	/* 3 - add 0644 entry over existing 0755 */
 | |
| 	add_entry_and_check_mode(index, true, GIT_FILEMODE_BLOB);
 | |
| 
 | |
| 	/* 4 - add 0755 buffer entry over existing 0644  */
 | |
| 	add_entry_and_check_mode(index, false, GIT_FILEMODE_BLOB_EXECUTABLE);
 | |
| 
 | |
| 	/* 5 - add 0644 buffer entry over existing 0755 */
 | |
| 	add_entry_and_check_mode(index, false, GIT_FILEMODE_BLOB);
 | |
| 
 | |
| 	git_index_free(index);
 | |
| }
 | |
| 
 | |
| void test_index_filemodes__invalid(void)
 | |
| {
 | |
| 	git_index *index;
 | |
| 	git_index_entry entry;
 | |
| 	const git_index_entry *dummy;
 | |
| 
 | |
| 	cl_git_pass(git_repository_index(&index, g_repo));
 | |
| 
 | |
| 	/* add a dummy file so that we have a valid id */
 | |
| 	cl_git_mkfile("./filemodes/dummy-file.txt", "new-file\n");
 | |
| 	cl_git_pass(git_index_add_bypath(index, "dummy-file.txt"));
 | |
| 	cl_assert((dummy = git_index_get_bypath(index, "dummy-file.txt", 0)));
 | |
| 
 | |
| 	GIT_IDXENTRY_STAGE_SET(&entry, 0);
 | |
| 	entry.path = "foo";
 | |
| 	entry.mode = GIT_OBJ_BLOB;
 | |
| 	git_oid_cpy(&entry.id, &dummy->id);
 | |
| 	cl_git_fail(git_index_add(index, &entry));
 | |
| 
 | |
| 	entry.mode = GIT_FILEMODE_BLOB;
 | |
| 	cl_git_pass(git_index_add(index, &entry));
 | |
| 
 | |
| 	git_index_free(index);
 | |
| }
 |