gitea源码

wiki_test.go 9.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package wiki
  4. import (
  5. "math/rand"
  6. "strings"
  7. "testing"
  8. repo_model "code.gitea.io/gitea/models/repo"
  9. "code.gitea.io/gitea/models/unittest"
  10. user_model "code.gitea.io/gitea/models/user"
  11. "code.gitea.io/gitea/modules/git"
  12. "code.gitea.io/gitea/modules/gitrepo"
  13. repo_service "code.gitea.io/gitea/services/repository"
  14. _ "code.gitea.io/gitea/models/actions"
  15. "github.com/stretchr/testify/assert"
  16. "github.com/stretchr/testify/require"
  17. )
  18. func TestMain(m *testing.M) {
  19. unittest.MainTest(m)
  20. }
  21. func TestWebPathSegments(t *testing.T) {
  22. a := WebPathSegments("a%2Fa/b+c/d-e/f-g.-")
  23. assert.Equal(t, []string{"a/a", "b c", "d e", "f-g"}, a)
  24. }
  25. func TestUserTitleToWebPath(t *testing.T) {
  26. type test struct {
  27. Expected string
  28. UserTitle string
  29. }
  30. for _, test := range []test{
  31. {"unnamed", ""},
  32. {"unnamed", "."},
  33. {"unnamed", ".."},
  34. {"wiki-name", "wiki name"},
  35. {"title.md.-", "title.md"},
  36. {"wiki-name.-", "wiki-name"},
  37. {"the+wiki-name.-", "the wiki-name"},
  38. {"a%2Fb", "a/b"},
  39. {"a%25b", "a%b"},
  40. } {
  41. assert.EqualValues(t, test.Expected, UserTitleToWebPath("", test.UserTitle))
  42. }
  43. }
  44. func TestWebPathToDisplayName(t *testing.T) {
  45. type test struct {
  46. Expected string
  47. WebPath WebPath
  48. }
  49. for _, test := range []test{
  50. {"wiki name", "wiki-name"},
  51. {"wiki-name", "wiki-name.-"},
  52. {"name with / slash", "name-with %2F slash"},
  53. {"name with % percent", "name-with %25 percent"},
  54. {"2000-01-02 meeting", "2000-01-02+meeting.-.md"},
  55. {"a b", "a%20b.md"},
  56. } {
  57. _, displayName := WebPathToUserTitle(test.WebPath)
  58. assert.Equal(t, test.Expected, displayName)
  59. }
  60. }
  61. func TestWebPathToGitPath(t *testing.T) {
  62. type test struct {
  63. Expected string
  64. WikiName WebPath
  65. }
  66. for _, test := range []test{
  67. {"wiki-name.md", "wiki%20name"},
  68. {"wiki-name.md", "wiki+name"},
  69. {"wiki name.md", "wiki%20name.md"},
  70. {"wiki%20name.md", "wiki%2520name.md"},
  71. {"2000-01-02-meeting.md", "2000-01-02+meeting"},
  72. {"2000-01-02 meeting.-.md", "2000-01-02%20meeting.-"},
  73. } {
  74. assert.Equal(t, test.Expected, WebPathToGitPath(test.WikiName))
  75. }
  76. }
  77. func TestGitPathToWebPath(t *testing.T) {
  78. type test struct {
  79. Expected string
  80. Filename string
  81. }
  82. for _, test := range []test{
  83. {"hello-world", "hello-world.md"}, // this shouldn't happen, because it should always have a ".-" suffix
  84. {"hello-world", "hello world.md"},
  85. {"hello-world.-", "hello-world.-.md"},
  86. {"hello+world.-", "hello world.-.md"},
  87. {"symbols-%2F", "symbols %2F.md"},
  88. } {
  89. name, err := GitPathToWebPath(test.Filename)
  90. assert.NoError(t, err)
  91. assert.EqualValues(t, test.Expected, name)
  92. }
  93. for _, badFilename := range []string{
  94. "nofileextension",
  95. "wrongfileextension.txt",
  96. } {
  97. _, err := GitPathToWebPath(badFilename)
  98. assert.Error(t, err)
  99. assert.True(t, repo_model.IsErrWikiInvalidFileName(err))
  100. }
  101. _, err := GitPathToWebPath("badescaping%%.md")
  102. assert.Error(t, err)
  103. assert.False(t, repo_model.IsErrWikiInvalidFileName(err))
  104. }
  105. func TestUserWebGitPathConsistency(t *testing.T) {
  106. maxLen := 20
  107. b := make([]byte, maxLen)
  108. for range 1000 {
  109. l := rand.Intn(maxLen)
  110. for j := range l {
  111. r := rand.Intn(0x80-0x20) + 0x20
  112. b[j] = byte(r)
  113. }
  114. userTitle := strings.TrimSpace(string(b[:l]))
  115. if userTitle == "" || userTitle == "." || userTitle == ".." {
  116. continue
  117. }
  118. webPath := UserTitleToWebPath("", userTitle)
  119. gitPath := WebPathToGitPath(webPath)
  120. webPath1, _ := GitPathToWebPath(gitPath)
  121. _, userTitle1 := WebPathToUserTitle(webPath1)
  122. gitPath1 := WebPathToGitPath(webPath1)
  123. assert.Equal(t, userTitle, userTitle1, "UserTitle for userTitle: %q", userTitle)
  124. assert.Equal(t, webPath, webPath1, "WebPath for userTitle: %q", userTitle)
  125. assert.Equal(t, gitPath, gitPath1, "GitPath for userTitle: %q", userTitle)
  126. }
  127. }
  128. func TestRepository_InitWiki(t *testing.T) {
  129. unittest.PrepareTestEnv(t)
  130. // repo1 already has a wiki
  131. repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
  132. assert.NoError(t, InitWiki(t.Context(), repo1))
  133. // repo2 does not already have a wiki
  134. repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
  135. assert.NoError(t, InitWiki(t.Context(), repo2))
  136. assert.True(t, repo_service.HasWiki(t.Context(), repo2))
  137. }
  138. func TestRepository_AddWikiPage(t *testing.T) {
  139. assert.NoError(t, unittest.PrepareTestDatabase())
  140. const wikiContent = "This is the wiki content"
  141. const commitMsg = "Commit message"
  142. repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
  143. doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
  144. for _, userTitle := range []string{
  145. "Another page",
  146. "Here's a <tag> and a/slash",
  147. } {
  148. t.Run("test wiki exist: "+userTitle, func(t *testing.T) {
  149. webPath := UserTitleToWebPath("", userTitle)
  150. assert.NoError(t, AddWikiPage(t.Context(), doer, repo, webPath, wikiContent, commitMsg))
  151. // Now need to show that the page has been added:
  152. gitRepo, err := gitrepo.OpenRepository(t.Context(), repo.WikiStorageRepo())
  153. require.NoError(t, err)
  154. defer gitRepo.Close()
  155. masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch)
  156. assert.NoError(t, err)
  157. gitPath := WebPathToGitPath(webPath)
  158. entry, err := masterTree.GetTreeEntryByPath(gitPath)
  159. assert.NoError(t, err)
  160. assert.Equal(t, gitPath, entry.Name(), "%s not added correctly", userTitle)
  161. })
  162. }
  163. t.Run("check wiki already exist", func(t *testing.T) {
  164. t.Parallel()
  165. // test for already-existing wiki name
  166. err := AddWikiPage(t.Context(), doer, repo, "Home", wikiContent, commitMsg)
  167. assert.Error(t, err)
  168. assert.True(t, repo_model.IsErrWikiAlreadyExist(err))
  169. })
  170. t.Run("check wiki reserved name", func(t *testing.T) {
  171. t.Parallel()
  172. // test for reserved wiki name
  173. err := AddWikiPage(t.Context(), doer, repo, "_edit", wikiContent, commitMsg)
  174. assert.Error(t, err)
  175. assert.True(t, repo_model.IsErrWikiReservedName(err))
  176. })
  177. }
  178. func TestRepository_EditWikiPage(t *testing.T) {
  179. assert.NoError(t, unittest.PrepareTestDatabase())
  180. const newWikiContent = "This is the new content"
  181. const commitMsg = "Commit message"
  182. repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
  183. doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
  184. for _, newWikiName := range []string{
  185. "Home", // same name as before
  186. "New home",
  187. "New/name/with/slashes",
  188. } {
  189. webPath := UserTitleToWebPath("", newWikiName)
  190. unittest.PrepareTestEnv(t)
  191. assert.NoError(t, EditWikiPage(t.Context(), doer, repo, "Home", webPath, newWikiContent, commitMsg))
  192. // Now need to show that the page has been added:
  193. gitRepo, err := gitrepo.OpenRepository(t.Context(), repo.WikiStorageRepo())
  194. assert.NoError(t, err)
  195. masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch)
  196. assert.NoError(t, err)
  197. gitPath := WebPathToGitPath(webPath)
  198. entry, err := masterTree.GetTreeEntryByPath(gitPath)
  199. assert.NoError(t, err)
  200. assert.Equal(t, gitPath, entry.Name(), "%s not edited correctly", newWikiName)
  201. if newWikiName != "Home" {
  202. _, err := masterTree.GetTreeEntryByPath("Home.md")
  203. assert.Error(t, err)
  204. }
  205. gitRepo.Close()
  206. }
  207. }
  208. func TestRepository_DeleteWikiPage(t *testing.T) {
  209. unittest.PrepareTestEnv(t)
  210. repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
  211. doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
  212. assert.NoError(t, DeleteWikiPage(t.Context(), doer, repo, "Home"))
  213. // Now need to show that the page has been added:
  214. gitRepo, err := gitrepo.OpenRepository(t.Context(), repo.WikiStorageRepo())
  215. require.NoError(t, err)
  216. defer gitRepo.Close()
  217. masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch)
  218. assert.NoError(t, err)
  219. gitPath := WebPathToGitPath("Home")
  220. _, err = masterTree.GetTreeEntryByPath(gitPath)
  221. assert.Error(t, err)
  222. }
  223. func TestPrepareWikiFileName(t *testing.T) {
  224. unittest.PrepareTestEnv(t)
  225. repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
  226. gitRepo, err := gitrepo.OpenRepository(t.Context(), repo.WikiStorageRepo())
  227. require.NoError(t, err)
  228. defer gitRepo.Close()
  229. tests := []struct {
  230. name string
  231. arg string
  232. existence bool
  233. wikiPath string
  234. wantErr bool
  235. }{{
  236. name: "add suffix",
  237. arg: "Home",
  238. existence: true,
  239. wikiPath: "Home.md",
  240. wantErr: false,
  241. }, {
  242. name: "test special chars",
  243. arg: "home of and & or wiki page!",
  244. existence: false,
  245. wikiPath: "home-of-and-%26-or-wiki-page%21.md",
  246. wantErr: false,
  247. }}
  248. for _, tt := range tests {
  249. t.Run(tt.name, func(t *testing.T) {
  250. webPath := UserTitleToWebPath("", tt.arg)
  251. existence, newWikiPath, err := prepareGitPath(gitRepo, repo.DefaultWikiBranch, webPath)
  252. if (err != nil) != tt.wantErr {
  253. assert.NoError(t, err)
  254. return
  255. }
  256. if existence != tt.existence {
  257. if existence {
  258. t.Errorf("expect to find no escaped file but we detect one")
  259. } else {
  260. t.Errorf("expect to find an escaped file but we could not detect one")
  261. }
  262. }
  263. assert.Equal(t, tt.wikiPath, newWikiPath)
  264. })
  265. }
  266. }
  267. func TestPrepareWikiFileName_FirstPage(t *testing.T) {
  268. unittest.PrepareTestEnv(t)
  269. // Now create a temporaryDirectory
  270. tmpDir := t.TempDir()
  271. err := git.InitRepository(t.Context(), tmpDir, true, git.Sha1ObjectFormat.Name())
  272. assert.NoError(t, err)
  273. gitRepo, err := git.OpenRepository(t.Context(), tmpDir)
  274. require.NoError(t, err)
  275. defer gitRepo.Close()
  276. existence, newWikiPath, err := prepareGitPath(gitRepo, "master", "Home")
  277. assert.False(t, existence)
  278. assert.NoError(t, err)
  279. assert.Equal(t, "Home.md", newWikiPath)
  280. }
  281. func TestWebPathConversion(t *testing.T) {
  282. assert.Equal(t, "path/wiki", WebPathToURLPath(WebPath("path/wiki")))
  283. assert.Equal(t, "wiki", WebPathToURLPath(WebPath("wiki")))
  284. assert.Empty(t, WebPathToURLPath(WebPath("")))
  285. }
  286. func TestWebPathFromRequest(t *testing.T) {
  287. assert.Equal(t, WebPath("a%2Fb"), WebPathFromRequest("a/b"))
  288. assert.Equal(t, WebPath("a"), WebPathFromRequest("a"))
  289. assert.Equal(t, WebPath("b"), WebPathFromRequest("a/../b"))
  290. }