test_pagure_flask_ui_pr_no_sources.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. # -*- coding: utf-8 -*-
  2. """
  3. (c) 2015-2018 - Copyright Red Hat Inc
  4. Authors:
  5. Pierre-Yves Chibon <pingou@pingoured.fr>
  6. """
  7. from __future__ import unicode_literals
  8. __requires__ = ['SQLAlchemy >= 0.8']
  9. import pkg_resources
  10. import json
  11. import unittest
  12. import shutil
  13. import sys
  14. import tempfile
  15. import time
  16. import os
  17. import pygit2
  18. from mock import patch, MagicMock
  19. sys.path.insert(0, os.path.join(os.path.dirname(
  20. os.path.abspath(__file__)), '..'))
  21. import pagure.lib.query
  22. import tests
  23. from pagure.lib.repo import PagureRepo
  24. class BasePrNoSourcestests(tests.Modeltests):
  25. """ Tests PR in pagure when the source is gone """
  26. maxDiff = None
  27. @patch('pagure.lib.notify.send_email', MagicMock(return_value=True))
  28. @patch('pagure.lib.notify.fedmsg_publish', MagicMock(return_value=True))
  29. def setUp(self):
  30. """ Set up the environnment, ran before every tests. """
  31. super(BasePrNoSourcestests, self).setUp()
  32. tests.create_projects(self.session)
  33. tests.create_projects_git(
  34. os.path.join(self.path, 'repos'), bare=True)
  35. # Create foo's fork of pingou's test project
  36. item = pagure.lib.model.Project(
  37. user_id=2, # foo
  38. name='test',
  39. description='test project #1',
  40. hook_token='aaabbb',
  41. is_fork=True,
  42. parent_id=1,
  43. )
  44. self.session.add(item)
  45. self.session.commit()
  46. # Create the fork's git repo
  47. repo_path = os.path.join(self.path, 'repos', item.path)
  48. pygit2.init_repository(repo_path, bare=True)
  49. project = pagure.lib.query.get_authorized_project(self.session, 'test')
  50. fork = pagure.lib.query.get_authorized_project(
  51. self.session, 'test', user='foo')
  52. print('fork', fork.fullname)
  53. self.set_up_git_repo(repo=project, fork=fork)
  54. # Ensure things got setup straight
  55. project = pagure.lib.query.get_authorized_project(self.session, 'test')
  56. self.assertEqual(len(project.requests), 1)
  57. # wait for the worker to process the task
  58. path = os.path.join(
  59. self.path, 'repos', 'test.git',
  60. 'refs', 'pull', '1', 'head')
  61. self.assertTrue(os.path.exists(path))
  62. def set_up_git_repo(self, repo, fork, branch_from='feature'):
  63. """ Set up the git repo and create the corresponding PullRequest
  64. object.
  65. """
  66. # Clone the main repo
  67. gitrepo = os.path.join(self.path, 'repos', repo.path)
  68. newpath = tempfile.mkdtemp(prefix='pagure-fork-test')
  69. repopath = os.path.join(newpath, 'test')
  70. clone_repo = pygit2.clone_repository(gitrepo, repopath)
  71. # Create a file in that git repo
  72. with open(os.path.join(repopath, 'sources'), 'w') as stream:
  73. stream.write('foo\n bar')
  74. clone_repo.index.add('sources')
  75. clone_repo.index.write()
  76. # Commits the files added
  77. tree = clone_repo.index.write_tree()
  78. author = pygit2.Signature(
  79. 'Alice Author', 'alice@authors.tld')
  80. committer = pygit2.Signature(
  81. 'Cecil Committer', 'cecil@committers.tld')
  82. clone_repo.create_commit(
  83. 'refs/heads/master', # the name of the reference to update
  84. author,
  85. committer,
  86. 'Add sources file for testing',
  87. # binary string representing the tree object ID
  88. tree,
  89. # list of binary strings representing parents of the new commit
  90. []
  91. )
  92. refname = 'refs/heads/master:refs/heads/master'
  93. ori_remote = clone_repo.remotes[0]
  94. PagureRepo.push(ori_remote, refname)
  95. first_commit = clone_repo.revparse_single('HEAD')
  96. # Set the second repo
  97. repopath = os.path.join(self.path, 'repos', fork.path)
  98. new_gitrepo = os.path.join(newpath, 'fork_test')
  99. clone_repo = pygit2.clone_repository(repopath, new_gitrepo)
  100. # Add the main project as remote repo
  101. upstream_path = os.path.join(self.path, 'repos', repo.path)
  102. remote = clone_repo.create_remote('upstream', upstream_path)
  103. remote.fetch()
  104. # Edit the sources file again
  105. with open(os.path.join(new_gitrepo, 'sources'), 'w') as stream:
  106. stream.write('foo\n bar\nbaz\n boose')
  107. clone_repo.index.add('sources')
  108. clone_repo.index.write()
  109. # Commits the files added
  110. tree = clone_repo.index.write_tree()
  111. author = pygit2.Signature(
  112. 'Alice Author', 'alice@authors.tld')
  113. committer = pygit2.Signature(
  114. 'Cecil Committer', 'cecil@committers.tld')
  115. clone_repo.create_commit(
  116. 'refs/heads/%s' % branch_from,
  117. author,
  118. committer,
  119. 'A commit on branch %s' % branch_from,
  120. tree,
  121. [first_commit.oid.hex]
  122. )
  123. refname = 'refs/heads/%s' % (branch_from)
  124. ori_remote = clone_repo.remotes[0]
  125. PagureRepo.push(ori_remote, refname)
  126. # Create a PR for these changes
  127. project = pagure.lib.query.get_authorized_project(self.session, 'test')
  128. req = pagure.lib.query.new_pull_request(
  129. session=self.session,
  130. repo_from=fork,
  131. branch_from=branch_from,
  132. repo_to=project,
  133. branch_to='master',
  134. title='PR from the %s branch' % branch_from,
  135. user='pingou',
  136. )
  137. self.session.commit()
  138. self.assertEqual(req.id, 1)
  139. self.assertEqual(req.title, 'PR from the %s branch' % branch_from)
  140. shutil.rmtree(newpath)
  141. class PagureFlaskPrNoSourcestests(BasePrNoSourcestests):
  142. """ Tests PR in pagure when the source is gone """
  143. maxDiff = None
  144. @patch('pagure.lib.notify.send_email', MagicMock(return_value=True))
  145. @patch('pagure.lib.notify.fedmsg_publish', MagicMock(return_value=True))
  146. def setUp(self):
  147. """ Set up the environnment, ran before every tests. """
  148. super(PagureFlaskPrNoSourcestests, self).setUp()
  149. def test_request_pull_reference(self):
  150. """ Test if there is a reference created for a new PR. """
  151. project = pagure.lib.query.get_authorized_project(self.session, 'test')
  152. self.assertEqual(len(project.requests), 1)
  153. gitrepo = os.path.join(self.path, 'repos', 'test.git')
  154. repo = pygit2.Repository(gitrepo)
  155. self.assertEqual(
  156. list(repo.listall_references()),
  157. ['refs/heads/master', 'refs/pull/1/head']
  158. )
  159. def test_request_pull_fork_reference(self):
  160. """ Test if there the references created on the fork. """
  161. project = pagure.lib.query.get_authorized_project(
  162. self.session, 'test', user='foo')
  163. self.assertEqual(len(project.requests), 0)
  164. gitrepo = os.path.join(self.path, 'repos', project.path)
  165. repo = pygit2.Repository(gitrepo)
  166. self.assertEqual(
  167. list(repo.listall_references()),
  168. ['refs/heads/feature']
  169. )
  170. def test_accessing_pr_fork_deleted(self):
  171. """ Test accessing the PR if the fork has been deleted. """
  172. # Delete fork on disk
  173. project = pagure.lib.query.get_authorized_project(
  174. self.session, 'test', user='foo')
  175. repo_path = os.path.join(self.path, 'repos', project.path)
  176. self.assertTrue(os.path.exists(repo_path))
  177. shutil.rmtree(repo_path)
  178. self.assertFalse(os.path.exists(repo_path))
  179. # Delete fork in the DB
  180. self.session.delete(project)
  181. self.session.commit()
  182. # View the pull-request
  183. output2 = self.app.get('/test/pull-request/1')
  184. self.assertEqual(output2.status_code, 200)
  185. output_text = output2.get_data(as_text=True)
  186. self.assertIn('''<span>Files Changed&nbsp;</span>
  187. <span class="badge badge-secondary badge-pill">
  188. 1
  189. </span>''', output_text)
  190. def test_accessing_pr_patch_fork_deleted(self):
  191. """ Test accessing the PR's patch if the fork has been deleted. """
  192. # Delete fork on disk
  193. project = pagure.lib.query.get_authorized_project(
  194. self.session, 'test', user='foo')
  195. repo_path = os.path.join(self.path, 'repos', project.path)
  196. self.assertTrue(os.path.exists(repo_path))
  197. shutil.rmtree(repo_path)
  198. self.assertFalse(os.path.exists(repo_path))
  199. # Delete fork in the DB
  200. self.session.delete(project)
  201. self.session.commit()
  202. # View the pull-request
  203. output = self.app.get('/test/pull-request/1.patch')
  204. self.assertEqual(output.status_code, 200)
  205. self.assertIn(
  206. '--- a/sources\n+++ b/sources\n@@ -1,2 +1,4 @@',
  207. output.get_data(as_text=True))
  208. def test_accessing_pr_branch_deleted(self):
  209. """ Test accessing the PR if branch it originates from has been
  210. deleted. """
  211. project = pagure.lib.query.get_authorized_project(
  212. self.session, 'test', user='foo')
  213. # Check the branches before
  214. gitrepo = os.path.join(self.path, 'repos', project.path)
  215. repo = pygit2.Repository(gitrepo)
  216. self.assertEqual(
  217. list(repo.listall_references()),
  218. ['refs/heads/feature']
  219. )
  220. # Delete branch of the fork
  221. user = tests.FakeUser(username='foo')
  222. with tests.user_set(self.app.application, user):
  223. output = self.app.post(
  224. '/fork/foo/test/b/feature/delete', follow_redirects=True)
  225. self.assertEqual(output.status_code, 200)
  226. # Check the branches after
  227. gitrepo = os.path.join(self.path, 'repos', project.path)
  228. repo = pygit2.Repository(gitrepo)
  229. self.assertEqual(
  230. list(repo.listall_references()),
  231. []
  232. )
  233. # View the pull-request
  234. output2 = self.app.get('/test/pull-request/1')
  235. self.assertEqual(output2.status_code, 200)
  236. output_text = output2.get_data(as_text=True)
  237. self.assertIn('''<span>Files Changed&nbsp;</span>
  238. <span class="badge badge-secondary badge-pill">
  239. 1
  240. </span>''', output_text)
  241. def test_accessing_pr_patch_branch_deleted(self):
  242. """ Test accessing the PR's patch if branch it originates from has
  243. been deleted. """
  244. project = pagure.lib.query.get_authorized_project(
  245. self.session, 'test', user='foo')
  246. # Check the branches before
  247. gitrepo = os.path.join(self.path, 'repos', project.path)
  248. repo = pygit2.Repository(gitrepo)
  249. self.assertEqual(
  250. list(repo.listall_references()),
  251. ['refs/heads/feature']
  252. )
  253. # Delete branch of the fork
  254. user = tests.FakeUser(username='foo')
  255. with tests.user_set(self.app.application, user):
  256. output = self.app.post(
  257. '/fork/foo/test/b/feature/delete', follow_redirects=True)
  258. self.assertEqual(output.status_code, 200)
  259. # Check the branches after
  260. gitrepo = os.path.join(self.path, 'repos', project.path)
  261. repo = pygit2.Repository(gitrepo)
  262. self.assertEqual(
  263. list(repo.listall_references()),
  264. []
  265. )
  266. # View the pull-request
  267. output = self.app.get('/test/pull-request/1.patch')
  268. self.assertEqual(output.status_code, 200)
  269. output_text = output.get_data(as_text=True)
  270. self.assertIn(
  271. '--- a/sources\n+++ b/sources\n@@ -1,2 +1,4 @@',
  272. output_text)
  273. def test_accessing_pr_patch_fork_deleted_recreated(self):
  274. """ Test accessing the PR's patch if the fork has been deleted
  275. and re-created. """
  276. # Delete fork on disk
  277. project = pagure.lib.query.get_authorized_project(
  278. self.session, 'test', user='foo')
  279. repo_path = os.path.join(self.path, 'repos', project.path)
  280. self.assertTrue(os.path.exists(repo_path))
  281. shutil.rmtree(repo_path)
  282. self.assertFalse(os.path.exists(repo_path))
  283. # Delete fork in the DB
  284. self.session.delete(project)
  285. self.session.commit()
  286. # Re-create foo's fork of pingou's test project
  287. item = pagure.lib.model.Project(
  288. user_id=2, # foo
  289. name='test',
  290. description='test project #1',
  291. hook_token='aaabbb',
  292. is_fork=True,
  293. parent_id=1,
  294. )
  295. self.session.add(item)
  296. self.session.commit()
  297. # Create the fork's git repo
  298. repo_path = os.path.join(self.path, 'repos', item.path)
  299. pygit2.init_repository(repo_path, bare=True)
  300. # View the pull-request
  301. output = self.app.get('/test/pull-request/1')
  302. self.assertEqual(output.status_code, 200)
  303. output_text = output.get_data(as_text=True)
  304. self.assertIn('''<span>Commits&nbsp;</span>
  305. <span class="badge badge-secondary badge-pill">
  306. 1
  307. </span>''', output_text)
  308. self.assertIn('''<span>Files Changed&nbsp;</span>
  309. <span class="badge badge-secondary badge-pill">
  310. 1
  311. </span>''', output_text)
  312. class PagureFlaskClosedPrNoSourcestests(BasePrNoSourcestests):
  313. """ Tests viewing closed PR in pagure when the source is gone """
  314. maxDiff = None
  315. @patch('pagure.lib.notify.send_email', MagicMock(return_value=True))
  316. @patch('pagure.lib.notify.fedmsg_publish', MagicMock(return_value=True))
  317. def setUp(self):
  318. """ Set up the environnment, ran before every tests. """
  319. super(PagureFlaskClosedPrNoSourcestests, self).setUp()
  320. # Ensure things got setup straight
  321. project = pagure.lib.query.get_authorized_project(self.session, 'test')
  322. self.assertEqual(len(project.requests), 1)
  323. request = project.requests[0]
  324. self.assertEqual(request.status, "Open")
  325. request.status = "Closed"
  326. self.session.add(request)
  327. self.session.commit()
  328. def test_accessing_pr_patch_fork_deleted_recreated(self):
  329. """ Test accessing the PR's patch if the fork has been deleted
  330. and re-created. """
  331. # Delete fork on disk
  332. project = pagure.lib.query.get_authorized_project(
  333. self.session, 'test', user='foo')
  334. repo_path = os.path.join(self.path, 'repos', project.path)
  335. self.assertTrue(os.path.exists(repo_path))
  336. shutil.rmtree(repo_path)
  337. self.assertFalse(os.path.exists(repo_path))
  338. # Delete fork in the DB
  339. self.session.delete(project)
  340. self.session.commit()
  341. # Re-create foo's fork of pingou's test project
  342. item = pagure.lib.model.Project(
  343. user_id=2, # foo
  344. name='test',
  345. description='test project #1',
  346. hook_token='aaabbb',
  347. is_fork=True,
  348. parent_id=1,
  349. )
  350. self.session.add(item)
  351. self.session.commit()
  352. # Create the fork's git repo
  353. fork_path = os.path.join(self.path, 'repos', item.path)
  354. pygit2.clone_repository(repo_path, fork_path, bare=True)
  355. # View the pull-request
  356. output = self.app.get('/test/pull-request/1')
  357. self.assertEqual(output.status_code, 200)
  358. output_text = output.get_data(as_text=True)
  359. self.assertIn('''<span>Commits&nbsp;</span>
  360. <span class="badge badge-secondary badge-pill">
  361. 1
  362. </span>''', output_text)
  363. self.assertIn('''<span>Files Changed&nbsp;</span>
  364. <span class="badge badge-secondary badge-pill">
  365. 1
  366. </span>''', output_text)
  367. if __name__ == '__main__':
  368. unittest.main(verbosity=2)