test_pagure_flask_internal.py 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  1. # -*- coding: utf-8 -*-
  2. """
  3. (c) 2015 - Copyright Red Hat Inc
  4. Authors:
  5. Pierre-Yves Chibon <pingou@pingoured.fr>
  6. """
  7. __requires__ = ['SQLAlchemy >= 0.8']
  8. import pkg_resources
  9. import json
  10. import unittest
  11. import shutil
  12. import sys
  13. import os
  14. import pygit2
  15. from mock import patch
  16. sys.path.insert(0, os.path.join(os.path.dirname(
  17. os.path.abspath(__file__)), '..'))
  18. import pagure.lib
  19. import tests
  20. class PagureFlaskInternaltests(tests.Modeltests):
  21. """ Tests for flask Internal controller of pagure """
  22. def setUp(self):
  23. """ Set up the environnment, ran before every tests. """
  24. super(PagureFlaskInternaltests, self).setUp()
  25. pagure.APP.config['TESTING'] = True
  26. pagure.APP.config['IP_ALLOWED_INTERNAL'] = list(set(
  27. pagure.APP.config['IP_ALLOWED_INTERNAL'] + [None]))
  28. pagure.SESSION = self.session
  29. pagure.internal.SESSION = self.session
  30. pagure.ui.repo.SESSION = self.session
  31. pagure.APP.config['GIT_FOLDER'] = tests.HERE
  32. pagure.APP.config['FORK_FOLDER'] = os.path.join(
  33. tests.HERE, 'forks')
  34. pagure.APP.config['REQUESTS_FOLDER'] = None
  35. pagure.APP.config['TICKETS_FOLDER'] = None
  36. pagure.APP.config['DOCS_FOLDER'] = None
  37. self.app = pagure.APP.test_client()
  38. @patch('pagure.lib.notify.send_email')
  39. def test_pull_request_add_comment(self, send_email):
  40. """ Test the pull_request_add_comment function. """
  41. send_email.return_value = True
  42. tests.create_projects(self.session)
  43. repo = pagure.lib.get_project(self.session, 'test')
  44. req = pagure.lib.new_pull_request(
  45. session=self.session,
  46. repo_from=repo,
  47. branch_from='feature',
  48. repo_to=repo,
  49. branch_to='master',
  50. title='PR from the feature branch',
  51. user='pingou',
  52. requestfolder=None,
  53. )
  54. self.session.commit()
  55. self.assertEqual(req.id, 1)
  56. self.assertEqual(req.title, 'PR from the feature branch')
  57. request = repo.requests[0]
  58. self.assertEqual(len(request.comments), 0)
  59. self.assertEqual(len(request.discussion), 0)
  60. data = {
  61. 'objid': 'foo',
  62. }
  63. # Wrong http request
  64. output = self.app.post('/pv/pull-request/comment/', data=data)
  65. self.assertEqual(output.status_code, 405)
  66. # Invalid request
  67. output = self.app.put('/pv/pull-request/comment/', data=data)
  68. self.assertEqual(output.status_code, 400)
  69. data = {
  70. 'objid': 'foo',
  71. 'useremail': 'foo@pingou.com',
  72. }
  73. # Invalid objid
  74. output = self.app.put('/pv/pull-request/comment/', data=data)
  75. self.assertEqual(output.status_code, 404)
  76. data = {
  77. 'objid': request.uid,
  78. 'useremail': 'foo@pingou.com',
  79. }
  80. # Valid objid, in-complete data for a comment
  81. output = self.app.put('/pv/pull-request/comment/', data=data)
  82. self.assertEqual(output.status_code, 400)
  83. data = {
  84. 'objid': request.uid,
  85. 'useremail': 'foo@pingou.com',
  86. 'comment': 'Looks good to me!',
  87. }
  88. # Add comment
  89. output = self.app.put('/pv/pull-request/comment/', data=data)
  90. self.assertEqual(output.status_code, 200)
  91. js_data = json.loads(output.data)
  92. self.assertDictEqual(js_data, {'message': 'Comment added'})
  93. repo = pagure.lib.get_project(self.session, 'test')
  94. request = repo.requests[0]
  95. self.assertEqual(len(request.comments), 1)
  96. self.assertEqual(len(request.discussion), 1)
  97. # Check the @localonly
  98. pagure.APP.config['IP_ALLOWED_INTERNAL'].remove(None)
  99. output = self.app.put('/pv/pull-request/comment/', data=data)
  100. self.assertEqual(output.status_code, 403)
  101. @patch('pagure.lib.notify.send_email')
  102. def test_ticket_add_comment(self, send_email):
  103. """ Test the ticket_add_comment function. """
  104. send_email.return_value = True
  105. tests.create_projects(self.session)
  106. # Create issues to play with
  107. repo = pagure.lib.get_project(self.session, 'test')
  108. msg = pagure.lib.new_issue(
  109. session=self.session,
  110. repo=repo,
  111. title='Test issue',
  112. content='We should work on this',
  113. user='pingou',
  114. ticketfolder=None
  115. )
  116. self.session.commit()
  117. self.assertEqual(msg.title, 'Test issue')
  118. issue = repo.issues[0]
  119. self.assertEqual(len(issue.comments), 0)
  120. data = {
  121. 'objid': 'foo',
  122. }
  123. # Wrong http request
  124. output = self.app.post('/pv/ticket/comment/', data=data)
  125. self.assertEqual(output.status_code, 405)
  126. # Invalid request
  127. output = self.app.put('/pv/ticket/comment/', data=data)
  128. self.assertEqual(output.status_code, 400)
  129. data = {
  130. 'objid': 'foo',
  131. 'useremail': 'foo@pingou.com',
  132. }
  133. # Invalid objid
  134. output = self.app.put('/pv/ticket/comment/', data=data)
  135. self.assertEqual(output.status_code, 404)
  136. data = {
  137. 'objid': issue.uid,
  138. 'useremail': 'foo@pingou.com',
  139. }
  140. # Valid objid, in-complete data for a comment
  141. output = self.app.put('/pv/ticket/comment/', data=data)
  142. self.assertEqual(output.status_code, 400)
  143. data = {
  144. 'objid': issue.uid,
  145. 'useremail': 'foo@pingou.com',
  146. 'comment': 'Looks good to me!',
  147. }
  148. # Add comment
  149. output = self.app.put('/pv/ticket/comment/', data=data)
  150. self.assertEqual(output.status_code, 200)
  151. js_data = json.loads(output.data)
  152. self.assertDictEqual(js_data, {'message': 'Comment added'})
  153. repo = pagure.lib.get_project(self.session, 'test')
  154. issue = repo.issues[0]
  155. self.assertEqual(len(issue.comments), 1)
  156. # Check the @localonly
  157. pagure.APP.config['IP_ALLOWED_INTERNAL'].remove(None)
  158. output = self.app.put('/pv/ticket/comment/', data=data)
  159. self.assertEqual(output.status_code, 403)
  160. @patch('pagure.lib.notify.send_email')
  161. def test_private_ticket_add_comment(self, send_email):
  162. """ Test the ticket_add_comment function on a private ticket. """
  163. send_email.return_value = True
  164. tests.create_projects(self.session)
  165. # Create issues to play with
  166. repo = pagure.lib.get_project(self.session, 'test')
  167. msg = pagure.lib.new_issue(
  168. session=self.session,
  169. repo=repo,
  170. title='Test issue',
  171. content='We should work on this, really',
  172. user='pingou',
  173. private=True,
  174. ticketfolder=None
  175. )
  176. self.session.commit()
  177. self.assertEqual(msg.title, 'Test issue')
  178. issue = repo.issues[0]
  179. self.assertEqual(len(issue.comments), 0)
  180. data = {
  181. 'objid': 'foo',
  182. }
  183. # Wrong http request
  184. output = self.app.post('/pv/ticket/comment/', data=data)
  185. self.assertEqual(output.status_code, 405)
  186. # Invalid request
  187. output = self.app.put('/pv/ticket/comment/', data=data)
  188. self.assertEqual(output.status_code, 400)
  189. data = {
  190. 'objid': 'foo',
  191. 'useremail': 'foo@pingou.com',
  192. }
  193. # Invalid objid
  194. output = self.app.put('/pv/ticket/comment/', data=data)
  195. self.assertEqual(output.status_code, 404)
  196. data = {
  197. 'objid': issue.uid,
  198. 'useremail': 'foo@bar.com',
  199. }
  200. # Valid objid, un-allowed user for this (private) ticket
  201. output = self.app.put('/pv/ticket/comment/', data=data)
  202. self.assertEqual(output.status_code, 403)
  203. data = {
  204. 'objid': issue.uid,
  205. 'useremail': 'foo@pingou.com',
  206. }
  207. # Valid objid, un-allowed user for this (private) ticket
  208. output = self.app.put('/pv/ticket/comment/', data=data)
  209. self.assertEqual(output.status_code, 400)
  210. data = {
  211. 'objid': issue.uid,
  212. 'useremail': 'foo@pingou.com',
  213. 'comment': 'Looks good to me!',
  214. }
  215. # Add comment
  216. output = self.app.put('/pv/ticket/comment/', data=data)
  217. self.assertEqual(output.status_code, 200)
  218. js_data = json.loads(output.data)
  219. self.assertDictEqual(js_data, {'message': 'Comment added'})
  220. repo = pagure.lib.get_project(self.session, 'test')
  221. issue = repo.issues[0]
  222. self.assertEqual(len(issue.comments), 1)
  223. # Check the @localonly
  224. pagure.APP.config['IP_ALLOWED_INTERNAL'].remove(None)
  225. output = self.app.put('/pv/ticket/comment/', data=data)
  226. self.assertEqual(output.status_code, 403)
  227. @patch('pagure.lib.notify.send_email')
  228. def test_mergeable_request_pull_FF(self, send_email):
  229. """ Test the mergeable_request_pull endpoint with a fast-forward
  230. merge.
  231. """
  232. send_email.return_value = True
  233. # Create a git repo to play with
  234. gitrepo = os.path.join(tests.HERE, 'test.git')
  235. self.assertFalse(os.path.exists(gitrepo))
  236. os.makedirs(gitrepo)
  237. repo = pygit2.init_repository(gitrepo)
  238. # Create a file in that git repo
  239. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  240. stream.write('foo\n bar')
  241. repo.index.add('sources')
  242. repo.index.write()
  243. # Commits the files added
  244. tree = repo.index.write_tree()
  245. author = pygit2.Signature(
  246. 'Alice Author', 'alice@authors.tld')
  247. committer = pygit2.Signature(
  248. 'Cecil Committer', 'cecil@committers.tld')
  249. repo.create_commit(
  250. 'refs/heads/master', # the name of the reference to update
  251. author,
  252. committer,
  253. 'Add sources file for testing',
  254. # binary string representing the tree object ID
  255. tree,
  256. # list of binary strings representing parents of the new commit
  257. []
  258. )
  259. first_commit = repo.revparse_single('HEAD')
  260. # Edit the sources file again
  261. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  262. stream.write('foo\n bar\nbaz\n boose')
  263. repo.index.add('sources')
  264. repo.index.write()
  265. # Commits the files added
  266. tree = repo.index.write_tree()
  267. author = pygit2.Signature(
  268. 'Alice Author', 'alice@authors.tld')
  269. committer = pygit2.Signature(
  270. 'Cecil Committer', 'cecil@committers.tld')
  271. repo.create_commit(
  272. 'refs/heads/feature', # the name of the reference to update
  273. author,
  274. committer,
  275. 'Add baz and boose to the sources\n\n There are more objects to '
  276. 'consider',
  277. # binary string representing the tree object ID
  278. tree,
  279. # list of binary strings representing parents of the new commit
  280. [first_commit.oid.hex]
  281. )
  282. second_commit = repo.revparse_single('HEAD')
  283. # Create a PR for these changes
  284. tests.create_projects(self.session)
  285. project = pagure.lib.get_project(self.session, 'test')
  286. req = pagure.lib.new_pull_request(
  287. session=self.session,
  288. repo_from=project,
  289. branch_from='feature',
  290. repo_to=project,
  291. branch_to='master',
  292. title='PR from the feature branch',
  293. user='pingou',
  294. requestfolder=None,
  295. )
  296. self.session.commit()
  297. self.assertEqual(req.id, 1)
  298. self.assertEqual(req.title, 'PR from the feature branch')
  299. # Check if the PR can be merged
  300. data = {
  301. 'objid': 'blah',
  302. }
  303. # Missing CSRF
  304. output = self.app.post('/pv/pull-request/merge', data=data)
  305. self.assertEqual(output.status_code, 400)
  306. user = tests.FakeUser()
  307. user.username = 'pingou'
  308. with tests.user_set(pagure.APP, user):
  309. output = self.app.get('/test/adduser')
  310. csrf_token = output.data.split(
  311. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  312. # Missing request identifier
  313. data = {
  314. 'csrf_token': csrf_token,
  315. }
  316. output = self.app.post('/pv/pull-request/merge', data=data)
  317. self.assertEqual(output.status_code, 404)
  318. # With all the desired information
  319. project = pagure.lib.get_project(self.session, 'test')
  320. data = {
  321. 'csrf_token': csrf_token,
  322. 'requestid': project.requests[0].uid,
  323. }
  324. output = self.app.post('/pv/pull-request/merge', data=data)
  325. self.assertEqual(output.status_code, 200)
  326. exp = {
  327. "code": "FFORWARD",
  328. "message": "The pull-request can be merged and fast-forwarded",
  329. "short_code": "Ok"
  330. }
  331. js_data = json.loads(output.data)
  332. self.assertDictEqual(js_data, exp)
  333. @patch('pagure.lib.notify.send_email')
  334. def test_mergeable_request_pull_no_change(self, send_email):
  335. """ Test the mergeable_request_pull endpoint when there are no
  336. changes to merge.
  337. """
  338. send_email.return_value = True
  339. # Create a git repo to play with
  340. gitrepo = os.path.join(tests.HERE, 'test.git')
  341. self.assertFalse(os.path.exists(gitrepo))
  342. os.makedirs(gitrepo)
  343. repo = pygit2.init_repository(gitrepo)
  344. # Create a file in that git repo
  345. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  346. stream.write('foo\n bar')
  347. repo.index.add('sources')
  348. repo.index.write()
  349. # Commits the files added
  350. tree = repo.index.write_tree()
  351. author = pygit2.Signature(
  352. 'Alice Author', 'alice@authors.tld')
  353. committer = pygit2.Signature(
  354. 'Cecil Committer', 'cecil@committers.tld')
  355. repo.create_commit(
  356. 'refs/heads/master', # the name of the reference to update
  357. author,
  358. committer,
  359. 'Add sources file for testing',
  360. # binary string representing the tree object ID
  361. tree,
  362. # list of binary strings representing parents of the new commit
  363. []
  364. )
  365. first_commit = repo.revparse_single('HEAD')
  366. # Edit the sources file again
  367. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  368. stream.write('foo\n bar\nbaz\n boose')
  369. repo.index.add('sources')
  370. repo.index.write()
  371. # Commits the files added
  372. tree = repo.index.write_tree()
  373. author = pygit2.Signature(
  374. 'Alice Author', 'alice@authors.tld')
  375. committer = pygit2.Signature(
  376. 'Cecil Committer', 'cecil@committers.tld')
  377. repo.create_commit(
  378. 'refs/heads/master', # the name of the reference to update
  379. author,
  380. committer,
  381. 'Add baz and boose to the sources\n\n There are more objects to '
  382. 'consider',
  383. # binary string representing the tree object ID
  384. tree,
  385. # list of binary strings representing parents of the new commit
  386. [first_commit.oid.hex]
  387. )
  388. second_commit = repo.revparse_single('HEAD')
  389. # Create a PR for these changes
  390. tests.create_projects(self.session)
  391. project = pagure.lib.get_project(self.session, 'test')
  392. req = pagure.lib.new_pull_request(
  393. session=self.session,
  394. repo_from=project,
  395. branch_from='master',
  396. repo_to=project,
  397. branch_to='master',
  398. title='PR from the feature branch',
  399. user='pingou',
  400. requestfolder=None,
  401. )
  402. self.session.commit()
  403. self.assertEqual(req.id, 1)
  404. self.assertEqual(req.title, 'PR from the feature branch')
  405. # Check if the PR can be merged
  406. data = {
  407. 'objid': 'blah',
  408. }
  409. # Missing CSRF
  410. output = self.app.post('/pv/pull-request/merge', data=data)
  411. self.assertEqual(output.status_code, 400)
  412. user = tests.FakeUser()
  413. user.username = 'pingou'
  414. with tests.user_set(pagure.APP, user):
  415. output = self.app.get('/test/adduser')
  416. csrf_token = output.data.split(
  417. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  418. # Missing request identifier
  419. data = {
  420. 'csrf_token': csrf_token,
  421. }
  422. output = self.app.post('/pv/pull-request/merge', data=data)
  423. self.assertEqual(output.status_code, 404)
  424. # With all the desired information
  425. project = pagure.lib.get_project(self.session, 'test')
  426. data = {
  427. 'csrf_token': csrf_token,
  428. 'requestid': project.requests[0].uid,
  429. }
  430. output = self.app.post('/pv/pull-request/merge', data=data)
  431. self.assertEqual(output.status_code, 200)
  432. exp = {
  433. "code": "NO_CHANGE",
  434. "message": "Nothing to change, git is up to date",
  435. "short_code": "No changes"
  436. }
  437. js_data = json.loads(output.data)
  438. self.assertDictEqual(js_data, exp)
  439. @patch('pagure.lib.notify.send_email')
  440. def test_mergeable_request_pull_merge(self, send_email):
  441. """ Test the mergeable_request_pull endpoint when the changes can
  442. be merged with a merge commit.
  443. """
  444. send_email.return_value = True
  445. # Create a git repo to play with
  446. gitrepo = os.path.join(tests.HERE, 'test.git')
  447. self.assertFalse(os.path.exists(gitrepo))
  448. os.makedirs(gitrepo)
  449. repo = pygit2.init_repository(gitrepo)
  450. # Create a file in that git repo
  451. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  452. stream.write('foo\n bar')
  453. repo.index.add('sources')
  454. repo.index.write()
  455. # Commits the files added
  456. tree = repo.index.write_tree()
  457. author = pygit2.Signature(
  458. 'Alice Author', 'alice@authors.tld')
  459. committer = pygit2.Signature(
  460. 'Cecil Committer', 'cecil@committers.tld')
  461. repo.create_commit(
  462. 'refs/heads/master', # the name of the reference to update
  463. author,
  464. committer,
  465. 'Add sources file for testing',
  466. # binary string representing the tree object ID
  467. tree,
  468. # list of binary strings representing parents of the new commit
  469. []
  470. )
  471. first_commit = repo.revparse_single('HEAD')
  472. # Edit the sources file again
  473. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  474. stream.write('foo\n bar\nbaz\n boose')
  475. repo.index.add('sources')
  476. repo.index.write()
  477. # Commits the files added
  478. tree = repo.index.write_tree()
  479. author = pygit2.Signature(
  480. 'Alice Author', 'alice@authors.tld')
  481. committer = pygit2.Signature(
  482. 'Cecil Committer', 'cecil@committers.tld')
  483. repo.create_commit(
  484. 'refs/heads/feature', # the name of the reference to update
  485. author,
  486. committer,
  487. 'Add baz and boose to the sources\n\n There are more objects to '
  488. 'consider',
  489. # binary string representing the tree object ID
  490. tree,
  491. # list of binary strings representing parents of the new commit
  492. [first_commit.oid.hex]
  493. )
  494. # Create another file in the master branch
  495. with open(os.path.join(gitrepo, '.gitignore'), 'w') as stream:
  496. stream.write('*~')
  497. repo.index.add('.gitignore')
  498. repo.index.write()
  499. # Commits the files added
  500. tree = repo.index.write_tree()
  501. author = pygit2.Signature(
  502. 'Alice Author', 'alice@authors.tld')
  503. committer = pygit2.Signature(
  504. 'Cecil Committer', 'cecil@committers.tld')
  505. repo.create_commit(
  506. 'refs/heads/master', # the name of the reference to update
  507. author,
  508. committer,
  509. 'Add .gitignore file for testing',
  510. # binary string representing the tree object ID
  511. tree,
  512. # list of binary strings representing parents of the new commit
  513. [first_commit.oid.hex]
  514. )
  515. # Create a PR for these changes
  516. tests.create_projects(self.session)
  517. project = pagure.lib.get_project(self.session, 'test')
  518. req = pagure.lib.new_pull_request(
  519. session=self.session,
  520. repo_from=project,
  521. branch_from='feature',
  522. repo_to=project,
  523. branch_to='master',
  524. title='PR from the feature branch',
  525. user='pingou',
  526. requestfolder=None,
  527. )
  528. self.session.commit()
  529. self.assertEqual(req.id, 1)
  530. self.assertEqual(req.title, 'PR from the feature branch')
  531. # Check if the PR can be merged
  532. data = {}
  533. # Missing CSRF
  534. output = self.app.post('/pv/pull-request/merge', data=data)
  535. self.assertEqual(output.status_code, 400)
  536. user = tests.FakeUser()
  537. user.username = 'pingou'
  538. with tests.user_set(pagure.APP, user):
  539. output = self.app.get('/test/adduser')
  540. csrf_token = output.data.split(
  541. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  542. # Missing request identifier
  543. data = {
  544. 'csrf_token': csrf_token,
  545. }
  546. output = self.app.post('/pv/pull-request/merge', data=data)
  547. self.assertEqual(output.status_code, 404)
  548. # With all the desired information
  549. project = pagure.lib.get_project(self.session, 'test')
  550. data = {
  551. 'csrf_token': csrf_token,
  552. 'requestid': project.requests[0].uid,
  553. }
  554. output = self.app.post('/pv/pull-request/merge', data=data)
  555. self.assertEqual(output.status_code, 200)
  556. exp = {
  557. "code": "MERGE",
  558. "message": "The pull-request can be merged with a merge commit",
  559. "short_code": "With merge"
  560. }
  561. js_data = json.loads(output.data)
  562. self.assertDictEqual(js_data, exp)
  563. @patch('pagure.lib.notify.send_email')
  564. def test_mergeable_request_pull_conflicts(self, send_email):
  565. """ Test the mergeable_request_pull endpoint when the changes cannot
  566. be merged due to conflicts.
  567. """
  568. send_email.return_value = True
  569. # Create a git repo to play with
  570. gitrepo = os.path.join(tests.HERE, 'test.git')
  571. self.assertFalse(os.path.exists(gitrepo))
  572. os.makedirs(gitrepo)
  573. repo = pygit2.init_repository(gitrepo)
  574. # Create a file in that git repo
  575. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  576. stream.write('foo\n bar')
  577. repo.index.add('sources')
  578. repo.index.write()
  579. # Commits the files added
  580. tree = repo.index.write_tree()
  581. author = pygit2.Signature(
  582. 'Alice Author', 'alice@authors.tld')
  583. committer = pygit2.Signature(
  584. 'Cecil Committer', 'cecil@committers.tld')
  585. repo.create_commit(
  586. 'refs/heads/master', # the name of the reference to update
  587. author,
  588. committer,
  589. 'Add sources file for testing',
  590. # binary string representing the tree object ID
  591. tree,
  592. # list of binary strings representing parents of the new commit
  593. []
  594. )
  595. first_commit = repo.revparse_single('HEAD')
  596. # Edit the sources file again
  597. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  598. stream.write('foo\n bar\nbaz\n boose')
  599. repo.index.add('sources')
  600. repo.index.write()
  601. # Commits the files added
  602. tree = repo.index.write_tree()
  603. author = pygit2.Signature(
  604. 'Alice Author', 'alice@authors.tld')
  605. committer = pygit2.Signature(
  606. 'Cecil Committer', 'cecil@committers.tld')
  607. repo.create_commit(
  608. 'refs/heads/feature', # the name of the reference to update
  609. author,
  610. committer,
  611. 'Add baz and boose to the sources\n\n There are more objects to '
  612. 'consider',
  613. # binary string representing the tree object ID
  614. tree,
  615. # list of binary strings representing parents of the new commit
  616. [first_commit.oid.hex]
  617. )
  618. # Create another file in the master branch
  619. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  620. stream.write('foo\n bar\nbaz\n')
  621. repo.index.add('sources')
  622. repo.index.write()
  623. # Commits the files added
  624. tree = repo.index.write_tree()
  625. author = pygit2.Signature(
  626. 'Alice Author', 'alice@authors.tld')
  627. committer = pygit2.Signature(
  628. 'Cecil Committer', 'cecil@committers.tld')
  629. repo.create_commit(
  630. 'refs/heads/master', # the name of the reference to update
  631. author,
  632. committer,
  633. 'Add .gitignore file for testing',
  634. # binary string representing the tree object ID
  635. tree,
  636. # list of binary strings representing parents of the new commit
  637. [first_commit.oid.hex]
  638. )
  639. # Create a PR for these changes
  640. tests.create_projects(self.session)
  641. project = pagure.lib.get_project(self.session, 'test')
  642. req = pagure.lib.new_pull_request(
  643. session=self.session,
  644. repo_from=project,
  645. branch_from='feature',
  646. repo_to=project,
  647. branch_to='master',
  648. title='PR from the feature branch',
  649. user='pingou',
  650. requestfolder=None,
  651. )
  652. self.session.commit()
  653. self.assertEqual(req.id, 1)
  654. self.assertEqual(req.title, 'PR from the feature branch')
  655. # Check if the PR can be merged
  656. data = {}
  657. # Missing CSRF
  658. output = self.app.post('/pv/pull-request/merge', data=data)
  659. self.assertEqual(output.status_code, 400)
  660. user = tests.FakeUser()
  661. user.username = 'pingou'
  662. with tests.user_set(pagure.APP, user):
  663. output = self.app.get('/test/adduser')
  664. csrf_token = output.data.split(
  665. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  666. # Missing request identifier
  667. data = {
  668. 'csrf_token': csrf_token,
  669. }
  670. output = self.app.post('/pv/pull-request/merge', data=data)
  671. self.assertEqual(output.status_code, 404)
  672. # With all the desired information
  673. project = pagure.lib.get_project(self.session, 'test')
  674. data = {
  675. 'csrf_token': csrf_token,
  676. 'requestid': project.requests[0].uid,
  677. }
  678. output = self.app.post('/pv/pull-request/merge', data=data)
  679. self.assertEqual(output.status_code, 200)
  680. exp = {
  681. "code": "CONFLICTS",
  682. "message": "The pull-request cannot be merged due to conflicts",
  683. "short_code": "Conflicts"
  684. }
  685. js_data = json.loads(output.data)
  686. self.assertDictEqual(js_data, exp)
  687. def test_get_branches_of_commit(self):
  688. ''' Test the get_branches_of_commit from the internal API. '''
  689. tests.create_projects(self.session)
  690. user = tests.FakeUser()
  691. user.username = 'pingou'
  692. with tests.user_set(pagure.APP, user):
  693. output = self.app.get('/test/adduser')
  694. csrf_token = output.data.split(
  695. b'name="csrf_token" type="hidden" value="')[1].split(b'">')[0]
  696. # No CSRF token
  697. data = {
  698. 'repo': 'fakerepo',
  699. 'commit_id': 'foo',
  700. }
  701. output = self.app.post('/pv/branches/commit/', data=data)
  702. self.assertEqual(output.status_code, 400)
  703. js_data = json.loads(output.data.decode('utf-8'))
  704. self.assertDictEqual(
  705. js_data,
  706. {u'code': u'ERROR', u'message': u'Invalid input submitted'}
  707. )
  708. # Invalid repo
  709. data = {
  710. 'repo': 'fakerepo',
  711. 'commit_id': 'foo',
  712. 'csrf_token': csrf_token,
  713. }
  714. output = self.app.post('/pv/branches/commit/', data=data)
  715. self.assertEqual(output.status_code, 404)
  716. js_data = json.loads(output.data.decode('utf-8'))
  717. self.assertDictEqual(
  718. js_data,
  719. {
  720. u'code': u'ERROR',
  721. u'message': u'No repo found with the information provided'
  722. }
  723. )
  724. # Rigth repo, no commit
  725. data = {
  726. 'repo': 'test',
  727. 'csrf_token': csrf_token,
  728. }
  729. output = self.app.post('/pv/branches/commit/', data=data)
  730. self.assertEqual(output.status_code, 400)
  731. js_data = json.loads(output.data.decode('utf-8'))
  732. self.assertDictEqual(
  733. js_data,
  734. {u'code': u'ERROR', u'message': u'No commit id submitted'}
  735. )
  736. # Request is fine, but git repo doesn't exist
  737. data = {
  738. 'repo': 'test',
  739. 'commit_id': 'foo',
  740. 'csrf_token': csrf_token,
  741. }
  742. output = self.app.post('/pv/branches/commit/', data=data)
  743. self.assertEqual(output.status_code, 404)
  744. js_data = json.loads(output.data.decode('utf-8'))
  745. self.assertDictEqual(
  746. js_data,
  747. {
  748. u'code': u'ERROR',
  749. u'message': u'No git repo found with the information provided'
  750. }
  751. )
  752. # Create a git repo to play with
  753. gitrepo = os.path.join(tests.HERE, 'test.git')
  754. self.assertFalse(os.path.exists(gitrepo))
  755. os.makedirs(gitrepo)
  756. repo = pygit2.init_repository(gitrepo)
  757. # Create a file in that git repo
  758. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  759. stream.write('foo\n bar')
  760. repo.index.add('sources')
  761. repo.index.write()
  762. # Commits the files added
  763. tree = repo.index.write_tree()
  764. author = pygit2.Signature(
  765. 'Alice Author', 'alice@authors.tld')
  766. committer = pygit2.Signature(
  767. 'Cecil Committer', 'cecil@committers.tld')
  768. repo.create_commit(
  769. 'refs/heads/master', # the name of the reference to update
  770. author,
  771. committer,
  772. 'Add sources file for testing',
  773. # binary string representing the tree object ID
  774. tree,
  775. # list of binary strings representing parents of the new commit
  776. []
  777. )
  778. first_commit = repo.revparse_single('HEAD')
  779. # Edit the sources file again
  780. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  781. stream.write('foo\n bar\nbaz\n boose')
  782. repo.index.add('sources')
  783. repo.index.write()
  784. # Commits the files added
  785. tree = repo.index.write_tree()
  786. author = pygit2.Signature(
  787. 'Alice Author', 'alice@authors.tld')
  788. committer = pygit2.Signature(
  789. 'Cecil Committer', 'cecil@committers.tld')
  790. repo.create_commit(
  791. 'refs/heads/feature', # the name of the reference to update
  792. author,
  793. committer,
  794. 'Add baz and boose to the sources\n\n There are more objects to '
  795. 'consider',
  796. # binary string representing the tree object ID
  797. tree,
  798. # list of binary strings representing parents of the new commit
  799. [first_commit.oid.hex]
  800. )
  801. # Create another file in the master branch
  802. with open(os.path.join(gitrepo, '.gitignore'), 'w') as stream:
  803. stream.write('*~')
  804. repo.index.add('.gitignore')
  805. repo.index.write()
  806. # Commits the files added
  807. tree = repo.index.write_tree()
  808. author = pygit2.Signature(
  809. 'Alice Author', 'alice@authors.tld')
  810. committer = pygit2.Signature(
  811. 'Cecil Committer', 'cecil@committers.tld')
  812. commit_hash = repo.create_commit(
  813. 'refs/heads/feature_branch', # the name of the reference to update
  814. author,
  815. committer,
  816. 'Add .gitignore file for testing',
  817. # binary string representing the tree object ID
  818. tree,
  819. # list of binary strings representing parents of the new commit
  820. [first_commit.oid.hex]
  821. )
  822. # All good but the commit id
  823. data = {
  824. 'repo': 'test',
  825. 'commit_id': 'foo',
  826. 'csrf_token': csrf_token,
  827. }
  828. output = self.app.post('/pv/branches/commit/', data=data)
  829. self.assertEqual(output.status_code, 404)
  830. js_data = json.loads(output.data.decode('utf-8'))
  831. self.assertDictEqual(
  832. js_data,
  833. {
  834. u'code': u'ERROR',
  835. u'message': 'This commit could not be found in this repo'
  836. }
  837. )
  838. # All good
  839. data = {
  840. 'repo': 'test',
  841. 'commit_id': commit_hash,
  842. 'csrf_token': csrf_token,
  843. }
  844. output = self.app.post('/pv/branches/commit/', data=data)
  845. self.assertEqual(output.status_code, 200)
  846. js_data = json.loads(output.data.decode('utf-8'))
  847. self.assertDictEqual(
  848. js_data,
  849. {
  850. u'code': u'OK',
  851. u'branches': ['feature_branch'],
  852. }
  853. )
  854. if __name__ == '__main__':
  855. SUITE = unittest.TestLoader().loadTestsFromTestCase(
  856. PagureFlaskInternaltests)
  857. unittest.TextTestRunner(verbosity=2).run(SUITE)