Refactor: Use CStringUtils::StartsWith and CStringUtils::EndsWith
[TortoiseGit.git] / test / UnitTests / libgitTest.cpp
blobed92f0a40e8a06f71568b797a829c5c6ca15fef7
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2016-2019 - TortoiseGit
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "stdafx.h"
21 #include "Git.h"
22 #include "StringUtils.h"
23 #include "gitdll.h"
25 TEST(libgit, BrokenConfig)
27 CAutoTempDir tempdir;
28 g_Git.m_CurrentDir = tempdir.GetTempDir();
29 g_Git.m_IsGitDllInited = false;
30 g_Git.m_CurrentDir = g_Git.m_CurrentDir;
31 g_Git.m_IsUseGitDLL = true;
32 g_Git.m_IsUseLibGit2 = false;
33 g_Git.m_IsUseLibGit2_mask = 0;
34 // libgit relies on CWD being set to working tree
35 SetCurrentDirectory(g_Git.m_CurrentDir);
37 CString output;
38 EXPECT_EQ(0, g_Git.Run(L"git.exe init", &output, CP_UTF8));
39 EXPECT_STRNE(L"", output);
40 CString testFile = tempdir.GetTempDir() + L"\\.git\\config";
41 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(testFile, L"[push]\ndefault=something-that-is-invalid\n"));
43 EXPECT_THROW(g_Git.CheckAndInitDll(), const char*);
46 TEST(libgit, Mailmap)
48 CAutoTempDir tempdir;
49 g_Git.m_CurrentDir = tempdir.GetTempDir();
50 // libgit relies on CWD being set to working tree
51 SetCurrentDirectory(g_Git.m_CurrentDir);
53 GIT_MAILMAP mailmap = (void*)0x12345678;
54 git_read_mailmap(&mailmap);
55 EXPECT_EQ(nullptr, mailmap);
57 CString mailmapFile = tempdir.GetTempDir() + L"\\.mailmap";
58 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(mailmapFile, L""));
60 mailmap = (void*)0x12345678;
61 git_read_mailmap(&mailmap);
62 EXPECT_EQ(nullptr, mailmap);
64 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(mailmapFile, L"Sven Strickroth <sven@tortoisegit.org>"));
65 git_read_mailmap(&mailmap);
66 EXPECT_NE(nullptr, mailmap);
67 const char* email1 = nullptr;
68 const char* author1 = nullptr;
69 EXPECT_EQ(-1, git_lookup_mailmap(mailmap, &email1, &author1, "email@cs-ware.de", nullptr, [](void*) { return "Sven S."; }));
70 EXPECT_EQ(0, git_lookup_mailmap(mailmap, &email1, &author1, "sven@tortoisegit.org", nullptr, [](void*) { return "Sven S."; }));
71 EXPECT_EQ(nullptr, email1);
72 EXPECT_STREQ("Sven Strickroth", author1);
74 email1 = nullptr;
75 author1 = nullptr;
76 EXPECT_EQ(0, git_lookup_mailmap(mailmap, &email1, &author1, "Sven@tortoisegit.org", nullptr, [](void*) { return "Sven S."; }));
77 EXPECT_EQ(nullptr, email1);
78 EXPECT_STREQ("Sven Strickroth", author1);
80 git_free_mailmap(mailmap);
81 CString content;
82 for (auto& entry : { L"", L"1", L"2", L"A", L"4", L"5", L"b", L"7" })
83 content.AppendFormat(L"Sven%s Strickroth <sven%s@tortoisegit.org> <email%s@cs-ware.de>\n", entry, entry, entry);
84 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(mailmapFile, content));
85 git_read_mailmap(&mailmap);
86 EXPECT_NE(nullptr, mailmap);
87 email1 = nullptr;
88 author1 = nullptr;
89 EXPECT_EQ(-1, git_lookup_mailmap(mailmap, &email1, &author1, "sven@tortoisegit.org", nullptr, [](void*) { return "Sven S."; }));
90 EXPECT_EQ(-1, git_lookup_mailmap(mailmap, &email1, &author1, "aaa@tortoisegit.org", nullptr, [](void*) { return "Sven S."; }));
91 EXPECT_EQ(-1, git_lookup_mailmap(mailmap, &email1, &author1, "zzz@tortoisegit.org", nullptr, [](void*) { return "Sven S."; }));
92 for (auto& entry : { "", "1", "2", "A", "4", "5", "b", "7" })
94 CStringA maillookup, mail, name;
95 maillookup.Format("email%s@cs-ware.de", entry);
96 mail.Format("sven%s@tortoisegit.org", entry);
97 name.Format("Sven%s Strickroth", entry);
98 email1 = nullptr;
99 author1 = nullptr;
100 EXPECT_EQ(0, git_lookup_mailmap(mailmap, &email1, &author1, maillookup, nullptr, [](void*) { return "Sven S."; }));
101 EXPECT_STREQ(mail, email1);
102 EXPECT_STREQ(name, author1);
105 email1 = nullptr;
106 author1 = nullptr;
107 EXPECT_EQ(0, git_lookup_mailmap(mailmap, &email1, &author1, "email@cs-ware.de", nullptr, [](void*) { return "Sven Strickroth"; }));
108 EXPECT_STREQ("sven@tortoisegit.org", email1);
109 EXPECT_STREQ("Sven Strickroth", author1);
111 git_free_mailmap(mailmap);
112 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(mailmapFile, L"<sven@tortoisegit.org> <email@cs-ware.de>\nSven S. <sven@tortoisegit.org> Sven Strickroth <email@cs-ware.de>"));
113 git_read_mailmap(&mailmap);
114 EXPECT_NE(nullptr, mailmap);
115 email1 = nullptr;
116 author1 = nullptr;
117 EXPECT_EQ(-1, git_lookup_mailmap(mailmap, &email1, &author1, "sven@tortoisegit.org", nullptr, [](void*) { return "Sven S."; }));
118 EXPECT_EQ(-1, git_lookup_mailmap(mailmap, &email1, &author1, "aaa@tortoisegit.org", nullptr, [](void*) { return "Sven S."; }));
119 EXPECT_EQ(-1, git_lookup_mailmap(mailmap, &email1, &author1, "zzz@tortoisegit.org", nullptr, [](void*) { return "Sven S."; }));
120 EXPECT_EQ(0, git_lookup_mailmap(mailmap, &email1, &author1, "email@cs-ware.de", nullptr, [](void*) { return "Sven S."; }));
121 EXPECT_STREQ("sven@tortoisegit.org", email1);
122 EXPECT_STREQ(nullptr, author1);
123 email1 = nullptr;
124 author1 = nullptr;
125 EXPECT_EQ(0, git_lookup_mailmap(mailmap, &email1, &author1, "email@cs-ware.de", nullptr, [](void*) { return "Sven Strickroth"; }));
126 EXPECT_STREQ("sven@tortoisegit.org", email1);
127 EXPECT_STREQ("Sven S.", author1);
130 TEST(libgit, MkDir)
132 CAutoTempDir tempdir;
133 CString subdir = tempdir.GetTempDir() + L"\\abc";
135 EXPECT_FALSE(PathFileExists(subdir));
136 EXPECT_EQ(0, git_mkdir(CUnicodeUtils::GetUTF8(subdir)));
137 EXPECT_TRUE(PathFileExists(subdir));
138 EXPECT_TRUE(PathIsDirectory(subdir));
139 EXPECT_EQ(-1, git_mkdir(CUnicodeUtils::GetUTF8(subdir)));
142 TEST(libgit, RefreshIndex)
144 CAutoTempDir tempdir;
145 g_Git.m_CurrentDir = tempdir.GetTempDir();
146 g_Git.m_bInitialized = false;
147 g_Git.m_IsGitDllInited = false;
148 g_Git.m_IsUseGitDLL = true;
149 g_Git.m_IsUseLibGit2 = false;
150 g_Git.m_IsUseLibGit2_mask = 0;
152 // libgit relies on CWD being set to working tree
153 SetCurrentDirectory(g_Git.m_CurrentDir);
155 git_repository_init_options options = GIT_REPOSITORY_INIT_OPTIONS_INIT;
156 options.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
157 CAutoRepository repo;
158 ASSERT_EQ(0, git_repository_init_ext(repo.GetPointer(), CUnicodeUtils::GetUTF8(tempdir.GetTempDir()), &options));
159 CAutoConfig config(repo);
160 ASSERT_TRUE(config.IsValid());
161 CStringA path = CUnicodeUtils::GetUTF8(g_Git.m_CurrentDir);
162 path.Replace('\\', '/');
163 EXPECT_EQ(0, git_config_set_string(config, "filter.openssl.clean", path + "/clean_filter_openssl"));
164 EXPECT_EQ(0, git_config_set_string(config, "filter.openssl.smudge", path + "/smudge_filter_openssl"));
165 EXPECT_EQ(0, git_config_set_bool(config, "filter.openssl.required", 1));
166 CString cleanFilterFilename = g_Git.m_CurrentDir + L"\\clean_filter_openssl";
167 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(cleanFilterFilename, L"#!/bin/bash\nopenssl version | grep -q 1\\\\.0\nif [[ $? = 0 ]]; then\n\topenssl enc -base64 -aes-256-ecb -S FEEDDEADBEEF -k PASS_FIXED\nelse\n\topenssl enc -base64 -pbkdf2 -aes-256-ecb -S FEEDDEADBEEFFEED -k PASS_FIXED\nfi\n"));
168 CString smudgeFilterFilename = g_Git.m_CurrentDir + L"\\smudge_filter_openssl";
169 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(smudgeFilterFilename, L"#!/bin/bash\nopenssl version | grep -q 1\\\\.0\nif [[ $? = 0 ]]; then\n\topenssl enc -d -base64 -aes-256-ecb -k PASS_FIXED\nelse\n\topenssl enc -d -base64 -pbkdf2 -aes-256-ecb -k PASS_FIXED\nfi\n"));
170 EXPECT_EQ(0, git_config_set_string(config, "filter.test.clean", path + "/clean_filter_openssl"));
171 EXPECT_EQ(0, git_config_set_string(config, "filter.test.smudge", path + "/smudge_filter_openssl"));
172 EXPECT_EQ(0, git_config_set_string(config, "filter.test.process", path + "/clean_filter_openssl"));
173 EXPECT_EQ(0, git_config_set_bool(config, "filter.test.required", 1));
175 // need to make sure sh.exe is on PATH
176 g_Git.CheckMsysGitDir();
177 size_t size;
178 _wgetenv_s(&size, nullptr, 0, L"PATH");
179 ASSERT_LT(0U, size);
180 auto oldEnv = std::make_unique<wchar_t[]>(size);
181 ASSERT_TRUE(oldEnv);
182 _wgetenv_s(&size, oldEnv.get(), size, L"PATH");
183 _wputenv_s(L"PATH", g_Git.m_Environment.GetEnv(L"PATH"));
184 SCOPE_EXIT { _wputenv_s(L"PATH", oldEnv.get()); };
185 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(g_Git.m_CurrentDir + L"\\somefile.txt", L"some content"));
187 g_Git.RefreshGitIndex();
189 CString output;
190 EXPECT_EQ(0, g_Git.Run(L"git.exe add somefile.txt", &output, CP_UTF8));
191 EXPECT_STREQ(L"", output);
193 g_Git.RefreshGitIndex();
195 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(g_Git.m_CurrentDir + L"\\somefile.txt", L"some other content"));
197 g_Git.RefreshGitIndex();
199 output.Empty();
200 EXPECT_EQ(0, g_Git.Run(L"git.exe add somefile.txt", &output, CP_UTF8));
201 EXPECT_STREQ(L"", output);
203 g_Git.RefreshGitIndex();
205 // now check with external command filters defined
206 CString attributesFile = g_Git.m_CurrentDir + L"\\.gitattributes";
207 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(attributesFile, L"*.enc filter=openssl\n"));
209 CString encryptedFileOne = g_Git.m_CurrentDir + L"\\1.enc";
210 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(encryptedFileOne, L"This should be encrypted...\nAnd decrypted on the fly\n"));
212 output.Empty();
213 EXPECT_EQ(0, g_Git.Run(L"git.exe add 1.enc", &output, CP_UTF8));
214 if (!g_Git.ms_bCygwinGit) // on AppVeyor with the VS2017 image we get a warning: "WARNING: can't open config file: /usr/local/ssl/openssl.cnf"
215 EXPECT_STREQ(L"", output);
217 WIN32_FILE_ATTRIBUTE_DATA fdata;
218 GetFileAttributesEx(g_Git.m_CurrentDir + L"\\.git\\index", GetFileExInfoStandard, &fdata);
220 g_Git.RefreshGitIndex();
222 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(g_Git.m_CurrentDir + L"\\1.enc", L"some other content"));
224 g_Git.RefreshGitIndex();
226 // need racy timestamp
227 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(g_Git.m_CurrentDir + L"\\1.enc", L"somE other content"));
229 CAutoGeneralHandle handle = ::CreateFile(g_Git.m_CurrentDir + L"\\1.enc", FILE_WRITE_ATTRIBUTES, 0, nullptr, 0, 0, nullptr);
230 SetFileTime(handle, &fdata.ftCreationTime, &fdata.ftLastAccessTime, &fdata.ftLastWriteTime);
233 g_Git.RefreshGitIndex();
235 // now check with external command filters with multi-filter (process) defined
236 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(attributesFile, L"*.enc filter=test\n"));
238 g_Git.RefreshGitIndex();
240 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(g_Git.m_CurrentDir + L"\\1.enc", L"somE other conTentsome other conTentsome other conTen"));
242 g_Git.RefreshGitIndex();
244 // need racy timestamp
245 GetFileAttributesEx(g_Git.m_CurrentDir + L"\\.git\\index", GetFileExInfoStandard, &fdata);
246 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(g_Git.m_CurrentDir + L"\\1.enc", L"some other conTentsome other conTentsome other conTen"));
248 CAutoGeneralHandle handle = ::CreateFile(g_Git.m_CurrentDir + L"\\1.enc", FILE_WRITE_ATTRIBUTES, 0, nullptr, 0, 0, nullptr);
249 SetFileTime(handle, &fdata.ftCreationTime, &fdata.ftLastAccessTime, &fdata.ftLastWriteTime);
252 g_Git.RefreshGitIndex();
255 TEST(libgit, IncludeIf)
257 CAutoTempDir tempdir;
258 g_Git.m_bInitialized = false;
259 g_Git.m_IsGitDllInited = false;
260 g_Git.m_IsUseGitDLL = true;
261 g_Git.m_IsUseLibGit2 = false;
262 g_Git.m_IsUseLibGit2_mask = 0;
264 // .git dir
265 CString repoDir = tempdir.GetTempDir() + L"\\RepoWithAInPath";
266 g_Git.m_CurrentDir = repoDir;
267 EXPECT_TRUE(CreateDirectory(repoDir, nullptr));
268 // libgit relies on CWD being set to working tree
269 EXPECT_TRUE(SetCurrentDirectory(repoDir));
271 git_repository_init_options options = GIT_REPOSITORY_INIT_OPTIONS_INIT;
272 options.flags = GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
273 CAutoRepository repo;
274 ASSERT_EQ(0, git_repository_init_ext(repo.GetPointer(), CUnicodeUtils::GetUTF8(repoDir), &options));
276 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(repoDir + L"\\.git\\config", L"[core]\n repositoryformatversion = 0\n filemode = false\n bare = false\n logallrefupdates = true\n symlinks = false\n ignorecase = true\n hideDotFiles = dotGitOnly\n[something]\n thevalue = jap\n[includeIf \"gitdir:RepoWithAInPath/**\"]\n path = configA\n[includeIf \"gitdir:RepoWithBInPath/**\"]\n path = configB\n"));
277 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(repoDir + L"\\.git\\configA", L"[somethinga]\n thevalue = jop\n"));
278 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(repoDir + L"\\.git\\configB", L"[somethingb]\n thevalue = jup\n"));
280 EXPECT_STREQ(L"jap", g_Git.GetConfigValue(L"something.thevalue"));
281 EXPECT_STREQ(L"jop",g_Git.GetConfigValue(L"somethinga.thevalue"));
282 EXPECT_STREQ(L"", g_Git.GetConfigValue(L"somethingb.thevalue"));
284 // .git file
285 g_Git.m_bInitialized = false;
286 g_Git.m_IsGitDllInited = false;
287 g_Git.m_IsUseGitDLL = true;
288 repoDir = tempdir.GetTempDir() + L"\\RepoWithBInPath";
289 g_Git.m_CurrentDir = repoDir;
290 EXPECT_TRUE(CreateDirectory(repoDir, nullptr));
291 // libgit relies on CWD being set to working tree
292 EXPECT_TRUE(SetCurrentDirectory(repoDir));
293 EXPECT_TRUE(CStringUtils::WriteStringToTextFile(repoDir + L"\\.git", L"gitdir: ../RepoWithAInPath/.git\n"));
295 EXPECT_STREQ(L"jap", g_Git.GetConfigValue(L"something.thevalue"));
296 EXPECT_STREQ(L"jop", g_Git.GetConfigValue(L"somethinga.thevalue"));
297 EXPECT_STREQ(L"", g_Git.GetConfigValue(L"somethingb.thevalue"));
300 TEST(libgit, StoreUninitializedRepositoryConfig)
302 CAutoTempDir tempdir;
303 g_Git.m_CurrentDir = tempdir.GetTempDir();
304 g_Git.m_IsGitDllInited = false;
305 g_Git.m_CurrentDir = g_Git.m_CurrentDir;
306 g_Git.m_IsUseGitDLL = true;
307 g_Git.m_IsUseLibGit2 = false;
308 g_Git.m_IsUseLibGit2_mask = 0;
309 // libgit relies on CWD being set to working tree
310 SetCurrentDirectory(g_Git.m_CurrentDir);
312 // clear any leftovers in caches
313 EXPECT_THROW(g_Git.CheckAndInitDll(), const char*);
315 EXPECT_THROW(get_set_config("something", "else", CONFIG_LOCAL), const char*);