Switch android test to common Android SDK dependency management

~
This commit is contained in:
Mikhail Bogdanov
2020-04-09 08:51:48 +02:00
parent acb4d6cf63
commit 535fcbb534
9 changed files with 52 additions and 385 deletions
@@ -6,9 +6,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.3.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath 'com.android.tools.build:gradle:3.5.3'
}
}
apply plugin: 'com.android.application'
@@ -19,7 +17,7 @@ repositories {
}
android {
compileSdkVersion 19
compileSdkVersion 26
buildToolsVersion "28.0.3"
defaultConfig {
@@ -51,7 +49,7 @@ android {
dexOptions {
dexInProcess false
javaMaxHeapSize "1200m"
javaMaxHeapSize "1500m"
maxProcessCount 4
additionalParameters "--debug"
}
+2
View File
@@ -1,3 +1,4 @@
import TaskUtils.useAndroidEmulator
plugins {
kotlin("jvm")
@@ -59,6 +60,7 @@ projectTest {
}
workingDir = rootDir
useAndroidEmulator(this)
}
val generateAndroidTests by generator("org.jetbrains.kotlin.android.tests.CodegenTestsOnAndroidGenerator")
@@ -19,10 +19,8 @@ package org.jetbrains.kotlin.android.tests
import com.intellij.util.PlatformUtils
import junit.framework.TestCase
import junit.framework.TestSuite
import org.jetbrains.kotlin.android.tests.download.SDKDownloader
import org.jetbrains.kotlin.android.tests.emulator.Emulator
import org.jetbrains.kotlin.android.tests.gradle.GradleRunner
import org.jetbrains.kotlin.android.tests.run.PermissionManager
import org.junit.Assert
import org.w3c.dom.Element
import org.xml.sax.SAXException
@@ -39,8 +37,6 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
private fun runTestsInEmulator(): TestSuite {
val rootSuite = TestSuite("Root")
downloadDependencies()
val emulatorType = if (isTeamcity) Emulator.ARM else Emulator.X86
println("Using $emulatorType emulator!")
val emulator = Emulator(pathManager, emulatorType)
@@ -134,18 +130,6 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
}
private fun downloadDependencies() {
val rootForAndroidDependencies = File(pathManager.dependenciesRoot)
if (!rootForAndroidDependencies.exists()) {
rootForAndroidDependencies.mkdirs()
}
val downloader = SDKDownloader(pathManager)
downloader.downloadAll()
downloader.unzipAll()
PermissionManager.setPermissions(pathManager)
}
companion object {
@JvmStatic
@@ -16,7 +16,7 @@
package org.jetbrains.kotlin.android.tests;
import org.jetbrains.kotlin.android.tests.download.SDKDownloader;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import java.io.File;
@@ -35,7 +35,7 @@ public class PathManager {
}
public String getAndroidAvdRoot() {
String androidEmulatorRoot = getAndroidSdkRoot() + "/emulatoravd";
String androidEmulatorRoot = getAndroidSdkRoot() + "/compiler_box_test_avd";
new File(androidEmulatorRoot).mkdirs();
return androidEmulatorRoot;
}
@@ -52,10 +52,6 @@ public class PathManager {
return getAndroidSdkRoot() + "/emulator";
}
public String getBuildToolsFolderInAndroidSdk() {
return getAndroidSdkRoot() + "/build-tools";
}
public String getOutputForCompiledFiles(int index) {
return tmpFolder + "/libs/libtest" + index;
}
@@ -73,19 +69,7 @@ public class PathManager {
}
public String getAndroidSdkRoot() {
return getDependenciesRoot() + "/android-sdk";
}
public String getDependenciesRoot() {
return rootFolder + "/dependencies/android.tests.dependencies";
}
public String getGradleBinFolder() {
return getDependenciesRoot() + "/gradle-" + SDKDownloader.GRADLE_VERSION + "/bin";
}
public String getRootForDownload() {
return getDependenciesRoot() + "/download";
return KotlinTestUtils.getAndroidSdkSystemIndependentPath();
}
public String getAndroidModuleRoot() {
@@ -1,269 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed 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.jetbrains.kotlin.android.tests.download;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.kotlin.android.tests.PathManager;
import org.jetbrains.kotlin.android.tests.run.RunUtils;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class SDKDownloader {
private final String platformZipPath;
private final String armImage;
private final String x86Image;
private final String platformToolsZipPath;
private final String skdToolsZipPath;
private final String buildToolsZipPath;
private final String gradleZipPath;
private final String emulatorZipPath;
private final PathManager pathManager;
private static final String PLATFORM_TOOLS = "28.0.1";
private static final String SDK_TOOLS = "4333796"; //"26.1.1";
public static final String BUILD_TOOLS = "28.0.3";
private static final int ANDROID_VERSION = 19;
public static final String GRADLE_VERSION = "5.1.1";
public static final String EMULATOR_TOOLS_VERSION = "5264690"; //"28.0.23";
public SDKDownloader(PathManager pathManager) {
this.pathManager = pathManager;
platformZipPath = pathManager.getRootForDownload() + "/platform" + ANDROID_VERSION + ".zip";
armImage = pathManager.getRootForDownload() + "/arm-image.zip";
x86Image = pathManager.getRootForDownload() + "/x86-image.zip";
platformToolsZipPath = pathManager.getRootForDownload() + "/platform-tools" + PLATFORM_TOOLS + ".zip";
skdToolsZipPath = pathManager.getRootForDownload() + "/sdk-tools" + SDK_TOOLS + ".zip";
buildToolsZipPath = pathManager.getRootForDownload() + "/build-tools" + BUILD_TOOLS + ".zip";
gradleZipPath = pathManager.getRootForDownload() + "/gradle" + GRADLE_VERSION + ".zip";
emulatorZipPath = pathManager.getRootForDownload() + "/emulator" + EMULATOR_TOOLS_VERSION + ".zip";
}
public void downloadPlatform() {
download("https://dl-ssl.google.com/android/repository/android-" + ANDROID_VERSION + "_r04.zip", platformZipPath); //Same for all platforms
}
private void downloadAbi() {
download("https://dl.google.com/android/repository/sys-img/android/armeabi-v7a-" + ANDROID_VERSION + "_r05.zip", armImage); //Same for all platforms
download("https://dl.google.com/android/repository/sys-img/android/x86-" + ANDROID_VERSION + "_r06.zip", x86Image); //Same for all platforms
}
public void downloadPlatformTools() {
download(getDownloadUrl("https://dl-ssl.google.com/android/repository/platform-tools_r" + PLATFORM_TOOLS), platformToolsZipPath);
}
public void downloadSdkTools() {
download("https://dl.google.com/android/repository/sdk-tools-" + getPlatformName() + "-" + SDK_TOOLS + ".zip",
skdToolsZipPath);
}
public void downloadBuildTools() {
download(getDownloadUrl("https://dl.google.com/android/repository/build-tools_r" + BUILD_TOOLS), buildToolsZipPath);
}
public void downloadEmulator() {
download("https://dl.google.com/android/repository/emulator-" + getPlatformName() + "-" + EMULATOR_TOOLS_VERSION + ".zip",
emulatorZipPath);
}
public void downloadGradle() {
download("https://services.gradle.org/distributions/gradle-" + GRADLE_VERSION + "-bin.zip", gradleZipPath);
}
private static String getDownloadUrl(String prefix) {
String suffix;
if (SystemInfo.isWindows) {
suffix = "-windows.zip";
}
else if (SystemInfo.isMac) {
suffix = "-macosx.zip";
}
else if (SystemInfo.isUnix) {
suffix = "-linux.zip";
}
else {
throw new IllegalStateException("Your operating system isn't supported yet.");
}
return prefix + suffix;
}
private static String getPlatformName() {
if (SystemInfo.isWindows) {
return "windows";
}
else if (SystemInfo.isMac) {
return "darwin";
}
else if (SystemInfo.isUnix) {
return "linux";
}
else {
throw new IllegalStateException("Your operating system isn't supported yet.");
}
}
public void downloadAll() {
downloadSdkTools();
downloadAbi();
downloadPlatform();
downloadPlatformTools();
downloadBuildTools();
downloadGradle();
downloadEmulator();
}
public void unzipAll() {
String androidSdkRoot = pathManager.getAndroidSdkRoot();
unzip(platformZipPath, pathManager.getPlatformFolderInAndroidSdk());
new File(pathManager.getPlatformFolderInAndroidSdk() + "/android-4.4.2").renameTo(new File(pathManager.getPlatformFolderInAndroidSdk() + "/android-" + ANDROID_VERSION));
unzip(armImage, androidSdkRoot + "/system-images/android-" + ANDROID_VERSION + "/default/");
unzip(x86Image, androidSdkRoot + "/system-images/android-" + ANDROID_VERSION + "/default/");
unzip(platformToolsZipPath, androidSdkRoot);
unzip(skdToolsZipPath, androidSdkRoot);
unzip(gradleZipPath, pathManager.getDependenciesRoot());
//BUILD TOOLS
String buildTools = androidSdkRoot + "/build-tools/";
unzip(buildToolsZipPath, buildTools);
unzip(emulatorZipPath, androidSdkRoot);
}
public void deleteAll() {
delete(platformZipPath);
delete(platformToolsZipPath);
delete(skdToolsZipPath);
delete(buildToolsZipPath);
delete(armImage);
delete(x86Image);
delete(gradleZipPath);
}
private static void download(String urlString, String output) {
System.out.println("Start downloading: " + urlString + " to " + output);
OutputStream outStream = null;
URLConnection urlConnection;
InputStream is;
try {
URL Url;
byte[] buf;
int read;
//int written = 0;
Url = new URL(urlString);
File outputFile = new File(output);
outputFile.getParentFile().mkdirs();
if (outputFile.exists()) {
System.out.println("File was already downloaded: " + output);
return;
}
outputFile.createNewFile();
FileOutputStream outputStream = new FileOutputStream(outputFile);
outStream = new BufferedOutputStream(outputStream);
urlConnection = Url.openConnection();
is = urlConnection.getInputStream();
buf = new byte[1024];
while ((read = is.read(buf)) != -1) {
outStream.write(buf, 0, read);
//written += read;
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
finally {
RunUtils.close(outStream);
}
System.out.println("Finish downloading: " + urlString + " to " + output);
}
protected void unzip(String pathToFile, String outputFolder) {
System.out.println("Start unzipping: " + pathToFile + " to " + outputFolder);
String pathToUnzip;
if (outputFolder.equals(pathManager.getPlatformFolderInAndroidSdk())) {
pathToUnzip = outputFolder;
}
else {
pathToUnzip = outputFolder + "/" + FileUtil.getNameWithoutExtension(new File(pathToFile));
}
if (new File(pathToUnzip).listFiles() != null) {
System.out.println("File was already unzipped: " + pathToFile);
return;
}
try {
byte[] buf = new byte[1024];
ZipEntry zipEntry = null;
try (ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(pathToFile))) {
zipEntry = zipInputStream.getNextEntry();
while (zipEntry != null) {
String entryName = zipEntry.getName();
int n;
File outputFile = new File(outputFolder + "/" + entryName);
if (zipEntry.isDirectory()) {
outputFile.mkdirs();
zipInputStream.closeEntry();
zipEntry = zipInputStream.getNextEntry();
continue;
}
else {
File parentFile = outputFile.getParentFile();
if (parentFile != null && !parentFile.exists()) {
parentFile.mkdirs();
}
outputFile.createNewFile();
}
try (FileOutputStream fileOutputStream = new FileOutputStream(outputFile)) {
while ((n = zipInputStream.read(buf, 0, 1024)) > -1) {
fileOutputStream.write(buf, 0, n);
}
}
zipInputStream.closeEntry();
zipEntry = zipInputStream.getNextEntry();
}
}
catch (IOException e) {
if (zipEntry != null) {
System.err.println("Entry name: " + zipEntry.getName());
}
e.printStackTrace();
}
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println("Finish unzipping: " + pathToFile + " to " + outputFolder);
}
private static void delete(String filePath) {
new File(filePath).delete();
}
}
@@ -48,8 +48,8 @@ public class Emulator {
private GeneralCommandLine getCreateCommand() {
GeneralCommandLine commandLine = new GeneralCommandLine();
String androidCmdName = SystemInfo.isWindows ? "android.bat" : "android";
commandLine.setExePath(pathManager.getToolsFolderInAndroidSdk() + "/" + androidCmdName);
String androidCmdName = SystemInfo.isWindows ? "avdmanager.bat" : "avdmanager";
commandLine.setExePath(pathManager.getToolsFolderInAndroidSdk() + "/bin/" + androidCmdName);
commandLine.addParameter("create");
commandLine.addParameter("avd");
commandLine.addParameter("--force");
@@ -31,8 +31,8 @@ public class GradleRunner {
public GradleRunner(PathManager pathManager) {
listOfCommands = new ArrayList<>();
String cmdName = SystemInfo.isWindows ? "gradle.bat" : "gradle";
listOfCommands.add(pathManager.getGradleBinFolder() + "/" + cmdName);
String cmdName = SystemInfo.isWindows ? "gradlew.bat" : "gradlew";
listOfCommands.add(pathManager.getTmpFolder() + "/" + cmdName);
listOfCommands.add("--no-daemon");
listOfCommands.add("--build-file");
listOfCommands.add(pathManager.getTmpFolder() + "/build.gradle");
@@ -1,64 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed 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.jetbrains.kotlin.android.tests.run;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.openapi.util.SystemInfo;
import org.jetbrains.kotlin.android.tests.PathManager;
import org.jetbrains.kotlin.android.tests.download.SDKDownloader;
import java.io.File;
public class PermissionManager {
private PermissionManager() {
}
public static void setPermissions(PathManager pathManager) {
if (!SystemInfo.isWindows) {
setExecPermissionForSimpleNamedFiles(new File(pathManager.getToolsFolderInAndroidSdk()));
setExecPermissionForSimpleNamedFiles(new File(pathManager.getBuildToolsFolderInAndroidSdk() + "/" + SDKDownloader.BUILD_TOOLS));
setExecPermissionForSimpleNamedFiles(new File(pathManager.getPlatformToolsFolderInAndroidSdk()));
setExecPermissionForSimpleNamedFiles(new File(pathManager.getToolsFolderInAndroidSdk() +"/bin"));
setExecPermissionForSimpleNamedFiles(new File(pathManager.getEmulatorFolderInAndroidSdk()));
setExecPermissionForSimpleNamedFiles(new File(pathManager.getEmulatorFolderInAndroidSdk() +"/bin"));
setExecPermissionForSimpleNamedFiles(new File(pathManager.getEmulatorFolderInAndroidSdk() +"/bin64"));
setExecPermissionForSimpleNamedFiles(new File(pathManager.getEmulatorFolderInAndroidSdk() +"/qemu/linux-x86_64"));
setExecPermissionForSimpleNamedFiles(new File(pathManager.getAndroidSdkRoot() + "/system-images/android-19/default/armeabi-v7a/"));
RunUtils.execute(generateChmodCmd(pathManager.getGradleBinFolder() + "/gradle"));
}
}
private static void setExecPermissionForSimpleNamedFiles(File folder) {
File[] files = folder.listFiles();
if (files != null) {
for (File file : files) {
if (file.isFile() && !file.getName().contains(".")) {
RunUtils.execute(generateChmodCmd(file.getAbsolutePath()));
}
}
}
}
private static GeneralCommandLine generateChmodCmd(String path) {
GeneralCommandLine commandLine = new GeneralCommandLine();
commandLine.setExePath("chmod");
commandLine.addParameter("a+x");
commandLine.addParameter(path);
return commandLine;
}
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.android.tests
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.FileUtilRt
import org.jetbrains.kotlin.cli.common.output.writeAllTo
@@ -48,19 +49,48 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
) + "/" + testClassName + "$index.java"
}
private fun prepareAndroidModuleAndGenerateTests() {
prepareAndroidModule()
private fun prepareAndroidModuleAndGenerateTests(skipSdkDirWriting: Boolean) {
prepareAndroidModule(skipSdkDirWriting)
generateTestsAndFlavourSuites()
}
private fun prepareAndroidModule() {
private fun prepareAndroidModule(skipSdkDirWriting: Boolean) {
FileUtil.copyDir(File(pathManager.androidModuleRoot), File(pathManager.tmpFolder))
writeAndroidSkdToLocalProperties(pathManager)
if (!skipSdkDirWriting) {
writeAndroidSkdToLocalProperties(pathManager)
}
println("Copying kotlin-stdlib.jar and kotlin-reflect.jar in android module...")
copyKotlinRuntimeJars()
copyGradleWrapperAndPatch()
}
private fun copyGradleWrapperAndPatch() {
val projectRoot = File(pathManager.tmpFolder)
val target = File(projectRoot, "gradle/wrapper")
File("./gradle/wrapper/").copyRecursively(target)
val gradlew = File(projectRoot, "gradlew")
File("./gradlew").copyTo(gradlew).also {
if (!SystemInfo.isWindows) {
it.setExecutable(true)
}
}
File("./gradlew.bat").copyTo(File(projectRoot, "gradlew.bat"));
val file = File(target, "gradle-wrapper.properties")
file.readLines().map {
if (it.startsWith("distributionUrl"))
"distributionUrl=https\\://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip"
else it
}.let { lines ->
FileWriter(file).use { fw ->
lines.forEach { line ->
fw.write("$line\n")
}
}
}
}
private fun copyKotlinRuntimeJars() {
FileUtil.copy(
ForTestCompileRuntime.runtimeJarForTests(),
@@ -250,6 +280,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
)
companion object {
const val GRADLE_VERSION = "5.6.4"
const val testClassPackage = "org.jetbrains.kotlin.android.tests"
const val testClassName = "CodegenTestCaseOnAndroid"
const val baseTestClassPackage = "org.jetbrains.kotlin.android.tests"
@@ -257,10 +288,11 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
const val generatorName = "CodegenTestsOnAndroidGenerator"
@JvmOverloads
@JvmStatic
@Throws(Throwable::class)
fun generate(pathManager: PathManager) {
CodegenTestsOnAndroidGenerator(pathManager).prepareAndroidModuleAndGenerateTests()
fun generate(pathManager: PathManager, skipSdkDirWriting: Boolean = false) {
CodegenTestsOnAndroidGenerator(pathManager).prepareAndroidModuleAndGenerateTests(skipSdkDirWriting)
}
private fun hasBoxMethod(text: String): Boolean {
@@ -269,7 +301,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
@Throws(IOException::class)
internal fun writeAndroidSkdToLocalProperties(pathManager: PathManager) {
val sdkRoot = File(pathManager.androidSdkRoot).invariantSeparatorsPath
val sdkRoot = KotlinTestUtils.getAndroidSdkSystemIndependentPath()
println("Writing android sdk to local.properties: $sdkRoot")
val file = File(pathManager.tmpFolder + "/local.properties")
FileWriter(file).use { fw -> fw.write("sdk.dir=$sdkRoot") }
@@ -281,7 +313,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
println("Created temporary folder for android tests: " + tmpFolder.absolutePath)
val rootFolder = File("")
val pathManager = PathManager(rootFolder.absolutePath, tmpFolder.absolutePath)
generate(pathManager)
generate(pathManager, true)
}
}
}