test_pagure_flask_api_project.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  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 datetime
  10. import json
  11. import unittest
  12. import shutil
  13. import sys
  14. import tempfile
  15. import os
  16. import pygit2
  17. from mock import patch
  18. sys.path.insert(0, os.path.join(os.path.dirname(
  19. os.path.abspath(__file__)), '..'))
  20. import pagure.lib
  21. import tests
  22. from pagure.lib.repo import PagureRepo
  23. class PagureFlaskApiProjecttests(tests.Modeltests):
  24. """ Tests for the flask API of pagure for issue """
  25. def setUp(self):
  26. """ Set up the environnment, ran before every tests. """
  27. super(PagureFlaskApiProjecttests, self).setUp()
  28. pagure.APP.config['TESTING'] = True
  29. pagure.SESSION = self.session
  30. pagure.api.SESSION = self.session
  31. pagure.api.project.SESSION = self.session
  32. pagure.lib.SESSION = self.session
  33. pagure.APP.config['GIT_FOLDER'] = os.path.join(tests.HERE, 'repos')
  34. pagure.APP.config['FORK_FOLDER'] = os.path.join(
  35. tests.HERE, 'forks')
  36. pagure.APP.config['REQUESTS_FOLDER'] = os.path.join(
  37. tests.HERE, 'requests')
  38. pagure.APP.config['TICKETS_FOLDER'] = os.path.join(
  39. tests.HERE, 'tickets')
  40. pagure.APP.config['DOCS_FOLDER'] = os.path.join(
  41. tests.HERE, 'docs')
  42. self.app = pagure.APP.test_client()
  43. def test_api_git_tags(self):
  44. """ Test the api_git_tags method of the flask api. """
  45. tests.create_projects(self.session)
  46. # Create a git repo to play with
  47. gitrepo = os.path.join(tests.HERE, 'repos', 'test.git')
  48. repo = pygit2.init_repository(gitrepo, bare=True)
  49. newpath = tempfile.mkdtemp(prefix='pagure-fork-test')
  50. repopath = os.path.join(newpath, 'test')
  51. clone_repo = pygit2.clone_repository(gitrepo, repopath)
  52. # Create a file in that git repo
  53. with open(os.path.join(repopath, 'sources'), 'w') as stream:
  54. stream.write('foo\n bar')
  55. clone_repo.index.add('sources')
  56. clone_repo.index.write()
  57. # Commits the files added
  58. tree = clone_repo.index.write_tree()
  59. author = pygit2.Signature(
  60. 'Alice Author', 'alice@authors.tld')
  61. committer = pygit2.Signature(
  62. 'Cecil Committer', 'cecil@committers.tld')
  63. clone_repo.create_commit(
  64. 'refs/heads/master', # the name of the reference to update
  65. author,
  66. committer,
  67. 'Add sources file for testing',
  68. # binary string representing the tree object ID
  69. tree,
  70. # list of binary strings representing parents of the new commit
  71. []
  72. )
  73. refname = 'refs/heads/master:refs/heads/master'
  74. ori_remote = clone_repo.remotes[0]
  75. PagureRepo.push(ori_remote, refname)
  76. # Tag our first commit
  77. first_commit = repo.revparse_single('HEAD')
  78. tagger = pygit2.Signature('Alice Doe', 'adoe@example.com', 12347, 0)
  79. repo.create_tag(
  80. "0.0.1", first_commit.oid.hex, pygit2.GIT_OBJ_COMMIT, tagger,
  81. "Release 0.0.1")
  82. # Check tags
  83. output = self.app.get('/api/0/test/git/tags')
  84. self.assertEqual(output.status_code, 200)
  85. data = json.loads(output.data)
  86. self.assertDictEqual(
  87. data,
  88. {'tags': ['0.0.1'], 'total_tags': 1}
  89. )
  90. shutil.rmtree(newpath)
  91. def test_api_projects(self):
  92. """ Test the api_projects method of the flask api. """
  93. tests.create_projects(self.session)
  94. # Check before adding
  95. repo = pagure.lib.get_project(self.session, 'test')
  96. self.assertEqual(repo.tags, [])
  97. # Adding a tag
  98. output = pagure.lib.update_tags(
  99. self.session, repo, 'infra', 'pingou',
  100. ticketfolder=None)
  101. self.assertEqual(output, ['Tag added: infra'])
  102. # Check after adding
  103. repo = pagure.lib.get_project(self.session, 'test')
  104. self.assertEqual(len(repo.tags), 1)
  105. self.assertEqual(repo.tags_text, ['infra'])
  106. # Check the API
  107. output = self.app.get('/api/0/projects?tags=inf')
  108. self.assertEqual(output.status_code, 404)
  109. data = json.loads(output.data)
  110. self.assertDictEqual(
  111. data,
  112. {'error_code': 'ENOPROJECTS', 'error': 'No projects found'}
  113. )
  114. output = self.app.get('/api/0/projects?tags=infra')
  115. self.assertEqual(output.status_code, 200)
  116. data = json.loads(output.data)
  117. data['projects'][0]['date_created'] = "1436527638"
  118. self.assertDictEqual(
  119. data,
  120. {
  121. "total_projects": 1,
  122. "projects": [
  123. {
  124. "date_created": "1436527638",
  125. "description": "test project #1",
  126. "id": 1,
  127. "name": "test",
  128. "parent": None,
  129. "priorities": {},
  130. "tags": ["infra"],
  131. "user": {
  132. "fullname": "PY C",
  133. "name": "pingou"
  134. }
  135. }
  136. ]
  137. }
  138. )
  139. output = self.app.get('/api/0/projects?username=pingou')
  140. self.assertEqual(output.status_code, 200)
  141. data = json.loads(output.data)
  142. data['projects'][0]['date_created'] = "1436527638"
  143. data['projects'][1]['date_created'] = "1436527638"
  144. self.assertDictEqual(
  145. data,
  146. {
  147. "total_projects": 2,
  148. "projects": [
  149. {
  150. "date_created": "1436527638",
  151. "description": "test project #1",
  152. "id": 1,
  153. "name": "test",
  154. "parent": None,
  155. "priorities": {},
  156. "tags": ["infra"],
  157. "user": {
  158. "fullname": "PY C",
  159. "name": "pingou"
  160. }
  161. },
  162. {
  163. "date_created": "1436527638",
  164. "description": "test project #2",
  165. "id": 2,
  166. "name": "test2",
  167. "parent": None,
  168. "priorities": {},
  169. "tags": [],
  170. "user": {
  171. "fullname": "PY C",
  172. "name": "pingou"
  173. }
  174. }
  175. ]
  176. }
  177. )
  178. output = self.app.get('/api/0/projects?username=pingou&tags=infra')
  179. self.assertEqual(output.status_code, 200)
  180. data = json.loads(output.data)
  181. data['projects'][0]['date_created'] = "1436527638"
  182. self.assertDictEqual(
  183. data,
  184. {
  185. "total_projects": 1,
  186. "projects": [
  187. {
  188. "date_created": "1436527638",
  189. "description": "test project #1",
  190. "id": 1,
  191. "name": "test",
  192. "parent": None,
  193. "priorities": {},
  194. "tags": ["infra"],
  195. "user": {
  196. "fullname": "PY C",
  197. "name": "pingou"
  198. }
  199. }
  200. ]
  201. }
  202. )
  203. @patch('pagure.lib.git.generate_gitolite_acls')
  204. def test_api_new_project(self, p_gga):
  205. """ Test the api_new_project method of the flask api. """
  206. p_gga.return_value = True
  207. tests.create_projects(self.session)
  208. tests.create_projects_git(os.path.join(tests.HERE, 'tickets'))
  209. tests.create_tokens(self.session)
  210. tests.create_tokens_acl(self.session)
  211. headers = {'Authorization': 'token foo_token'}
  212. # Invalid token
  213. output = self.app.post('/api/0/new', headers=headers)
  214. self.assertEqual(output.status_code, 401)
  215. data = json.loads(output.data)
  216. self.assertDictEqual(
  217. data,
  218. {
  219. "error": "Invalid or expired token. Please visit " \
  220. "https://pagure.org/ to get or renew your API token.",
  221. "error_code": "EINVALIDTOK"
  222. }
  223. )
  224. headers = {'Authorization': 'token aaabbbcccddd'}
  225. # No input
  226. output = self.app.post('/api/0/new', headers=headers)
  227. self.assertEqual(output.status_code, 400)
  228. data = json.loads(output.data)
  229. self.assertDictEqual(
  230. data,
  231. {
  232. "error": "Invalid or incomplete input submited",
  233. "error_code": "EINVALIDREQ",
  234. }
  235. )
  236. data = {
  237. 'name': 'test',
  238. }
  239. # Incomplete request
  240. output = self.app.post(
  241. '/api/0/new', data=data, headers=headers)
  242. self.assertEqual(output.status_code, 400)
  243. data = json.loads(output.data)
  244. self.assertDictEqual(
  245. data,
  246. {
  247. "error": "Invalid or incomplete input submited",
  248. "error_code": "EINVALIDREQ",
  249. }
  250. )
  251. data = {
  252. 'name': 'test',
  253. 'description': 'Just a small test project',
  254. }
  255. # Valid request but repo already exists
  256. output = self.app.post(
  257. '/api/0/new/', data=data, headers=headers)
  258. self.assertEqual(output.status_code, 400)
  259. data = json.loads(output.data)
  260. self.assertDictEqual(
  261. data,
  262. {
  263. "error": "The tickets repo \"test.git\" already exists",
  264. "error_code": "ENOCODE"
  265. }
  266. )
  267. data = {
  268. 'name': 'test_42',
  269. 'description': 'Just another small test project',
  270. }
  271. # Valid request
  272. output = self.app.post(
  273. '/api/0/new/', data=data, headers=headers)
  274. self.assertEqual(output.status_code, 200)
  275. data = json.loads(output.data)
  276. self.assertDictEqual(
  277. data,
  278. {'message': 'Project "test_42" created'}
  279. )
  280. @patch('pagure.lib.git.generate_gitolite_acls')
  281. def test_api_fork_project(self, p_gga):
  282. """ Test the api_fork_project method of the flask api. """
  283. p_gga.return_value = True
  284. tests.create_projects(self.session)
  285. for folder in ['docs', 'tickets', 'requests', 'repos']:
  286. tests.create_projects_git(
  287. os.path.join(tests.HERE, folder), bare=True)
  288. tests.create_tokens(self.session)
  289. tests.create_tokens_acl(self.session)
  290. headers = {'Authorization': 'token foo_token'}
  291. # Invalid token
  292. output = self.app.post('/api/0/fork', headers=headers)
  293. self.assertEqual(output.status_code, 401)
  294. data = json.loads(output.data)
  295. self.assertDictEqual(
  296. data,
  297. {
  298. "error": "Invalid or expired token. Please visit " \
  299. "https://pagure.org/ to get or renew your API token.",
  300. "error_code": "EINVALIDTOK"
  301. }
  302. )
  303. headers = {'Authorization': 'token aaabbbcccddd'}
  304. # No input
  305. output = self.app.post('/api/0/fork', headers=headers)
  306. self.assertEqual(output.status_code, 400)
  307. data = json.loads(output.data)
  308. self.assertDictEqual(
  309. data,
  310. {
  311. "error": "Invalid or incomplete input submited",
  312. "error_code": "EINVALIDREQ",
  313. }
  314. )
  315. data = {
  316. 'name': 'test',
  317. }
  318. # Incomplete request
  319. output = self.app.post(
  320. '/api/0/fork', data=data, headers=headers)
  321. self.assertEqual(output.status_code, 400)
  322. data = json.loads(output.data)
  323. self.assertDictEqual(
  324. data,
  325. {
  326. "error": "Invalid or incomplete input submited",
  327. "error_code": "EINVALIDREQ",
  328. }
  329. )
  330. data = {
  331. 'repo': 'test',
  332. }
  333. # Valid request
  334. output = self.app.post(
  335. '/api/0/fork/', data=data, headers=headers)
  336. self.assertEqual(output.status_code, 200)
  337. data = json.loads(output.data)
  338. self.assertDictEqual(
  339. data,
  340. {
  341. "message": "Repo \"test\" cloned to \"pingou/test\""
  342. }
  343. )
  344. data = {
  345. 'repo': 'test',
  346. }
  347. # project already forked
  348. output = self.app.post(
  349. '/api/0/fork/', data=data, headers=headers)
  350. self.assertEqual(output.status_code, 400)
  351. data = json.loads(output.data)
  352. self.assertDictEqual(
  353. data,
  354. {
  355. "error": "Repo \"forks/pingou/test\" already exists",
  356. "error_code": "ENOCODE"
  357. }
  358. )
  359. data = {
  360. 'repo': 'test',
  361. 'username': 'pingou',
  362. }
  363. # Fork already exists
  364. output = self.app.post(
  365. '/api/0/fork/', data=data, headers=headers)
  366. self.assertEqual(output.status_code, 400)
  367. data = json.loads(output.data)
  368. self.assertDictEqual(
  369. data,
  370. {
  371. "error": "Repo \"forks/pingou/test\" already exists",
  372. "error_code": "ENOCODE"
  373. }
  374. )
  375. if __name__ == '__main__':
  376. SUITE = unittest.TestLoader().loadTestsFromTestCase(
  377. PagureFlaskApiProjecttests)
  378. unittest.TextTestRunner(verbosity=2).run(SUITE)