OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DdlConcurrencyTest.java
Go to the documentation of this file.
1 /*
2  * Copyright 2023 HEAVY.AI, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.mapd.tests;
17 
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
20 
21 import java.io.File;
22 import java.lang.Integer;
23 import java.lang.String;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.concurrent.CyclicBarrier;
29 
30 public class DdlConcurrencyTest extends ConcurrencyTest {
31  static File scratchDir;
32  static String scratchDirPath;
33 
34  public static void main(String[] args) throws Exception {
35  configure();
36  scratchDir = new File("./scratch");
37  scratchDirPath = scratchDir.getCanonicalPath();
39  test.testConcurrency();
40  }
41 
42  // Configure testing based on command line parameteres.
43  public static void configure() {
44  logger = getLogger();
46  ports = getPorts();
51  logger.info(getConfig());
52  }
53 
54  public static Logger getLogger() {
55  return LoggerFactory.getLogger(DdlConcurrencyTest.class);
56  }
57 
58  public static String getTestName() {
59  return "DdlConcurrencyTest";
60  }
61 
62  // Full list of tests to perform.
63  public List<SqlCommandThread[]> createTestThreads() {
64  logger.info("Initializing test threads...");
65  ArrayList<SqlCommandThread[]> tests = new ArrayList<>();
66  tests.add(makeTests("ShowTable", "SHOW TABLES;"));
67  tests.add(makeTests("ShowTableDetails", "SHOW TABLE DETAILS;"));
68  tests.add(makeTests("ShowCreateTable", "SHOW CREATE TABLE test_table;"));
69  tests.add(makeTests("ShowServers", "SHOW SERVERS;"));
70  tests.add(makeTests("ShowCreateServer", "SHOW CREATE SERVER test_server;"));
71  tests.add(makeTests("ShowFunctions", "SHOW FUNCTIONS;"));
72  tests.add(makeTests("ShowRuntimeFunctions", "SHOW RUNTIME FUNCTIONS;"));
73  tests.add(makeTests("ShowRuntimeTF", "SHOW RUNTIME TABLE FUNCTIONS;"));
74  tests.add(makeTests("AlterDatabase", "ALTER DATABASE " + db + " OWNER TO admin;"));
75  tests.add(makeTests("ShowUserDetails", "SHOW USER DETAILS;"));
76  tests.add(makeTests("ShowRoles", "SHOW ROLES"));
77  tests.add(makeTests("ReassignOwned", "REASSIGN OWNED BY test_user TO admin;"));
78  tests.add(makeTests("CreatePolicy",
79  "CREATE POLICY ON COLUMN test_table.i TO test_user VALUES (1);",
80  "already exists"));
81  tests.add(makeTests("DropPolicy",
82  "DROP POLICY ON COLUMN test_table.i FROM test_user;",
83  "not found"));
84  tests.add(makeTests("ShowPolicy", "SHOW POLICIES test_user;"));
85  tests.add(makeTests("ShowSupportedDataSources", "SHOW POLICIES test_user;"));
86  tests.add(makeTests(
87  "CreateTable", "CREATE TABLE IF NOT EXISTS test_table_<threadId> (i int);"));
88  tests.add(makeTests("DropTable", "DROP TABLE IF EXISTS test_table_<threadId>;"));
89  tests.add(makeTests("InsertTable", "INSERT INTO test_table (i) VALUES (2);"));
90  tests.add(makeTests("UpdateTable", "UPDATE test_table SET i = 3 WHERE i = 2;"));
91  tests.add(makeTests("AddColumn",
92  "ALTER TABLE test_table ADD (x int DEFAULT 1);",
93  "already exists"));
94  tests.add(makeTests(
95  "DropColumn", "ALTER TABLE test_table DROP COLUMN x;", "does not exist"));
96  tests.add(makeTests("RenameTable",
97  "ALTER TABLE test_table_<threadId> RENAME TO altered_table_<threadId>;",
98  Arrays.asList("not exist", "Attempted to overwrite")));
99  tests.add(makeTests("DumpTable",
100  "DUMP TABLE test_table to '" + scratchDirPath + "/dump.gz';",
101  "exists"));
102  tests.add(makeTests("RestoreTable",
103  "RESTORE TABLE restore_table_<threadId> from '" + scratchDirPath
104  + "/dump.gz';",
105  Arrays.asList("does not exist", "exists"),
106  "DROP TABLE IF EXISTS restore_table_<threadId>;"));
107  tests.add(makeTests("TruncateTable", "TRUNCATE TABLE test_table;"));
108  tests.add(makeTests("OptimizeTable", "OPTIMIZE TABLE test_table;"));
109  tests.add(
110  makeTests("CopyFrom", "COPY test_table FROM '../Tests/FsiDataFiles/1.csv';"));
111  tests.add(makeTests("CopyTo",
112  "COPY (SELECT * FROM test_table) TO '" + scratchDirPath + "/copy.csv';",
113  "exists"));
114  tests.add(makeTests("CreateDB",
115  "CREATE DATABASE IF NOT EXISTS test_db_<threadId>;",
116  Collections.emptyList(),
117  "DROP DATABASE IF EXISTS test_db_<threadId>;"));
118  tests.add(makeTests("DropDB", "DROP DATABASE IF EXISTS test_db_<threadId>;"));
119  tests.add(makeTests("CreateUser",
120  "CREATE USER test_user_<threadId> (password = 'pass');",
121  "exists",
122  "DROP USER IF EXISTS test_user_<threadId>;"));
123  tests.add(makeTests("DropUser", "DROP USER IF EXISTS test_user_<threadId>;"));
124  tests.add(makeTests("AlterUser", "ALTER USER test_user (password = 'pass');"));
125  tests.add(makeTests("RenameUser",
126  "ALTER USER test_user_<threadId> RENAME TO altered_user_<threadId>;",
127  Arrays.asList("doesn't exist", "already exists", "does not exist"),
128  "DROP USER IF EXISTS altered_user_<threadId>;"));
129  tests.add(makeTests("CreateRole",
130  "CREATE ROLE test_role_<threadId>;",
131  "already exists",
132  "DROP ROLE IF EXISTS test_role_<threadId>;"));
133  tests.add(makeTests("DropRole", "DROP ROLE IF EXISTS test_role_<threadId>;"));
134  tests.add(makeTests(
135  "GrantRole", "GRANT test_role_<threadId> TO test_user;", "does not exist"));
136  tests.add(makeTests("RevokeRole",
137  "REVOKE test_role_<threadId> FROM test_user;",
138  Arrays.asList("does not exist", "have not been granted")));
139  tests.add(makeTests("ValidateSystem", "Validate"));
140  tests.add(makeTests("CreateView",
141  "CREATE VIEW IF NOT EXISTS test_view_<threadId> AS (SELECT * FROM test_table);"));
142  tests.add(makeTests("DropView", "DROP VIEW IF EXISTS test_view_<threadId>;"));
143  if (enableHeavyConnect) {
144  tests.add(makeTests("CreateServer",
145  "CREATE SERVER IF NOT EXISTS test_server_<threadId> FOREIGN DATA WRAPPER "
146  + "delimited_file WITH (storage_type = 'LOCAL_FILE', base_path = '"
147  + System.getProperty("user.dir") + "');"));
148  tests.add(makeTests("DropServer", "DROP SERVER IF EXISTS test_server_<threadId>;"));
149  tests.add(makeTests("AlterServer",
150  "ALTER SERVER test_server SET (s3_bucket = 'diff_bucket');"));
151  tests.add(makeTests("CreateForeignTable",
152  "CREATE FOREIGN TABLE IF NOT EXISTS test_foreign_table_<threadId> "
153  + "(b BOOLEAN, t TINYINT, s SMALLINT, i INTEGER, bi BIGINT, f FLOAT, "
154  + "dc DECIMAL(10, 5), tm TIME, tp TIMESTAMP, d DATE, txt TEXT, "
155  + "txt_2 TEXT ENCODING NONE) "
156  + "SERVER default_local_delimited WITH "
157  + "(file_path = '../Tests/FsiDataFiles/scalar_types.csv', "
158  + "FRAGMENT_SIZE = 10);"));
159  tests.add(makeTests("DropForeignTable",
160  "DROP FOREIGN TABLE IF EXISTS test_foreign_table_<threadId>;"));
161  tests.add(makeTests("CreateUserMapping",
162  "CREATE USER MAPPING IF NOT EXISTS FOR PUBLIC SERVER test_server WITH "
163  + "(S3_ACCESS_KEY = 'test_key', S3_SECRET_KEY = 'test_key');"));
164  tests.add(makeTests("DropUserMapping",
165  "DROP USER MAPPING IF EXISTS FOR PUBLIC SERVER test_server;"));
166  tests.add(makeTests("AlterForeignTable",
167  "ALTER FOREIGN TABLE test_foreign_table SET (refresh_update_type = 'APPEND');"));
168  tests.add(makeTests("ShowDiskCacheUsage", "SHOW DISK CACHE USAGE;"));
169  tests.add(makeTests("RefreshForeignTable",
170  "REFRESH FOREIGN TABLES test_foreign_table_<threadId>;",
171  "does not exist"));
172  }
173  logger.info("Initialized test threads.");
174  return tests;
175  }
176 
177  // Some tests use custom queries that include the threadID. Here we do a quick
178  // find/replace of the <threadId> symbol with the actual thread id.
179  public static List<String> customizeQueriesByThreadId(
180  final List<String> queries, int threadId) {
181  List<String> customQueries = new ArrayList<String>();
182  for (String query : queries) {
183  customQueries.add(query.replaceAll("<threadId>", Integer.toString(threadId)));
184  }
185  return customQueries;
186  }
187 
188  // Initializes an array of threads that perform the same test, customized by thread id.
189  public final SqlCommandThread[] makeTests(final String threadName,
190  final List<String> queries,
191  final List<String> expectedExceptions,
192  final List<String> cleanUpQueries,
193  int numThreads) {
194  SqlCommandThread[] threadGroup = new SqlCommandThread[numThreads];
195  for (int threadId = 0; threadId < numThreads; ++threadId) {
196  List<String> customQueries = customizeQueriesByThreadId(queries, threadId);
197  List<String> customCleanUps = customizeQueriesByThreadId(cleanUpQueries, threadId);
198  threadGroup[threadId] = new SqlCommandThread(
199  threadName, customQueries, threadId, expectedExceptions, customCleanUps);
200  }
201  return threadGroup;
202  }
203 
204  // Syntactic sugar for common cases.
205  public final SqlCommandThread[] makeTests(final String threadName, final String query) {
206  return makeTests(threadName,
207  Arrays.asList(query),
208  Collections.emptyList(),
209  Collections.emptyList(),
210  numThreads);
211  }
212 
213  // Syntactic sugar for common cases.
214  public final SqlCommandThread[] makeTests(
215  final String threadName, final String query, final String exception) {
216  return makeTests(threadName,
217  Arrays.asList(query),
218  Arrays.asList(exception),
219  Collections.emptyList(),
220  numThreads);
221  }
222 
223  // Syntactic sugar for common cases.
224  public final SqlCommandThread[] makeTests(
225  final String threadName, final String query, final List<String> exceptions) {
226  return makeTests(threadName,
227  Arrays.asList(query),
228  exceptions,
229  Collections.emptyList(),
230  numThreads);
231  }
232 
233  // Syntactic sugar for common cases.
234  public final SqlCommandThread[] makeTests(final String threadName,
235  final String query,
236  final List<String> exceptions,
237  final String cleanUpQueries) {
238  return makeTests(threadName,
239  Arrays.asList(query),
240  exceptions,
241  Arrays.asList(cleanUpQueries),
242  numThreads);
243  }
244 
245  // Syntactic sugar for common cases.
246  public final SqlCommandThread[] makeTests(final String threadName,
247  final String query,
248  final String exceptions,
249  final String cleanUpQueries) {
250  return makeTests(threadName,
251  Arrays.asList(query),
252  Arrays.asList(exceptions),
253  Arrays.asList(cleanUpQueries),
254  numThreads);
255  }
256 
257  @Override
258  public void setUpTests() throws Exception {
259  logger.info("Starting Setup...");
260  scratchDir.mkdirs();
262  runAndLog(heavyAdmin, "DROP DATABASE IF EXISTS " + db + ";");
263  runAndLog(heavyAdmin, "CREATE DATABASE " + db + ";");
265  runAndLog(dbAdmin, "DROP USER IF EXISTS test_user");
266  runAndLog(dbAdmin, "CREATE USER test_user (password = 'pass');");
267  runAndLog(dbAdmin, "CREATE TABLE test_table (i int);");
268  if (enableHeavyConnect) {
269  runAndLog(dbAdmin,
270  "CREATE SERVER test_server FOREIGN DATA WRAPPER delimited_file "
271  + "WITH (storage_type = 'AWS_S3', s3_bucket = 'test_bucket', "
272  + "aws_region = 'test_region');");
273  runAndLog(dbAdmin,
274  "CREATE FOREIGN TABLE IF NOT EXISTS test_foreign_table"
275  + " (b BOOLEAN, t TINYINT, s SMALLINT, i INTEGER, bi BIGINT, f FLOAT, "
276  + "dc DECIMAL(10, 5), tm TIME, tp TIMESTAMP, d DATE, txt TEXT, "
277  + "txt_2 TEXT ENCODING NONE) "
278  + "SERVER default_local_delimited WITH "
279  + "(file_path = '../Tests/FsiDataFiles/scalar_types.csv', "
280  + "FRAGMENT_SIZE = 10);");
281  }
282  logger.info("Finished Setup.");
283  }
284 
285  @Override
286  public void cleanUpTests(final List<SqlCommandThread[]> tests) throws Exception {
287  logger.info("Starting cleanup...");
289  runAndLog(heavyAdmin, "DROP USER test_user;");
290  runAndLog(heavyAdmin, "DROP DATABASE " + db + ";");
291  // Some tests require (and can specify) custom cleanup.
292  for (SqlCommandThread[] testGroup : tests) {
293  for (SqlCommandThread test : testGroup) {
294  for (String query : test.cleanUpQueries) {
295  runAndLog(heavyAdmin, query);
296  }
297  }
298  }
300  logger.info("Finished cleanup.");
301  }
302 
303  @Override
304  public void runTests(final List<SqlCommandThread[]> tests) throws Exception {
305  logger.info("starting runTests.");
306 
307  // Initialize threads, but block them from executing until all threads are ready.
308  int numTests = 0;
309  for (SqlCommandThread threadGroup[] : tests) {
310  numTests += threadGroup.length;
311  }
312  barrier = createBarrier(numTests);
313 
314  for (SqlCommandThread threadGroup[] : tests) {
315  for (SqlCommandThread thread : threadGroup) {
316  thread.start();
317  }
318  }
319 
320  logger.info("Waiting for threads to sync...");
321 
322  if (enableMonitorThread) {
323  new MonitoringThread(tests, numThreads).start();
324  }
325 
326  for (SqlCommandThread threadGroup[] : tests) {
327  for (SqlCommandThread thread : threadGroup) {
328  thread.join();
329  }
330  }
331 
333 
334  logger.info("Finished runTests.");
335  }
336 }
List< SqlCommandThread[]> createTestThreads()
final SqlCommandThread[] makeTests(final String threadName, final String query, final List< String > exceptions)
void runAndLog(HeavyDBTestClient client, String sql)
void cleanUpTests(final List< SqlCommandThread[]> tests)
void runTests(final List< SqlCommandThread[]> tests)
final SqlCommandThread[] makeTests(final String threadName, final String query, final String exception)
static boolean deleteDirectory(File dir)
final SqlCommandThread[] makeTests(final String threadName, final List< String > queries, final List< String > expectedExceptions, final List< String > cleanUpQueries, int numThreads)
static void printErrors(ArrayList< String > exceptionTexts)
final SqlCommandThread[] makeTests(final String threadName, final String query)
static CyclicBarrier createBarrier(int numThreadsToWait)
final SqlCommandThread[] makeTests(final String threadName, final String query, final String exceptions, final String cleanUpQueries)
ArrayList< String > exceptionTexts
static List< String > customizeQueriesByThreadId(final List< String > queries, int threadId)
static void main(String[] args)
final SqlCommandThread[] makeTests(final String threadName, final String query, final List< String > exceptions, final String cleanUpQueries)
HeavyDBTestClient getAdminClient(String db)