db_test.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. from base_test import DakTestCase, fixture
  2. from daklib.config import Config
  3. from daklib.dbconn import *
  4. from sqlalchemy import create_engine, func, __version__
  5. from sqlalchemy.schema import DDL
  6. import pickle
  7. all_tables = [
  8. 'acl', 'acl_architecture_map', 'acl_fingerprint_map', 'acl_per_source',
  9. 'architecture', 'archive', 'bin_associations', 'bin_contents', 'binaries',
  10. 'binaries_metadata', 'build_queue', 'changelogs_text', 'changes',
  11. 'component', 'component_suite', 'config', 'dsc_files', 'external_files',
  12. 'external_overrides', 'external_signature_requests', 'extra_src_references',
  13. 'files', 'files_archive_map', 'fingerprint', 'hashfile', 'keyrings',
  14. 'maintainer', 'metadata_keys', 'new_comments', 'override', 'override_type',
  15. 'policy_queue', 'policy_queue_byhand_file', 'policy_queue_upload',
  16. 'policy_queue_upload_binaries_map', 'priority', 'section',
  17. 'signature_history', 'source', 'source_metadata', 'src_associations',
  18. 'src_contents', 'src_format', 'src_uploaders', 'suite', 'suite_acl_map',
  19. 'suite_architectures', 'suite_build_queue_copy', 'suite_permission',
  20. 'suite_src_formats', 'uid', 'version_check',
  21. ]
  22. class DBDakTestCase(DakTestCase):
  23. def execute(self, statement):
  24. DDL(statement).execute(self.metadata.bind)
  25. metadata = None
  26. def initialize(self):
  27. cnf = Config()
  28. if cnf["DB::Name"] in ('backports', 'obscurity', 'projectb'):
  29. self.fail("You have configured an invalid database name: '%s'." %
  30. cnf["DB::Name"])
  31. if cnf["DB::Host"]:
  32. # TCP/IP
  33. connstr = "postgresql://%s" % cnf["DB::Host"]
  34. if cnf["DB::Port"] and cnf["DB::Port"] != "-1":
  35. connstr += ":%s" % cnf["DB::Port"]
  36. connstr += "/%s" % cnf["DB::Name"]
  37. else:
  38. # Unix Socket
  39. connstr = "postgresql:///%s" % cnf["DB::Name"]
  40. if cnf["DB::Port"] and cnf["DB::Port"] != "-1":
  41. connstr += "?port=%s" % cnf["DB::Port"]
  42. self.metadata = DBConn().db_meta
  43. self.metadata.bind = create_engine(connstr)
  44. self.metadata.create_all()
  45. def setup_archive(self):
  46. if 'archive' in self.__dict__:
  47. return
  48. self.archive = self.session.query(Archive).get(1)
  49. def setup_suites(self, suites=None):
  50. "setup a hash of Suite objects in self.suite"
  51. if 'suite' in self.__dict__:
  52. return
  53. # Default suites. Can be overridden by passing a parameter with a list
  54. # of suite names and codenames.
  55. if not suites:
  56. suites = [('lenny', ''), ('squeeze', ''), ('sid', '')]
  57. self.setup_archive()
  58. self.suite = {}
  59. for suite_name, codename in suites:
  60. self.suite[suite_name] = get_suite(suite_name, self.session)
  61. if not self.suite[suite_name]:
  62. self.suite[suite_name] = Suite(suite_name=suite_name, version='-')
  63. self.suite[suite_name].archive_id = self.archive.archive_id
  64. self.suite[suite_name].codename = codename
  65. self.session.add(self.suite[suite_name])
  66. def setup_architectures(self):
  67. "setup Architecture objects in self.arch and connect to suites"
  68. if 'arch' in self.__dict__:
  69. return
  70. self.setup_suites()
  71. self.arch = {}
  72. for arch_string in ('source', 'all', 'i386', 'amd64', 'kfreebsd-i386'):
  73. self.arch[arch_string] = get_architecture(arch_string, self.session)
  74. if not self.arch[arch_string]:
  75. self.arch[arch_string] = Architecture(arch_string)
  76. if arch_string != 'kfreebsd-i386':
  77. self.arch[arch_string].suites = list(self.suite.values())
  78. else:
  79. filtered = list(self.suite.values())
  80. if 'lenny' in self.suite:
  81. filtered.remove(self.suite['lenny'])
  82. self.arch[arch_string].suites = filtered
  83. self.session.add_all(self.arch.values())
  84. def setup_components(self):
  85. 'create some Component objects'
  86. if 'comp' in self.__dict__:
  87. return
  88. self.comp = {}
  89. for name in ('main', 'contrib', 'non-free'):
  90. self.comp[name] = get_component(name, self.session)
  91. if not self.comp[name]:
  92. self.comp[name] = Component(component_name=name)
  93. self.session.add(self.comp[name])
  94. def setup_poolfiles(self):
  95. 'create some PoolFile objects'
  96. if 'file' in self.__dict__:
  97. return
  98. self.setup_archive()
  99. self.setup_components()
  100. self.file = {}
  101. self.file['hello_2.2-3.dsc'] = PoolFile(filename='h/hello/hello_2.2-3.dsc',
  102. filesize=0, md5sum='')
  103. self.file['hello_2.2-2.dsc'] = PoolFile(filename='h/hello/hello_2.2-2.dsc',
  104. filesize=0, md5sum='')
  105. self.file['hello_2.2-1.dsc'] = PoolFile(filename='h/hello/hello_2.2-1.dsc',
  106. filesize=0, md5sum='')
  107. self.file['gnome-hello_3.0-1.dsc'] = PoolFile(
  108. filename='g/gnome-hello/gnome-hello_3.0-1.dsc',
  109. filesize=0, md5sum='')
  110. self.file['hello_2.2-1_i386.deb'] = PoolFile(
  111. filename='h/hello/hello_2.2-1_i386.deb',
  112. filesize=0, md5sum='')
  113. self.file['gnome-hello_2.2-1_i386.deb'] = PoolFile(
  114. filename='h/hello/gnome-hello_2.2-1_i386.deb',
  115. filesize=0, md5sum='')
  116. self.file['python-hello_2.2-1_all.deb'] = PoolFile(
  117. filename='h/hello/python-hello_2.2-1_all.deb',
  118. filesize=0, md5sum='')
  119. self.file['gnome-hello_3.0-1_i386.deb'] = PoolFile(
  120. filename='g/gnome-hello/gnome-hello_3.0-1_i386.deb',
  121. filesize=0, md5sum='')
  122. self.file['sl_3.03-16.dsc'] = PoolFile(filename='s/sl/sl_3.03-16.dsc',
  123. filesize=0, md5sum='')
  124. self.file['python2.6_2.6.6-8.dsc'] = PoolFile(
  125. filename='p/python2.6/python2.6_2.6.6-8.dsc',
  126. filesize=0, md5sum='')
  127. archive_files = []
  128. for f in self.file.values():
  129. f.sha1sum = 'sha1sum'
  130. f.sha256sum = 'sha256sum'
  131. if 'gnome-hello_3.0-1' not in f.filename:
  132. archive_files.append(ArchiveFile(
  133. archive=self.archive, component=self.comp['main'], file=f))
  134. else:
  135. archive_files.append(ArchiveFile(
  136. archive=self.archive, component=self.comp['contrib'], file=f))
  137. self.session.add_all(self.file.values())
  138. self.session.add_all(archive_files)
  139. def setup_maintainers(self):
  140. 'create some Maintainer objects'
  141. if 'maintainer' in self.__dict__:
  142. return
  143. self.maintainer = {}
  144. self.maintainer['maintainer'] = get_or_set_maintainer('Mr. Maintainer', self.session)
  145. self.maintainer['uploader'] = get_or_set_maintainer('Mrs. Uploader', self.session)
  146. self.maintainer['lazyguy'] = get_or_set_maintainer('Lazy Guy', self.session)
  147. def setup_sources(self):
  148. 'create DBSource objects'
  149. if 'source' in self.__dict__:
  150. return
  151. install_date = self.now()
  152. self.setup_maintainers()
  153. self.setup_suites()
  154. self.setup_poolfiles()
  155. self.source = {}
  156. self.source['hello_2.2-2'] = DBSource(source='hello', version='2.2-2',
  157. maintainer=self.maintainer['maintainer'],
  158. changedby=self.maintainer['uploader'],
  159. poolfile=self.file['hello_2.2-2.dsc'], install_date=install_date)
  160. self.source['hello_2.2-2'].suites.append(self.suite['sid'])
  161. self.source['hello_2.2-1'] = DBSource(source='hello', version='2.2-1',
  162. maintainer=self.maintainer['maintainer'],
  163. changedby=self.maintainer['uploader'],
  164. poolfile=self.file['hello_2.2-1.dsc'], install_date=install_date)
  165. self.source['hello_2.2-1'].suites.append(self.suite['sid'])
  166. self.source['gnome-hello_3.0-1'] = DBSource(source='gnome-hello',
  167. version='3.0-1', maintainer=self.maintainer['maintainer'],
  168. changedby=self.maintainer['uploader'],
  169. poolfile=self.file['gnome-hello_3.0-1.dsc'], install_date=install_date)
  170. self.source['gnome-hello_3.0-1'].suites.append(self.suite['sid'])
  171. self.source['sl_3.03-16'] = DBSource(source='sl', version='3.03-16',
  172. maintainer=self.maintainer['maintainer'],
  173. changedby=self.maintainer['uploader'],
  174. poolfile=self.file['sl_3.03-16.dsc'], install_date=install_date)
  175. self.source['sl_3.03-16'].suites.append(self.suite['squeeze'])
  176. self.source['sl_3.03-16'].suites.append(self.suite['sid'])
  177. self.session.add_all(self.source.values())
  178. def setup_binaries(self):
  179. 'create DBBinary objects'
  180. if 'binary' in self.__dict__:
  181. return
  182. self.setup_sources()
  183. self.setup_architectures()
  184. self.binary = {}
  185. self.binary['hello_2.2-1_i386'] = DBBinary(package='hello',
  186. source=self.source['hello_2.2-1'], version='2.2-1',
  187. maintainer=self.maintainer['maintainer'],
  188. architecture=self.arch['i386'],
  189. poolfile=self.file['hello_2.2-1_i386.deb'])
  190. self.binary['hello_2.2-1_i386'].suites.append(self.suite['squeeze'])
  191. self.binary['hello_2.2-1_i386'].suites.append(self.suite['sid'])
  192. self.binary['gnome-hello_2.2-1_i386'] = DBBinary(package='gnome-hello',
  193. source=self.source['hello_2.2-1'], version='2.2-1',
  194. maintainer=self.maintainer['maintainer'],
  195. architecture=self.arch['i386'],
  196. poolfile=self.file['gnome-hello_2.2-1_i386.deb'])
  197. self.binary['gnome-hello_2.2-1_i386'].suites.append(self.suite['squeeze'])
  198. self.binary['gnome-hello_2.2-1_i386'].suites.append(self.suite['sid'])
  199. self.binary['gnome-hello_3.0-1_i386'] = DBBinary(package='gnome-hello',
  200. source=self.source['gnome-hello_3.0-1'], version='3.0-1',
  201. maintainer=self.maintainer['maintainer'],
  202. architecture=self.arch['i386'],
  203. poolfile=self.file['gnome-hello_3.0-1_i386.deb'])
  204. self.binary['gnome-hello_3.0-1_i386'].suites.append(self.suite['sid'])
  205. self.binary['python-hello_2.2-1_i386'] = DBBinary(package='python-hello',
  206. source=self.source['hello_2.2-1'], version='2.2-1',
  207. maintainer=self.maintainer['maintainer'],
  208. architecture=self.arch['all'],
  209. poolfile=self.file['python-hello_2.2-1_all.deb'])
  210. self.binary['python-hello_2.2-1_i386'].suites.append(self.suite['squeeze'])
  211. self.session.add_all(self.binary.values())
  212. def setup_overridetypes(self):
  213. '''
  214. Setup self.otype of class OverrideType.
  215. '''
  216. if 'otype' in self.__dict__:
  217. return
  218. self.otype = {}
  219. for type_ in ('deb', 'udeb'):
  220. self.otype[type_] = get_override_type(type_, self.session)
  221. def setup_sections(self):
  222. '''
  223. Setup self.section of class Section.
  224. '''
  225. if 'section' in self.__dict__:
  226. return
  227. self.section = {}
  228. self.section['python'] = get_section('python', self.session)
  229. def setup_priorities(self):
  230. '''
  231. Setup self.prio of class Priority.
  232. '''
  233. if 'prio' in self.__dict__:
  234. return
  235. self.prio = {}
  236. self.prio['standard'] = get_priority('standard', self.session)
  237. def setup_overrides(self):
  238. '''
  239. Setup self.override of class Override.
  240. '''
  241. if 'override' in self.__dict__:
  242. return
  243. self.setup_suites()
  244. self.setup_components()
  245. self.setup_overridetypes()
  246. self.setup_sections()
  247. self.setup_priorities()
  248. self.override = {}
  249. self.override['hello_sid_main_udeb'] = Override(package='hello',
  250. suite=self.suite['sid'], component=self.comp['main'],
  251. overridetype=self.otype['udeb'],
  252. section=self.section['python'], priority=self.prio['standard'])
  253. self.override['hello_squeeze_main_deb'] = Override(package='hello',
  254. suite=self.suite['squeeze'], component=self.comp['main'],
  255. overridetype=self.otype['deb'],
  256. section=self.section['python'], priority=self.prio['standard'])
  257. self.override['hello_lenny_contrib_deb'] = Override(package='hello',
  258. suite=self.suite['lenny'], component=self.comp['contrib'],
  259. overridetype=self.otype['deb'],
  260. section=self.section['python'], priority=self.prio['standard'])
  261. self.session.add_all(self.override.values())
  262. self.session.flush()
  263. def setUp(self):
  264. if self.metadata is None:
  265. self.initialize()
  266. self.session = DBConn().session()
  267. def now(self):
  268. """
  269. Returns the current time at the db server. Please note the function
  270. returns the same value as long as it is in the same transaction. You
  271. should self.session.rollback() (or commit) if you rely on getting a
  272. fresh timestamp.
  273. """
  274. return self.session.query(func.now()).scalar()
  275. def classes_to_clean(self):
  276. """
  277. The function classes_to_clean() returns a list of classes. All objects
  278. of each class will be deleted from the database in tearDown(). This
  279. function should be overridden in derived test cases as needed.
  280. """
  281. return ()
  282. def clean_suites(self):
  283. for suite in self.suite.values():
  284. self.session.delete(suite)
  285. def tearDown(self):
  286. self.session.rollback()
  287. for class_ in self.classes_to_clean():
  288. for object_ in self.session.query(class_):
  289. self.session.delete(object_)
  290. self.session.commit()
  291. # usually there is no need to drop all tables here
  292. # self.metadata.drop_all()