db_test.py 15 KB

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