You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

wiki_test.go 9.7KB

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