PageRenderTime 47ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/software/jupyter/test/test.py

https://github.com/SlapOS/slapos
Python | 270 lines | 216 code | 28 blank | 26 comment | 6 complexity | 0fac4493ed5fdf4f693107db23087779 MD5 | raw file
  1. ##############################################################################
  2. #
  3. # Copyright (c) 2019 Nexedi SA and Contributors. All Rights Reserved.
  4. #
  5. # WARNING: This program as such is intended to be used by professional
  6. # programmers who take the whole responsibility of assessing all potential
  7. # consequences resulting from its eventual inadequacies and bugs
  8. # End users who are looking for a ready-to-use solution with commercial
  9. # guarantees and support are strongly adviced to contract a Free Software
  10. # Service Company
  11. #
  12. # This program is Free Software; you can redistribute it and/or
  13. # modify it under the terms of the GNU General Public License
  14. # as published by the Free Software Foundation; either version 3
  15. # of the License, or (at your option) any later version.
  16. #
  17. # This program is distributed in the hope that it will be useful,
  18. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. # GNU General Public License for more details.
  21. #
  22. # You should have received a copy of the GNU General Public License
  23. # along with this program; if not, write to the Free Software
  24. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  25. #
  26. ##############################################################################
  27. import http.client
  28. import json
  29. import os
  30. import requests
  31. import sqlite3
  32. from slapos.proxy.db_version import DB_VERSION
  33. from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass
  34. setUpModule, InstanceTestCase = makeModuleSetUpAndTestCaseClass(
  35. os.path.abspath(
  36. os.path.join(os.path.dirname(__file__), '..', 'software.cfg')))
  37. class TestJupyter(InstanceTestCase):
  38. def test(self):
  39. connection_dict = self.computer_partition.getConnectionParameterDict()
  40. self.assertTrue('password' in connection_dict)
  41. password = connection_dict['password']
  42. self.assertEqual(
  43. {
  44. 'jupyter-classic-url': 'https://[%s]:8888/tree' % (self._ipv6_address, ),
  45. 'jupyterlab-url': 'https://[%s]:8888/lab' % (self._ipv6_address, ),
  46. 'password': '%s' % (password, ),
  47. 'url': 'https://[%s]:8888/tree' % (self._ipv6_address, )
  48. },
  49. connection_dict
  50. )
  51. result = requests.get(
  52. connection_dict['url'], verify=False, allow_redirects=False)
  53. self.assertEqual(
  54. [http.client.FOUND, True, '/login?next=%2Ftree'],
  55. [result.status_code, result.is_redirect, result.headers['Location']]
  56. )
  57. result = requests.get(
  58. connection_dict['jupyter-classic-url'],
  59. verify=False, allow_redirects=False)
  60. self.assertEqual(
  61. [http.client.FOUND, True, '/login?next=%2Ftree'],
  62. [result.status_code, result.is_redirect, result.headers['Location']]
  63. )
  64. result = requests.get(
  65. connection_dict['jupyterlab-url'],
  66. verify=False, allow_redirects=False)
  67. self.assertEqual(
  68. [http.client.FOUND, True, '/login?next=%2Flab'],
  69. [result.status_code, result.is_redirect, result.headers['Location']]
  70. )
  71. class TestJupyterAdditional(InstanceTestCase):
  72. @classmethod
  73. def getInstanceParameterDict(cls):
  74. return {
  75. 'frontend-additional-instance-guid': 'SOMETHING'
  76. }
  77. def test(self):
  78. connection_dict = self.computer_partition.getConnectionParameterDict()
  79. result = requests.get(
  80. connection_dict['url'], verify=False, allow_redirects=False)
  81. self.assertEqual(
  82. [http.client.FOUND, True, '/login?next=%2Ftree'],
  83. [result.status_code, result.is_redirect, result.headers['Location']]
  84. )
  85. result = requests.get(
  86. connection_dict['jupyter-classic-url'],
  87. verify=False, allow_redirects=False)
  88. self.assertEqual(
  89. [http.client.FOUND, True, '/login?next=%2Ftree'],
  90. [result.status_code, result.is_redirect, result.headers['Location']]
  91. )
  92. result = requests.get(
  93. connection_dict['jupyterlab-url'],
  94. verify=False, allow_redirects=False)
  95. self.assertEqual(
  96. [http.client.FOUND, True, '/login?next=%2Flab'],
  97. [result.status_code, result.is_redirect, result.headers['Location']]
  98. )
  99. result = requests.get(
  100. connection_dict['url-additional'], verify=False, allow_redirects=False)
  101. self.assertEqual(
  102. [http.client.FOUND, True, '/login?next=%2Ftree'],
  103. [result.status_code, result.is_redirect, result.headers['Location']]
  104. )
  105. result = requests.get(
  106. connection_dict['jupyter-classic-url-additional'],
  107. verify=False, allow_redirects=False)
  108. self.assertEqual(
  109. [http.client.FOUND, True, '/login?next=%2Ftree'],
  110. [result.status_code, result.is_redirect, result.headers['Location']]
  111. )
  112. result = requests.get(
  113. connection_dict['jupyterlab-url-additional'],
  114. verify=False, allow_redirects=False)
  115. self.assertEqual(
  116. [http.client.FOUND, True, '/login?next=%2Flab'],
  117. [result.status_code, result.is_redirect, result.headers['Location']]
  118. )
  119. class TestJupyterPassword(InstanceTestCase):
  120. def test(self):
  121. connection_dict = self.computer_partition.getConnectionParameterDict()
  122. url = connection_dict['url']
  123. with requests.Session() as s:
  124. resp = s.get(url, verify=False)
  125. result = s.post(
  126. resp.url,
  127. verify = False,
  128. data={"_xsrf": s.cookies["_xsrf"], "password": connection_dict['password']}
  129. )
  130. self.assertEqual(
  131. [http.client.OK, url],
  132. [result.status_code, result.url]
  133. )
  134. class SelectMixin(object):
  135. def sqlite3_connect(self):
  136. sqlitedb_file = os.path.join(
  137. os.path.abspath(
  138. os.path.join(
  139. self.slap.instance_directory, os.pardir
  140. )
  141. ), 'var', 'proxy.db'
  142. )
  143. return sqlite3.connect(sqlitedb_file)
  144. def select(self, table, fields=('*',), **where):
  145. db = self.sqlite3_connect()
  146. try:
  147. db.row_factory = lambda cursor, row: {
  148. col[0]: row[idx]
  149. for idx, col in enumerate(cursor.description)
  150. }
  151. return db.execute("SELECT %s FROM %s%s%s" % (
  152. ", ".join(fields),
  153. table, DB_VERSION,
  154. " WHERE " + " AND ".join("%s='%s'" % x for x in where.items())
  155. if where else "",
  156. )).fetchall()
  157. finally:
  158. db.close()
  159. class TestJupyterCustomFrontend(SelectMixin, InstanceTestCase):
  160. instance_parameter_dict = {}
  161. frontend_software_url = 'hello://frontend.url'
  162. frontend_software_type = 'hello-type'
  163. frontend_instance_name = 'Hello Frontend'
  164. @classmethod
  165. def getInstanceParameterDict(cls):
  166. return cls.instance_parameter_dict
  167. def test(self):
  168. # create a fake master instance for the frontend slave request
  169. r = self.slap.request(
  170. software_release=self.frontend_software_url,
  171. software_type=self.frontend_software_type,
  172. partition_reference= "Fake master instance",
  173. )
  174. # update the request parameters of the test instance
  175. self.instance_parameter_dict.update({
  176. 'frontend-software-url': self.frontend_software_url,
  177. 'frontend-software-type': self.frontend_software_type,
  178. 'frontend-instance-name': self.frontend_instance_name,
  179. 'frontend-instance-guid': r._partition_id,
  180. })
  181. self.requestDefaultInstance()
  182. # wait for the instance to converge to the new state
  183. try:
  184. self.slap.waitForInstance()
  185. except Exception:
  186. pass
  187. selection = self.select("slave", hosted_by=r._partition_id)
  188. self.assertEqual(len(selection), 1)
  189. # clean up the fake master
  190. r.destroyed()
  191. class TestJupyterCustomAdditional(SelectMixin, InstanceTestCase):
  192. instance_parameter_dict = {}
  193. frontend_additional_software_url = 'hello://frontend.url'
  194. frontend_additional_software_type = 'hello-type'
  195. frontend_additional_instance_name = 'Hello Frontend'
  196. @classmethod
  197. def getInstanceParameterDict(cls):
  198. return cls.instance_parameter_dict
  199. def test(self):
  200. # create a fake master instance for the frontend slave request
  201. r = self.slap.request(
  202. software_release=self.frontend_additional_software_url,
  203. software_type=self.frontend_additional_software_type,
  204. partition_reference= "Fake master instance",
  205. )
  206. # update the request parameters of the test instance
  207. self.instance_parameter_dict.update({
  208. 'frontend-additional-software-url': self.frontend_additional_software_url,
  209. 'frontend-additional-software-type': self.frontend_additional_software_type,
  210. 'frontend-additional-instance-name': self.frontend_additional_instance_name,
  211. 'frontend-additional-instance-guid': r._partition_id,
  212. })
  213. self.requestDefaultInstance()
  214. # wait for the instance to converge to the new state
  215. try:
  216. self.slap.waitForInstance()
  217. except Exception:
  218. pass
  219. selection = self.select("slave", hosted_by=r._partition_id)
  220. self.assertEqual(len(selection), 1)
  221. # clean up the fake master
  222. r.destroyed()