diff options
| author | Joshua Watt <JPEWhacker@gmail.com> | 2023-11-03 08:26:35 -0600 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2023-11-09 17:33:03 +0000 |
| commit | 92a9d6d55ddb64a12be4ad38e2ed4280ce59ba8e (patch) | |
| tree | d2f52f6c5be0237a7bb120dccfec0f3a031b2332 /bitbake/lib | |
| parent | c1574ae46f7a5701d79f2c1d333094a5d5919a46 (diff) | |
| download | poky-92a9d6d55ddb64a12be4ad38e2ed4280ce59ba8e.tar.gz | |
bitbake: hashserv: test: Add bitbake-hashclient tests
The bitbake-hashclient command-line tool now has a lot more features
which should be tested, so add some tests for them.
(Bitbake rev: 178cf99673d7ddf8e0bb63a5a43331a18f3286d5)
Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib')
| -rw-r--r-- | bitbake/lib/hashserv/tests.py | 300 |
1 files changed, 277 insertions, 23 deletions
diff --git a/bitbake/lib/hashserv/tests.py b/bitbake/lib/hashserv/tests.py index fc69acaf7c..a80ccd57e1 100644 --- a/bitbake/lib/hashserv/tests.py +++ b/bitbake/lib/hashserv/tests.py | |||
| @@ -19,6 +19,14 @@ import unittest | |||
| 19 | import socket | 19 | import socket |
| 20 | import time | 20 | import time |
| 21 | import signal | 21 | import signal |
| 22 | import subprocess | ||
| 23 | import json | ||
| 24 | import re | ||
| 25 | from pathlib import Path | ||
| 26 | |||
| 27 | |||
| 28 | THIS_DIR = Path(__file__).parent | ||
| 29 | BIN_DIR = THIS_DIR.parent.parent / "bin" | ||
| 22 | 30 | ||
| 23 | def server_prefunc(server, idx): | 31 | def server_prefunc(server, idx): |
| 24 | logging.basicConfig(level=logging.DEBUG, filename='bbhashserv-%d.log' % idx, filemode='w', | 32 | logging.basicConfig(level=logging.DEBUG, filename='bbhashserv-%d.log' % idx, filemode='w', |
| @@ -103,8 +111,22 @@ class HashEquivalenceTestSetup(object): | |||
| 103 | result = client.get_unihash(self.METHOD, taskhash) | 111 | result = client.get_unihash(self.METHOD, taskhash) |
| 104 | self.assertEqual(result, unihash) | 112 | self.assertEqual(result, unihash) |
| 105 | 113 | ||
| 114 | def assertUserPerms(self, user, permissions): | ||
| 115 | with self.auth_client(user) as client: | ||
| 116 | info = client.get_user() | ||
| 117 | self.assertEqual(info, { | ||
| 118 | "username": user["username"], | ||
| 119 | "permissions": permissions, | ||
| 120 | }) | ||
| 121 | |||
| 122 | def assertUserCanAuth(self, user): | ||
| 123 | with self.start_client(self.auth_server.address) as client: | ||
| 124 | client.auth(user["username"], user["token"]) | ||
| 125 | |||
| 126 | def assertUserCannotAuth(self, user): | ||
| 127 | with self.start_client(self.auth_server.address) as client, self.assertRaises(InvokeError): | ||
| 128 | client.auth(user["username"], user["token"]) | ||
| 106 | 129 | ||
| 107 | class HashEquivalenceCommonTests(object): | ||
| 108 | def create_test_hash(self, client): | 130 | def create_test_hash(self, client): |
| 109 | # Simple test that hashes can be created | 131 | # Simple test that hashes can be created |
| 110 | taskhash = '35788efcb8dfb0a02659d81cf2bfd695fb30faf9' | 132 | taskhash = '35788efcb8dfb0a02659d81cf2bfd695fb30faf9' |
| @@ -117,6 +139,24 @@ class HashEquivalenceCommonTests(object): | |||
| 117 | self.assertEqual(result['unihash'], unihash, 'Server returned bad unihash') | 139 | self.assertEqual(result['unihash'], unihash, 'Server returned bad unihash') |
| 118 | return taskhash, outhash, unihash | 140 | return taskhash, outhash, unihash |
| 119 | 141 | ||
| 142 | def run_hashclient(self, args, **kwargs): | ||
| 143 | try: | ||
| 144 | p = subprocess.run( | ||
| 145 | [BIN_DIR / "bitbake-hashclient"] + args, | ||
| 146 | stdout=subprocess.PIPE, | ||
| 147 | stderr=subprocess.STDOUT, | ||
| 148 | encoding="utf-8", | ||
| 149 | **kwargs | ||
| 150 | ) | ||
| 151 | except subprocess.CalledProcessError as e: | ||
| 152 | print(e.output) | ||
| 153 | raise e | ||
| 154 | |||
| 155 | print(p.stdout) | ||
| 156 | return p | ||
| 157 | |||
| 158 | |||
| 159 | class HashEquivalenceCommonTests(object): | ||
| 120 | def test_create_hash(self): | 160 | def test_create_hash(self): |
| 121 | return self.create_test_hash(self.client) | 161 | return self.create_test_hash(self.client) |
| 122 | 162 | ||
| @@ -161,7 +201,7 @@ class HashEquivalenceCommonTests(object): | |||
| 161 | self.assertClientGetHash(self.client, taskhash, unihash) | 201 | self.assertClientGetHash(self.client, taskhash, unihash) |
| 162 | 202 | ||
| 163 | def test_remove_taskhash(self): | 203 | def test_remove_taskhash(self): |
| 164 | taskhash, outhash, unihash = self.test_create_hash() | 204 | taskhash, outhash, unihash = self.create_test_hash(self.client) |
| 165 | result = self.client.remove({"taskhash": taskhash}) | 205 | result = self.client.remove({"taskhash": taskhash}) |
| 166 | self.assertGreater(result["count"], 0) | 206 | self.assertGreater(result["count"], 0) |
| 167 | self.assertClientGetHash(self.client, taskhash, None) | 207 | self.assertClientGetHash(self.client, taskhash, None) |
| @@ -170,13 +210,13 @@ class HashEquivalenceCommonTests(object): | |||
| 170 | self.assertIsNone(result_outhash) | 210 | self.assertIsNone(result_outhash) |
| 171 | 211 | ||
| 172 | def test_remove_unihash(self): | 212 | def test_remove_unihash(self): |
| 173 | taskhash, outhash, unihash = self.test_create_hash() | 213 | taskhash, outhash, unihash = self.create_test_hash(self.client) |
| 174 | result = self.client.remove({"unihash": unihash}) | 214 | result = self.client.remove({"unihash": unihash}) |
| 175 | self.assertGreater(result["count"], 0) | 215 | self.assertGreater(result["count"], 0) |
| 176 | self.assertClientGetHash(self.client, taskhash, None) | 216 | self.assertClientGetHash(self.client, taskhash, None) |
| 177 | 217 | ||
| 178 | def test_remove_outhash(self): | 218 | def test_remove_outhash(self): |
| 179 | taskhash, outhash, unihash = self.test_create_hash() | 219 | taskhash, outhash, unihash = self.create_test_hash(self.client) |
| 180 | result = self.client.remove({"outhash": outhash}) | 220 | result = self.client.remove({"outhash": outhash}) |
| 181 | self.assertGreater(result["count"], 0) | 221 | self.assertGreater(result["count"], 0) |
| 182 | 222 | ||
| @@ -184,7 +224,7 @@ class HashEquivalenceCommonTests(object): | |||
| 184 | self.assertIsNone(result_outhash) | 224 | self.assertIsNone(result_outhash) |
| 185 | 225 | ||
| 186 | def test_remove_method(self): | 226 | def test_remove_method(self): |
| 187 | taskhash, outhash, unihash = self.test_create_hash() | 227 | taskhash, outhash, unihash = self.create_test_hash(self.client) |
| 188 | result = self.client.remove({"method": self.METHOD}) | 228 | result = self.client.remove({"method": self.METHOD}) |
| 189 | self.assertGreater(result["count"], 0) | 229 | self.assertGreater(result["count"], 0) |
| 190 | self.assertClientGetHash(self.client, taskhash, None) | 230 | self.assertClientGetHash(self.client, taskhash, None) |
| @@ -193,7 +233,7 @@ class HashEquivalenceCommonTests(object): | |||
| 193 | self.assertIsNone(result_outhash) | 233 | self.assertIsNone(result_outhash) |
| 194 | 234 | ||
| 195 | def test_clean_unused(self): | 235 | def test_clean_unused(self): |
| 196 | taskhash, outhash, unihash = self.test_create_hash() | 236 | taskhash, outhash, unihash = self.create_test_hash(self.client) |
| 197 | 237 | ||
| 198 | # Clean the database, which should not remove anything because all hashes an in-use | 238 | # Clean the database, which should not remove anything because all hashes an in-use |
| 199 | result = self.client.clean_unused(0) | 239 | result = self.client.clean_unused(0) |
| @@ -497,7 +537,7 @@ class HashEquivalenceCommonTests(object): | |||
| 497 | admin_client = self.start_auth_server() | 537 | admin_client = self.start_auth_server() |
| 498 | 538 | ||
| 499 | # Create hashes with non-authenticated server | 539 | # Create hashes with non-authenticated server |
| 500 | taskhash, outhash, unihash = self.test_create_hash() | 540 | taskhash, outhash, unihash = self.create_test_hash(self.client) |
| 501 | 541 | ||
| 502 | # Validate hash can be retrieved using authenticated client | 542 | # Validate hash can be retrieved using authenticated client |
| 503 | with self.auth_perms("@read") as client: | 543 | with self.auth_perms("@read") as client: |
| @@ -534,14 +574,6 @@ class HashEquivalenceCommonTests(object): | |||
| 534 | with self.start_client(self.auth_server.address) as client, self.assertRaises(InvokeError): | 574 | with self.start_client(self.auth_server.address) as client, self.assertRaises(InvokeError): |
| 535 | client.refresh_token() | 575 | client.refresh_token() |
| 536 | 576 | ||
| 537 | def assertUserCanAuth(self, user): | ||
| 538 | with self.start_client(self.auth_server.address) as client: | ||
| 539 | client.auth(user["username"], user["token"]) | ||
| 540 | |||
| 541 | def assertUserCannotAuth(self, user): | ||
| 542 | with self.start_client(self.auth_server.address) as client, self.assertRaises(InvokeError): | ||
| 543 | client.auth(user["username"], user["token"]) | ||
| 544 | |||
| 545 | def test_auth_self_token_refresh(self): | 577 | def test_auth_self_token_refresh(self): |
| 546 | admin_client = self.start_auth_server() | 578 | admin_client = self.start_auth_server() |
| 547 | 579 | ||
| @@ -650,14 +682,6 @@ class HashEquivalenceCommonTests(object): | |||
| 650 | with self.auth_perms("@user-admin") as client, self.assertRaises(InvokeError): | 682 | with self.auth_perms("@user-admin") as client, self.assertRaises(InvokeError): |
| 651 | client.delete_user(user["username"]) | 683 | client.delete_user(user["username"]) |
| 652 | 684 | ||
| 653 | def assertUserPerms(self, user, permissions): | ||
| 654 | with self.auth_client(user) as client: | ||
| 655 | info = client.get_user() | ||
| 656 | self.assertEqual(info, { | ||
| 657 | "username": user["username"], | ||
| 658 | "permissions": permissions, | ||
| 659 | }) | ||
| 660 | |||
| 661 | def test_auth_set_user_perms(self): | 685 | def test_auth_set_user_perms(self): |
| 662 | admin_client = self.start_auth_server() | 686 | admin_client = self.start_auth_server() |
| 663 | 687 | ||
| @@ -785,6 +809,236 @@ class HashEquivalenceCommonTests(object): | |||
| 785 | for col in columns: | 809 | for col in columns: |
| 786 | self.client.remove({col: ""}) | 810 | self.client.remove({col: ""}) |
| 787 | 811 | ||
| 812 | |||
| 813 | class TestHashEquivalenceClient(HashEquivalenceTestSetup, unittest.TestCase): | ||
| 814 | def get_server_addr(self, server_idx): | ||
| 815 | return "unix://" + os.path.join(self.temp_dir.name, 'sock%d' % server_idx) | ||
| 816 | |||
| 817 | def test_stats(self): | ||
| 818 | self.run_hashclient(["--address", self.server_address, "stats"], check=True) | ||
| 819 | |||
| 820 | def test_stress(self): | ||
| 821 | self.run_hashclient(["--address", self.server_address, "stress"], check=True) | ||
| 822 | |||
| 823 | def test_remove_taskhash(self): | ||
| 824 | taskhash, outhash, unihash = self.create_test_hash(self.client) | ||
| 825 | self.run_hashclient([ | ||
| 826 | "--address", self.server_address, | ||
| 827 | "remove", | ||
| 828 | "--where", "taskhash", taskhash, | ||
| 829 | ], check=True) | ||
| 830 | self.assertClientGetHash(self.client, taskhash, None) | ||
| 831 | |||
| 832 | result_outhash = self.client.get_outhash(self.METHOD, outhash, taskhash) | ||
| 833 | self.assertIsNone(result_outhash) | ||
| 834 | |||
| 835 | def test_remove_unihash(self): | ||
| 836 | taskhash, outhash, unihash = self.create_test_hash(self.client) | ||
| 837 | self.run_hashclient([ | ||
| 838 | "--address", self.server_address, | ||
| 839 | "remove", | ||
| 840 | "--where", "unihash", unihash, | ||
| 841 | ], check=True) | ||
| 842 | self.assertClientGetHash(self.client, taskhash, None) | ||
| 843 | |||
| 844 | def test_remove_outhash(self): | ||
| 845 | taskhash, outhash, unihash = self.create_test_hash(self.client) | ||
| 846 | self.run_hashclient([ | ||
| 847 | "--address", self.server_address, | ||
| 848 | "remove", | ||
| 849 | "--where", "outhash", outhash, | ||
| 850 | ], check=True) | ||
| 851 | |||
| 852 | result_outhash = self.client.get_outhash(self.METHOD, outhash, taskhash) | ||
| 853 | self.assertIsNone(result_outhash) | ||
| 854 | |||
| 855 | def test_remove_method(self): | ||
| 856 | taskhash, outhash, unihash = self.create_test_hash(self.client) | ||
| 857 | self.run_hashclient([ | ||
| 858 | "--address", self.server_address, | ||
| 859 | "remove", | ||
| 860 | "--where", "method", self.METHOD, | ||
| 861 | ], check=True) | ||
| 862 | self.assertClientGetHash(self.client, taskhash, None) | ||
| 863 | |||
| 864 | result_outhash = self.client.get_outhash(self.METHOD, outhash, taskhash) | ||
| 865 | self.assertIsNone(result_outhash) | ||
| 866 | |||
| 867 | def test_clean_unused(self): | ||
| 868 | taskhash, outhash, unihash = self.create_test_hash(self.client) | ||
| 869 | |||
| 870 | # Clean the database, which should not remove anything because all hashes an in-use | ||
| 871 | self.run_hashclient([ | ||
| 872 | "--address", self.server_address, | ||
| 873 | "clean-unused", "0", | ||
| 874 | ], check=True) | ||
| 875 | self.assertClientGetHash(self.client, taskhash, unihash) | ||
| 876 | |||
| 877 | # Remove the unihash. The row in the outhash table should still be present | ||
| 878 | self.run_hashclient([ | ||
| 879 | "--address", self.server_address, | ||
| 880 | "remove", | ||
| 881 | "--where", "unihash", unihash, | ||
| 882 | ], check=True) | ||
| 883 | result_outhash = self.client.get_outhash(self.METHOD, outhash, taskhash, False) | ||
| 884 | self.assertIsNotNone(result_outhash) | ||
| 885 | |||
| 886 | # Now clean with no minimum age which will remove the outhash | ||
| 887 | self.run_hashclient([ | ||
| 888 | "--address", self.server_address, | ||
| 889 | "clean-unused", "0", | ||
| 890 | ], check=True) | ||
| 891 | result_outhash = self.client.get_outhash(self.METHOD, outhash, taskhash, False) | ||
| 892 | self.assertIsNone(result_outhash) | ||
| 893 | |||
| 894 | def test_refresh_token(self): | ||
| 895 | admin_client = self.start_auth_server() | ||
| 896 | |||
| 897 | user = admin_client.new_user("test-user", ["@read", "@report"]) | ||
| 898 | |||
| 899 | p = self.run_hashclient([ | ||
| 900 | "--address", self.auth_server.address, | ||
| 901 | "--login", user["username"], | ||
| 902 | "--password", user["token"], | ||
| 903 | "refresh-token" | ||
| 904 | ], check=True) | ||
| 905 | |||
| 906 | new_token = None | ||
| 907 | for l in p.stdout.splitlines(): | ||
| 908 | l = l.rstrip() | ||
| 909 | m = re.match(r'Token: +(.*)$', l) | ||
| 910 | if m is not None: | ||
| 911 | new_token = m.group(1) | ||
| 912 | |||
| 913 | self.assertTrue(new_token) | ||
| 914 | |||
| 915 | print("New token is %r" % new_token) | ||
| 916 | |||
| 917 | self.run_hashclient([ | ||
| 918 | "--address", self.auth_server.address, | ||
| 919 | "--login", user["username"], | ||
| 920 | "--password", new_token, | ||
| 921 | "get-user" | ||
| 922 | ], check=True) | ||
| 923 | |||
| 924 | def test_set_user_perms(self): | ||
| 925 | admin_client = self.start_auth_server() | ||
| 926 | |||
| 927 | user = admin_client.new_user("test-user", ["@read"]) | ||
| 928 | |||
| 929 | self.run_hashclient([ | ||
| 930 | "--address", self.auth_server.address, | ||
| 931 | "--login", admin_client.username, | ||
| 932 | "--password", admin_client.password, | ||
| 933 | "set-user-perms", | ||
| 934 | "-u", user["username"], | ||
| 935 | "@read", "@report", | ||
| 936 | ], check=True) | ||
| 937 | |||
| 938 | new_user = admin_client.get_user(user["username"]) | ||
| 939 | |||
| 940 | self.assertEqual(set(new_user["permissions"]), {"@read", "@report"}) | ||
| 941 | |||
| 942 | def test_get_user(self): | ||
| 943 | admin_client = self.start_auth_server() | ||
| 944 | |||
| 945 | user = admin_client.new_user("test-user", ["@read"]) | ||
| 946 | |||
| 947 | p = self.run_hashclient([ | ||
| 948 | "--address", self.auth_server.address, | ||
| 949 | "--login", admin_client.username, | ||
| 950 | "--password", admin_client.password, | ||
| 951 | "get-user", | ||
| 952 | "-u", user["username"], | ||
| 953 | ], check=True) | ||
| 954 | |||
| 955 | self.assertIn("Username:", p.stdout) | ||
| 956 | self.assertIn("Permissions:", p.stdout) | ||
| 957 | |||
| 958 | p = self.run_hashclient([ | ||
| 959 | "--address", self.auth_server.address, | ||
| 960 | "--login", user["username"], | ||
| 961 | "--password", user["token"], | ||
| 962 | "get-user", | ||
| 963 | ], check=True) | ||
| 964 | |||
| 965 | self.assertIn("Username:", p.stdout) | ||
| 966 | self.assertIn("Permissions:", p.stdout) | ||
| 967 | |||
| 968 | def test_get_all_users(self): | ||
| 969 | admin_client = self.start_auth_server() | ||
| 970 | |||
| 971 | admin_client.new_user("test-user1", ["@read"]) | ||
| 972 | admin_client.new_user("test-user2", ["@read"]) | ||
| 973 | |||
| 974 | p = self.run_hashclient([ | ||
| 975 | "--address", self.auth_server.address, | ||
| 976 | "--login", admin_client.username, | ||
| 977 | "--password", admin_client.password, | ||
| 978 | "get-all-users", | ||
| 979 | ], check=True) | ||
| 980 | |||
| 981 | self.assertIn("admin", p.stdout) | ||
| 982 | self.assertIn("test-user1", p.stdout) | ||
| 983 | self.assertIn("test-user2", p.stdout) | ||
| 984 | |||
| 985 | def test_new_user(self): | ||
| 986 | admin_client = self.start_auth_server() | ||
| 987 | |||
| 988 | p = self.run_hashclient([ | ||
| 989 | "--address", self.auth_server.address, | ||
| 990 | "--login", admin_client.username, | ||
| 991 | "--password", admin_client.password, | ||
| 992 | "new-user", | ||
| 993 | "-u", "test-user", | ||
| 994 | "@read", "@report", | ||
| 995 | ], check=True) | ||
| 996 | |||
| 997 | new_token = None | ||
| 998 | for l in p.stdout.splitlines(): | ||
| 999 | l = l.rstrip() | ||
| 1000 | m = re.match(r'Token: +(.*)$', l) | ||
| 1001 | if m is not None: | ||
| 1002 | new_token = m.group(1) | ||
| 1003 | |||
| 1004 | self.assertTrue(new_token) | ||
| 1005 | |||
| 1006 | user = { | ||
| 1007 | "username": "test-user", | ||
| 1008 | "token": new_token, | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | self.assertUserPerms(user, ["@read", "@report"]) | ||
| 1012 | |||
| 1013 | def test_delete_user(self): | ||
| 1014 | admin_client = self.start_auth_server() | ||
| 1015 | |||
| 1016 | user = admin_client.new_user("test-user", ["@read"]) | ||
| 1017 | |||
| 1018 | p = self.run_hashclient([ | ||
| 1019 | "--address", self.auth_server.address, | ||
| 1020 | "--login", admin_client.username, | ||
| 1021 | "--password", admin_client.password, | ||
| 1022 | "delete-user", | ||
| 1023 | "-u", user["username"], | ||
| 1024 | ], check=True) | ||
| 1025 | |||
| 1026 | |||
| 1027 | self.assertIsNone(admin_client.get_user(user["username"])) | ||
| 1028 | |||
| 1029 | def test_get_db_usage(self): | ||
| 1030 | p = self.run_hashclient([ | ||
| 1031 | "--address", self.server_address, | ||
| 1032 | "get-db-usage", | ||
| 1033 | ], check=True) | ||
| 1034 | |||
| 1035 | def test_get_db_query_columns(self): | ||
| 1036 | p = self.run_hashclient([ | ||
| 1037 | "--address", self.server_address, | ||
| 1038 | "get-db-query-columns", | ||
| 1039 | ], check=True) | ||
| 1040 | |||
| 1041 | |||
| 788 | class TestHashEquivalenceUnixServer(HashEquivalenceTestSetup, HashEquivalenceCommonTests, unittest.TestCase): | 1042 | class TestHashEquivalenceUnixServer(HashEquivalenceTestSetup, HashEquivalenceCommonTests, unittest.TestCase): |
| 789 | def get_server_addr(self, server_idx): | 1043 | def get_server_addr(self, server_idx): |
| 790 | return "unix://" + os.path.join(self.temp_dir.name, 'sock%d' % server_idx) | 1044 | return "unix://" + os.path.join(self.temp_dir.name, 'sock%d' % server_idx) |
