test_postgresql.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import os
  2. import infra.basetest
  3. class TestPostgreSQL(infra.basetest.BRTest):
  4. # We use a specific configuration for:
  5. # - using Aarch64, to have more than 256MB memory,
  6. # - to have an ext4 rootfs image exposed as a virtio storage
  7. # (rather than cpio initrd). This will save some memory, as the
  8. # rootfs image is big.
  9. config = \
  10. """
  11. BR2_aarch64=y
  12. BR2_TOOLCHAIN_EXTERNAL=y
  13. BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0"
  14. BR2_LINUX_KERNEL=y
  15. BR2_LINUX_KERNEL_CUSTOM_VERSION=y
  16. BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.1.72"
  17. BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
  18. BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config"
  19. BR2_PACKAGE_POSTGRESQL=y
  20. BR2_TARGET_ROOTFS_EXT2=y
  21. BR2_TARGET_ROOTFS_EXT2_4=y
  22. BR2_TARGET_ROOTFS_EXT2_SIZE="256M"
  23. # BR2_TARGET_ROOTFS_TAR is not set
  24. """
  25. def __init__(self, names):
  26. super(TestPostgreSQL, self).__init__(names)
  27. self.db_admin = "postgres"
  28. self.db_user = "br_user"
  29. self.db_name = "br_database"
  30. self.backup_file = "dump.sql"
  31. self.pgdata_dir = "/var/lib/pgsql"
  32. def run_user_db_query(self, user, database, query, opts=None):
  33. cmd = f"psql --username={user} --dbname={database}"
  34. cmd += f' --command="{query}"'
  35. if opts is not None:
  36. cmd += " " + opts
  37. self.assertRunOk(cmd)
  38. def run_admin_sql_query(self, query, opts=None):
  39. self.run_user_db_query(self.db_admin, self.db_admin, query, opts)
  40. def run_sql_query(self, query, opts=None):
  41. self.run_user_db_query(self.db_user, self.db_name, query, opts)
  42. def cleanup_database(self):
  43. # This cleanup is useful when run-test -k is used. It makes
  44. # this test idempotent. Since the drive storage is preserved
  45. # between reboots, this cleanup will prevent errors during the
  46. # user/db creation.
  47. # Drop the test database, if it exists.
  48. cmd = f"dropdb --username={self.db_admin} "
  49. cmd += f"--if-exists {self.db_name}"
  50. self.assertRunOk(cmd)
  51. # Drop the test user, if it exists.
  52. cmd = f"dropuser --username={self.db_admin} "
  53. cmd += f"--if-exists {self.db_user}"
  54. self.assertRunOk(cmd)
  55. def create_tables(self):
  56. sql_query = "CREATE TABLE fruits ("
  57. sql_query += "id integer PRIMARY KEY, name varchar(16) NOT NULL);"
  58. self.run_sql_query(sql_query)
  59. sql_query = "CREATE TABLE colors ("
  60. sql_query += "id integer PRIMARY KEY, name varchar(16) NOT NULL);"
  61. self.run_sql_query(sql_query)
  62. sql_query = "CREATE TABLE fruit_colors ("
  63. sql_query += "fruit_id integer REFERENCES fruits(id), "
  64. sql_query += "color_id integer REFERENCES colors(id), "
  65. sql_query += "UNIQUE (fruit_id, color_id));"
  66. self.run_sql_query(sql_query)
  67. def insert_data(self):
  68. fruits = ["Banana", "Blueberry", "Orange", "Raspberry"]
  69. fruit_id = 1
  70. for fruit in fruits:
  71. sql_query = "INSERT INTO fruits (id, name) "
  72. sql_query += f"VALUES ({fruit_id}, '{fruit}');"
  73. self.run_sql_query(sql_query)
  74. fruit_id += 1
  75. colors = ["Blue", "Orange", "Red", "Yellow"]
  76. color_id = 1
  77. for color in colors:
  78. sql_query = "INSERT INTO colors (id, name) "
  79. sql_query += f"VALUES ({color_id}, '{color}');"
  80. self.run_sql_query(sql_query)
  81. color_id += 1
  82. fruit_colors = [(1, 4), (2, 1), (3, 2), (4, 3)]
  83. for fruit_color in fruit_colors:
  84. fruit_id, color_id = fruit_color
  85. sql_query = "INSERT INTO fruit_colors (fruit_id, color_id) "
  86. sql_query += f"VALUES ({fruit_id}, {color_id});"
  87. self.run_sql_query(sql_query)
  88. def query_database(self):
  89. sql_query = "SELECT "
  90. sql_query += "fruits.name AS fruit, colors.name AS color "
  91. sql_query += "FROM fruits, colors, fruit_colors "
  92. sql_query += "WHERE fruits.id = fruit_colors.fruit_id "
  93. sql_query += "AND colors.id = fruit_colors.color_id "
  94. sql_query += "ORDER BY fruit;"
  95. self.run_sql_query(sql_query)
  96. def test_run(self):
  97. drive = os.path.join(self.builddir, "images", "rootfs.ext4")
  98. kern = os.path.join(self.builddir, "images", "Image")
  99. self.emulator.boot(arch="aarch64",
  100. kernel=kern,
  101. kernel_cmdline=["root=/dev/vda console=ttyAMA0"],
  102. options=["-M", "virt",
  103. "-cpu", "cortex-a57",
  104. "-m", "512M",
  105. "-smp", "2",
  106. "-drive", f"file={drive},if=virtio,format=raw"])
  107. self.emulator.login()
  108. # Check the server binary can execute.
  109. self.assertRunOk("postgres --version")
  110. # Check the client binary can execute.
  111. self.assertRunOk("psql --version")
  112. # Check the server is ready.
  113. self.assertRunOk("pg_isready")
  114. # Query the server version from the client.
  115. sql_query = "SELECT version();"
  116. self.run_admin_sql_query(sql_query,
  117. opts="--tuples-only --no-align")
  118. self.cleanup_database()
  119. # Create a new user.
  120. cmd = f"createuser --username={self.db_admin} "
  121. cmd += "--no-superuser --no-createdb --no-createrole "
  122. cmd += self.db_user
  123. self.assertRunOk(cmd)
  124. # Create a new database.
  125. cmd = f"createdb --username={self.db_admin} "
  126. cmd += f"--owner={self.db_user} "
  127. cmd += f'{self.db_name} "Test Database for Buildroot Test"'
  128. self.assertRunOk(cmd)
  129. self.create_tables()
  130. self.insert_data()
  131. self.query_database()
  132. # Update a table.
  133. sql_query = "UPDATE fruits SET name = 'Lemon' WHERE id = 1;"
  134. self.run_sql_query(sql_query)
  135. # Backup the test database.
  136. cmd = f"pg_dump --username={self.db_user} --dbname={self.db_name} "
  137. cmd += f"--file={self.backup_file} --inserts"
  138. self.assertRunOk(cmd)
  139. # Drop all the tables.
  140. sql_query = "DROP TABLE fruit_colors, fruits, colors;"
  141. self.run_sql_query(sql_query)
  142. # Query the server status.
  143. cmd = f"su - {self.db_admin} -c 'pg_ctl status -D {self.pgdata_dir}'"
  144. self.assertRunOk(cmd)
  145. # Stop the server.
  146. cmd = f"su - {self.db_admin} -c 'pg_ctl stop -D {self.pgdata_dir}'"
  147. self.assertRunOk(cmd)
  148. # Check the server is no longer ready.
  149. _, exit_code = self.emulator.run("pg_isready")
  150. self.assertNotEqual(exit_code, 0)
  151. # Restart the server.
  152. cmd = f"su - {self.db_admin} -c 'pg_ctl start -D {self.pgdata_dir}'"
  153. self.assertRunOk(cmd)
  154. # Restore the backup.
  155. cmd = f"psql --username={self.db_user} --dbname={self.db_name} "
  156. cmd += f"--file={self.backup_file}"
  157. self.assertRunOk(cmd)
  158. # Query on last time our data, to check the backup restoration
  159. # succeeded.
  160. self.query_database()