/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.drill.exec.util; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.drill.common.exceptions.ExecutionSetupException; import org.apache.drill.common.expression.SchemaPath; import org.apache.drill.exec.ops.FragmentContext; import org.apache.drill.exec.store.RecordReader; import org.apache.drill.exec.store.StoragePluginRegistry; import org.apache.drill.exec.store.dfs.DrillFileSystem; import org.apache.drill.exec.store.dfs.FileSystemConfig; import org.apache.drill.exec.store.dfs.FileSystemPlugin; import org.apache.drill.exec.store.dfs.WorkspaceConfig; import com.google.common.io.Files; import org.apache.drill.exec.store.easy.json.JSONRecordReader; /** * This class contains utility methods to speed up tests. Some of the production code currently calls this method * when the production code is executed as part of the test runs. That's the reason why this code has to be in * production module. */ public class TestUtilities { // Below two variable values are derived from // <DRILL_SRC_HOME>/exec/java-exec/src/main/resources/bootstrap-storage-plugins.json. private static final String dfsPluginName = "dfs"; private static final String dfsTmpSchema = "tmp"; // Below two variable values are derived from // <DRILL_SRC_HOME>/exec/java-exec/src/test/resources/bootstrap-storage-plugins.json. private static final String dfsTestPluginName = "dfs_test"; private static final String dfsTestTmpSchema = "tmp"; /** * Create and removes a temporary folder * * @return absolute path to temporary folder */ public static String createTempDir() { final File tmpDir = Files.createTempDir(); tmpDir.deleteOnExit(); return tmpDir.getAbsolutePath(); } /** * Update the location of dfs_test.tmp location. Get the "dfs_test.tmp" workspace and update the location with an * exclusive temp directory just for use in the current test jvm. * * @param pluginRegistry * @return JVM exclusive temporary directory location. */ public static void updateDfsTestTmpSchemaLocation(final StoragePluginRegistry pluginRegistry, final String tmpDirPath) throws ExecutionSetupException { @SuppressWarnings("resource") final FileSystemPlugin plugin = (FileSystemPlugin) pluginRegistry.getPlugin(dfsTestPluginName); final FileSystemConfig pluginConfig = (FileSystemConfig) plugin.getConfig(); final WorkspaceConfig tmpWSConfig = pluginConfig.workspaces.get(dfsTestTmpSchema); final WorkspaceConfig newTmpWSConfig = new WorkspaceConfig(tmpDirPath, true, tmpWSConfig.getDefaultInputFormat()); pluginConfig.workspaces.remove(dfsTestTmpSchema); pluginConfig.workspaces.put(dfsTestTmpSchema, newTmpWSConfig); pluginRegistry.createOrUpdate(dfsTestPluginName, pluginConfig, true); } /** * Make the dfs.tmp schema immutable, so that tests writers don't use the dfs.tmp to create views. * Schema "dfs.tmp" added as part of the default bootstrap plugins file that comes with drill-java-exec jar */ public static void makeDfsTmpSchemaImmutable(final StoragePluginRegistry pluginRegistry) throws ExecutionSetupException { @SuppressWarnings("resource") final FileSystemPlugin dfsPlugin = (FileSystemPlugin) pluginRegistry.getPlugin(dfsPluginName); final FileSystemConfig dfsPluginConfig = (FileSystemConfig) dfsPlugin.getConfig(); final WorkspaceConfig tmpWSConfig = dfsPluginConfig.workspaces.get(dfsTmpSchema); final WorkspaceConfig newTmpWSConfig = new WorkspaceConfig(tmpWSConfig.getLocation(), false, tmpWSConfig.getDefaultInputFormat()); dfsPluginConfig.workspaces.remove(dfsTmpSchema); dfsPluginConfig.workspaces.put(dfsTmpSchema, newTmpWSConfig); pluginRegistry.createOrUpdate(dfsPluginName, dfsPluginConfig, true); } /** * Create JSONRecordReader from input strings. * @param jsonBatches : list of input strings, each element represent a batch. Each string could either * be in the form of "[{...}, {...}, ..., {...}]", or in the form of "{...}". * @param fragContext : fragment context * @param columnsToRead : list of schema pathes to read from JSON reader. * @return */ public static Iterator<RecordReader> getJsonReadersFromBatchString(List<String> jsonBatches, FragmentContext fragContext, List<SchemaPath> columnsToRead) { ObjectMapper mapper = new ObjectMapper(); List<RecordReader> readers = new ArrayList<>(); for (String batchJason : jsonBatches) { JsonNode records; try { records = mapper.readTree(batchJason); } catch (IOException e) { throw new RuntimeException(e); } readers.add(new JSONRecordReader(fragContext, records, null, columnsToRead)); } return readers.iterator(); } /** * Create JSONRecordReader from files on a file system. * @param fs : file system. * @param inputPaths : list of .json file paths. * @param fragContext * @param columnsToRead * @return */ public static Iterator<RecordReader> getJsonReadersFromInputFiles(DrillFileSystem fs, List<String> inputPaths, FragmentContext fragContext, List<SchemaPath> columnsToRead) { List<RecordReader> readers = new ArrayList<>(); for (String inputPath : inputPaths) { readers.add(new JSONRecordReader(fragContext, inputPath, fs, columnsToRead)); } return readers.iterator(); } }