void testAndExpectUserException(final String query, ErrorType errorType, final String errorMessage) throws Exception { try { test(query); Assert.fail("Query should've failed"); } catch (UserRemoteException uex) { Assert.assertEquals("Error Message: "+ uex.getMessage(), errorType, uex.getErrorType()); Assert.assertTrue( String.format("Expected error message to contain: %s but was actually [%s].", errorMessage, uex.getMessage()), uex.getMessage().contains(errorMessage)); } } }
@Test // DRILL-3688 public void testIncorrectHeaderFooterProperty() throws Exception { Map<String, String> testData = ImmutableMap.<String, String>builder() .put("hive.skipper.kv_incorrect_skip_header","skip.header.line.count") .put("hive.skipper.kv_incorrect_skip_footer", "skip.footer.line.count") .build(); String query = "select * from %s"; String exceptionMessage = "Hive table property %s value 'A' is non-numeric"; for (Map.Entry<String, String> entry : testData.entrySet()) { try { test(String.format(query, entry.getKey())); } catch (UserRemoteException e) { assertThat(e.getMessage(), containsString(String.format(exceptionMessage, entry.getValue()))); } } }
@Test public void testIncorrectFunctionPlacement() throws Exception { Map<String, String> configMap = ImmutableMap.<String, String>builder() .put("select %s('dfs_root','" + path + "') from dfs.\"" + path + "/*/*.csv\"", "Select List") .put("select dir0 from dfs.\"" + path + "/*/*.csv\" order by %s('dfs_root','" + path + "')", "Order By") .put("select max(dir0) from dfs.\"" + path + "/*/*.csv\" group by %s('dfs_root','" + path + "')", "Group By") .put("select concat(concat(%s('dfs_root','" + path + "'),'someName'),'someName') from dfs.\"" + path + "/*/*.csv\"", "Select List") .put("select dir0 from dfs.\"" + path + "/*/*.csv\" order by concat(%s('dfs_root','" + path + "'),'someName')", "Order By") .put("select max(dir0) from dfs.\"" + path + "/*/*.csv\" group by concat(%s('dfs_root','" + path + "'),'someName')", "Group By") .build(); for (Map.Entry<String, String> configEntry : configMap.entrySet()) { for (ConstantFoldingTestConfig functionConfig : tests) { try { test(String.format(configEntry.getKey(), functionConfig.funcName)); } catch (UserRemoteException e) { assertThat(e.getMessage(), containsString( String.format("Directory explorers [MAXDIR, IMAXDIR, MINDIR, IMINDIR] functions are not supported in %s", configEntry.getValue()))); } } } }
@Test public void testWildCardEmptyNoCache() throws Exception { prepareTables("4376_3", false); try { runSQL("SELECT COUNT(*) AS \"count\" FROM dfs_test.\"4376_3/604*\""); fail("Query should've failed!"); } catch (UserRemoteException uex) { final String expectedMsg = "Table 'dfs_test.4376_3/604*' not found"; assertTrue(String.format("Error message should contain \"%s\" but was instead \"%s\"", expectedMsg, uex.getMessage()), uex.getMessage().contains(expectedMsg)); } }
@Test public void testSelectEmptyNoCache() throws Exception { prepareTables("4376_5", false); try { runSQL("SELECT COUNT(*) AS \"count\" FROM dfs_test.\"4376_5/6041\""); fail("Query should've failed!"); } catch (UserRemoteException uex) { final String expectedMsg = "Table 'dfs_test.4376_5/6041' not found"; assertTrue(String.format("Error message should contain \"%s\" but was instead \"%s\"", expectedMsg, uex.getMessage()), uex.getMessage().contains(expectedMsg)); } }
@Test @Ignore("empty table") public void testSelectEmptyWithCache() throws Exception { prepareTables("4376_4", true); try { runSQL("SELECT COUNT(*) AS \"count\" FROM dfs_test.\"4376_4/6041\""); fail("Query should've failed!"); } catch (UserRemoteException uex) { final String expectedMsg = "The table you tried to query is empty"; assertTrue(String.format("Error message should contain \"%s\" but was instead \"%s\"", expectedMsg, uex.getMessage()), uex.getMessage().contains(expectedMsg)); } }
@Test @Ignore("empty table") public void testWildCardEmptyWithCache() throws Exception { prepareTables("4376_2", true); try { runSQL("SELECT COUNT(*) AS \"count\" FROM dfs_test.\"4376_2/604*\""); fail("Query should've failed!"); } catch (UserRemoteException uex) { final String expectedMsg = "The table you tried to query is empty"; assertTrue(String.format("Error message should contain \"%s\" but was instead \"%s\"", expectedMsg, uex.getMessage()), uex.getMessage().contains(expectedMsg)); } }
@Test public void testSchemaChange() throws Exception { File dir = new File("target/tests/" + this.getClass().getName() + "/testSchemaChange"); if ((!dir.exists() && !dir.mkdirs()) || (dir.exists() && !dir.isDirectory())) { throw new RuntimeException("can't create dir " + dir); } // CAUTION: There's no ordering guarantee about which file will be read first // so make sure that each file has an incompatible schema compared to the other one. File input1 = new File(dir, "1.json"); File input2 = new File(dir, "2.json"); try (FileWriter fw = new FileWriter(input1)) { fw.append("{\"a\":\"foo\"}\n"); fw.append("{\"a\":\"bar\"}\n"); fw.append("{\"a\":\"baz\", \"c\": \"foz\"}\n"); } try (FileWriter fw = new FileWriter(input2)) { fw.append("{\"b\":\"foo\"}\n"); fw.append("{\"a\":1, \"b\":\"baz\"}\n"); fw.append("{\"a\":\"baz\",\"b\":\"boz\"}\n"); } // we don't retry in test, so let the schema learn the first time around try { test("select * from " + "dfs.\"" + dir.getAbsolutePath() + "\""); fail("query should have failed with schema change error"); } catch (UserRemoteException e) { assertTrue(e.toString(), e.getMessage().contains("SCHEMA_CHANGE ERROR")); } // and it should work the second time runTestAndValidate("*", "*", "dfs.\"" + dir.getAbsolutePath() + "\"", "schema_change_parquet", false); }
@Test public void tpch01() throws Exception { final String query = getFile("memory/tpch01_memory_leak.sql"); try { QueryTestUtil.test(client, "alter session set \"planner.slice_target\" = 10; " + query); } catch (UserRemoteException e) { if (e.getMessage().contains("Allocator closed with outstanding buffers allocated")) { return; } throw e; } fail("Expected UserRemoteException indicating memory leak"); }
@Test public void testConstantFoldingOff() throws Exception { try { test("set \"planner.enable_constant_folding\" = false;"); String query = "select * from dfs.\"" + path + "/*/*.csv\" where dir0 = %s('dfs_root','" + path + "')"; for (ConstantFoldingTestConfig config : tests) { try { test(String.format(query, config.funcName)); } catch (UserRemoteException e) { assertThat(e.getMessage(), containsString("Directory explorers [MAXDIR, IMAXDIR, MINDIR, IMINDIR] functions can not be used " + "when planner.enable_constant_folding option is set to false")); } } } finally { test("set \"planner.enable_constant_folding\" = true;"); } } }
@Test public void ensureColumnNameDisplayedinError() throws Exception { final String COL_NAME = "col1"; try { test("select max(columns[1]) as %s from cp.\"textinput/input1.csv\" where %s is not null", COL_NAME, COL_NAME); fail("Query should have failed"); } catch(UserRemoteException ex) { assertEquals(ErrorType.VALIDATION, ex.getErrorType()); assertTrue("Error message should contain " + COL_NAME, ex.getMessage().contains(COL_NAME)); } }
@Test public void testShouldFailSimpleUnionNonNullSchema_StarQuery() throws Exception { final String file = AvroTestUtil.generateUnionSchema_WithNonNullValues().getFilePath(); final String sql = "select * from dfs_root.\"" + file + "\""; try { test(sql); Assert.fail("Test should fail as union is only supported for optional fields"); } catch(UserRemoteException e) { String message = e.getMessage(); Assert.assertTrue(message.contains("Avro union type must be of the format : [\"null\", \"some-type\"]")); } }
@Test public void testShowFilesInWSWithNoPermissionsForQueryUser() throws Exception { UserRemoteException ex = null; updateClient(user2); try { // Try show tables in schema "dremioTestGrp1_700" which is owned by "user1" test(String.format("SHOW FILES IN %s.dremioTestGrp1_700", MINIDFS_STORAGE_PLUGIN_NAME)); } catch(UserRemoteException e) { ex = e; } assertNotNull("UserRemoteException is expected", ex); assertThat(ex.getMessage(), containsString("Permission denied: user=dremioTestUser2, " + "access=READ_EXECUTE, inode=\"/dremioTestGrp1_700\":dremioTestUser1:dremioTestGrp1:drwx------")); }
@Test public void testCreateTableInWSWithNoPermissionsForQueryUser() throws Exception { // Workspace dir owned by "processUser", workspace group is "group0" and "user2" is not part of "group0" final String tableWS = "dremioTestGrp0_755"; final String tableName = "table1"; UserRemoteException ex = null; try { updateClient(user2); test("USE " + Joiner.on(".").join(MINIDFS_STORAGE_PLUGIN_NAME, tableWS)); test("CREATE TABLE " + tableName + " AS SELECT " + "c_custkey, c_nationkey FROM cp.\"tpch/customer.parquet\" ORDER BY c_custkey;"); } catch(UserRemoteException e) { ex = e; } assertNotNull("UserRemoteException is expected", ex); assertThat(ex.getMessage(), containsString("SYSTEM ERROR: RemoteException: Permission denied: user=dremioTestUser2, access=WRITE, inode=\"/dremioTestGrp0_755/")); }
@Test public void testDirectImpersonation_NoReadPermissions() throws Exception { try { // Table lineitem is owned by "user0_1:group0_1" with permissions 750. Now try to read the table as "user2_1". We // should expect a permission denied error as "user2_1" is not part of the "group0_1" updateClient(org1Users[2]); test(String.format("SELECT * FROM %s ORDER BY l_orderkey LIMIT 1", fullPath(org1Users[0], "lineitem"))); fail("query is expected to fail"); } catch(UserRemoteException e) { assertEquals(ErrorType.PERMISSION, e.getErrorType()); assertThat(e.getMessage(), containsString("PERMISSION ERROR: Access denied reading dataset miniDfsPlugin.\"/user/user0_1/lineitem\"")); } }
.build(), statusListener)); } catch (UserRemoteException e) { throw new DACRuntimeException(format("Failure while running %s query for dataset %s :\n%s", queryType, messagePath, query) + "\n" + e.getMessage(), e);
@Test public void testCreateTableDirectImpersonation_NoWritePermission() throws Exception { // Table lineitem is owned by "user0_1:group0_1" with permissions 750. Try to read the table as "user0_1" // and create a table under user2_1, which should fail try { updateClient(org1Users[0]); test(String.format("CREATE TABLE %s AS SELECT * FROM %s ORDER BY l_orderkey LIMIT 1", fullPath(org1Users[2], "copy_lineitem"), fullPath(org1Users[0], "lineitem"))); fail("query is expected to fail"); } catch(UserRemoteException e) { assertEquals(ErrorType.SYSTEM, e.getErrorType()); assertThat(e.getMessage(), containsString("Permission denied")); } } @Test