diff --git a/fdroidserver/common.py b/fdroidserver/common.py index e63320db..9fa6072d 100644 --- a/fdroidserver/common.py +++ b/fdroidserver/common.py @@ -2342,7 +2342,7 @@ gradle_signing_configs = re.compile(r'^[\t ]*signingConfigs[ \t]*{[ \t]*$') gradle_line_matches = [ re.compile(r'^[\t ]*signingConfig [^ ]*$'), re.compile(r'.*android\.signingConfigs\.[^{]*$'), - re.compile(r'.*\.readLine\(.*'), + re.compile(r'.*release\.signingConfig *= *'), ] diff --git a/tests/common.TestCase b/tests/common.TestCase index 45e43f6f..d2d46ce4 100755 --- a/tests/common.TestCase +++ b/tests/common.TestCase @@ -2,6 +2,7 @@ # http://www.drdobbs.com/testing/unit-testing-with-python/240165163 +import difflib import glob import inspect import logging @@ -925,6 +926,64 @@ class CommonTest(unittest.TestCase): self.assertEqual(('1.0-free', '1', 'com.kunzisoft.fdroidtest.applicationidsuffix'), fdroidserver.common.parse_androidmanifests(paths, app)) + def test_remove_signing_keys(self): + testdir = tempfile.mkdtemp(prefix=inspect.currentframe().f_code.co_name, dir=self.tmpdir) + print(testdir) + shutil.copytree(os.path.join(self.basedir, 'source-files'), + os.path.join(testdir, 'source-files')) + os.chdir(testdir) + with_signingConfigs = [ + 'source-files/com.seafile.seadroid2/app/build.gradle', + 'source-files/eu.siacs.conversations/build.gradle', + 'source-files/info.guardianproject.ripple/build.gradle', + 'source-files/open-keychain/open-keychain/build.gradle', + 'source-files/open-keychain/open-keychain/OpenKeychain/build.gradle', + 'source-files/osmandapp/osmand/build.gradle', + 'source-files/ut.ewh.audiometrytest/app/build.gradle', + ] + for f in with_signingConfigs: + build_dir = os.path.join(*f.split(os.sep)[:2]) + if not os.path.isdir(build_dir): + continue + fdroidserver.common.remove_signing_keys(build_dir) + fromfile = os.path.join(self.basedir, f) + with open(f) as fp: + content = fp.read() + if 'signingConfig' in content: + with open(f) as fp: + b = fp.readlines() + with open(fromfile) as fp: + a = fp.readlines() + diff = difflib.unified_diff(a, b, fromfile, f) + sys.stdout.writelines(diff) + self.assertFalse(True) + do_not_modify = [ + 'source-files/Zillode/syncthing-silk/build.gradle', + 'source-files/at.bitfire.davdroid/build.gradle', + 'source-files/com.kunzisoft.testcase/build.gradle', + 'source-files/com.nextcloud.client/build.gradle', + 'source-files/fdroid/fdroidclient/build.gradle', + 'source-files/firebase-suspect/app/build.gradle', + 'source-files/firebase-suspect/build.gradle', + 'source-files/firebase-whitelisted/app/build.gradle', + 'source-files/firebase-whitelisted/build.gradle', + 'source-files/org.mozilla.rocket/app/build.gradle', + 'source-files/realm/react-native/android/build.gradle', + 'triple-t-2/build/org.piwigo.android/app/build.gradle', + ] + for f in do_not_modify: + build_dir = os.path.join(*f.split(os.sep)[:2]) + if not os.path.isdir(build_dir): + continue + fdroidserver.common.remove_signing_keys(build_dir) + fromfile = os.path.join(self.basedir, f) + with open(fromfile) as fp: + a = fp.readlines() + with open(f) as fp: + b = fp.readlines() + diff = list(difflib.unified_diff(a, b, fromfile, f)) + self.assertEqual(0, len(diff), 'This file should not have been modified:\n' + ''.join(diff)) + def test_calculate_math_string(self): self.assertEqual(1234, fdroidserver.common.calculate_math_string('1234')) diff --git a/tests/scanner.TestCase b/tests/scanner.TestCase index 6e41b905..22f9417b 100755 --- a/tests/scanner.TestCase +++ b/tests/scanner.TestCase @@ -29,13 +29,16 @@ class ScannerTest(unittest.TestCase): source_files = os.path.join(self.basedir, 'source-files') projects = { 'Zillode': 1, - 'firebase-suspect': 1 + 'firebase-suspect': 1, + 'org.mozilla.rocket': 4, + 'realm': 1, } for d in glob.glob(os.path.join(source_files, '*')): build = fdroidserver.metadata.Build() fatal_problems = fdroidserver.scanner.scan_source(d, build) - self.assertEqual(projects.get(os.path.basename(d), 0), - fatal_problems) + should = projects.get(os.path.basename(d), 0) + self.assertEqual(should, fatal_problems, + "%s should have %d errors!" % (d, should)) if __name__ == "__main__": diff --git a/tests/source-files/com.seafile.seadroid2/app/build.gradle b/tests/source-files/com.seafile.seadroid2/app/build.gradle new file mode 100644 index 00000000..55813267 --- /dev/null +++ b/tests/source-files/com.seafile.seadroid2/app/build.gradle @@ -0,0 +1,122 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion rootProject.ext.compileSdkVersion + + defaultConfig { + applicationId 'com.seafile.seadroid2' + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 93 + versionName "2.2.18" + multiDexEnabled true + resValue "string", "authorities", applicationId + '.cameraupload.provider' + resValue "string", "account_type", "com.seafile.seadroid2.account.api2" + buildConfigField "String", "ACCOUNT_TYPE", '"com.seafile.seadroid2.account.api2"' + ndk { + abiFilters 'armeabi', 'armeabi-v7a', 'x86' + } + } + + lintOptions { + abortOnError false + disable 'MissingTranslation' + } + + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + signingConfigs { + debug { +// def props = new Properties() +// props.load(new FileInputStream(project.file("debugkey.properties"))) +// storeFile project.file(props.keyStore) +// storePassword props.keyStorePassword +// keyAlias props.keyAlias +// keyPassword props.keyAliasPassword + } + release { +// Signing code for manual signing +// storeFile file(System.console().readLine("\n\$ Enter keystore path: ")) +// storePassword System.console().readPassword("\n\$ Enter keystore password: ").toString() +// keyAlias System.console().readLine("\n\$ Enter key alias: ") +// keyPassword System.console().readPassword("\n\$ Enter key password: ").toString() + + def props = new Properties() + props.load(new FileInputStream(project.file("key.properties"))) + storeFile project.file(props.keyStore) + storePassword props.keyStorePassword + keyAlias props.keyAlias + keyPassword props.keyAliasPassword + } + } + + buildTypes { + debug { + debuggable true + applicationIdSuffix ".debug" + resValue "string", "authorities", defaultConfig.applicationId + '.debug.cameraupload.provider' + resValue "string", "account_type", "com.seafile.seadroid2.debug.account.api2" + buildConfigField "String", "ACCOUNT_TYPE", '"com.seafile.seadroid2.debug.account.api2"' + signingConfig signingConfigs.debug + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt' + applicationVariants.all { variant -> + variant.outputs.all { output -> + if (output.outputFile != null && output.outputFile.name.endsWith('.apk')) { + if (variant.name == "debug") + outputFileName = "seafile-debug-" + defaultConfig.versionName + ".apk" + } + } + } + } + release { + signingConfig signingConfigs.release + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt' + applicationVariants.all { variant -> + variant.outputs.all { output -> + if (output.outputFile != null && output.outputFile.name.endsWith('.apk')) { + if (variant.name == "release") { + outputFileName = "seafile-" + defaultConfig.versionName + ".apk" + } + } + } + } + } + } + + allprojects { + repositories { + maven { url 'https://jitpack.io' } + } + } + dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}" + implementation "com.android.support:design:${rootProject.ext.supportLibVersion}" + implementation 'com.github.JakeWharton:ViewPagerIndicator:2.4.1' + implementation 'com.github.kevinsawicki:http-request:6.0' + implementation 'commons-io:commons-io:2.4' + implementation 'com.google.guava:guava:18.0' + implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.3' + implementation 'com.cocosw:bottomsheet:1.3.1' + implementation 'com.commit451:PhotoView:1.2.4' + implementation 'com.joanzapata.iconify:android-iconify-material-community:2.2.1' + testImplementation 'junit:junit:4.12' + testImplementation 'org.robolectric:robolectric:3.0' + implementation 'com.madgag.spongycastle:core:1.54.0.0' + implementation 'com.madgag.spongycastle:prov:1.54.0.0' + implementation 'com.shuyu:gsyVideoPlayer-java:2.1.0' + implementation 'com.shuyu:gsyVideoPlayer-ex_so:2.1.0' + implementation 'com.squareup.okhttp3:okhttp:3.9.1' + + implementation 'com.yydcdut:markdown-processor:0.1.3' + implementation 'ren.qinc.edit:lib:0.0.5'//editor undo redo + implementation 'com.github.tiagohm.MarkdownView:library:0.19.0' + } +} + diff --git a/tests/source-files/org.mozilla.rocket/app/build.gradle b/tests/source-files/org.mozilla.rocket/app/build.gradle new file mode 100644 index 00000000..f05d2899 --- /dev/null +++ b/tests/source-files/org.mozilla.rocket/app/build.gradle @@ -0,0 +1,414 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-kapt' +apply plugin: 'com.google.android.gms.oss-licenses-plugin' +apply from: '../buildSrc/pmd.gradle' +apply from: '../buildSrc/checkstyle.gradle' +apply from: '../buildSrc/findbugs.gradle' +apply from: 'buildscripts/l10n.gradle' + + +android { + compileSdkVersion Versions.compile_sdk + buildToolsVersion Versions.build_tools + defaultConfig { + applicationId "org.mozilla" + minSdkVersion Versions.min_sdk + targetSdkVersion Versions.target_sdk + versionCode Versions.version_code + versionName Versions.version_name + if (SystemEnv.auto_screenshot == "1") { + testInstrumentationRunner "org.mozilla.focus.test.runner.ScreenshotTestRunner" + testInstrumentationRunnerArguments clearPackageData: 'true' + } else { + // general UI test, using notAnnotation to filter out auto screenshot classes + testInstrumentationRunner "org.mozilla.focus.test.runner.CustomTestRunner" + testInstrumentationRunnerArguments clearPackageData: 'true', notAnnotation: 'org.mozilla.focus.annotation.ScreengrabOnly,android.support.test.filters.FlakyTest' + } + testInstrumentationRunnerArgument 'disableAnalytics', 'true' + + multiDexEnabled true + + vectorDrawables { + useSupportLibrary false + generatedDensities = [] + } + + def bitrise_build_number = System.getenv("BITRISE_BUILD_NUMBER") + if (bitrise_build_number?.trim()) { + versionCode bitrise_build_number.toInteger() + versionNameSuffix "(" + bitrise_build_number + ")" + } + + // used by Room, to test migrations + javaCompileOptions { + annotationProcessorOptions { + arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + } + + dexOptions { + preDexLibraries true + } + + bundle { + language { + enableSplit = false + } + density { + enableSplit = false + } + abi { + enableSplit = true + } + } + + // We have a three dimensional build configuration: + // BUILD TYPE (debug, release) + + buildTypes { + release { + minifyEnabled true + shrinkResources true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + matchingFallbacks = ["firebase"] + } + debug { + def userName = System.getenv("USER") + applicationIdSuffix ".debug." + userName + versionNameSuffix applicationIdSuffix + matchingFallbacks = ["firebase_no_op"] + } + // Use a separate buildType for coverage: testCoverageEnabled produces slower code (4-5x slower + // in places that I've benchmarked), and more importantly seems to break debugging with Android Studio + // for some developers (i.e. variables can't be inspected or seen). + coverage { + initWith debug + applicationIdSuffix ".coverage" + testCoverageEnabled true + matchingFallbacks = ["debug", "firebase_no_op"] + } + // special build type to develop Firebase related stuff + firebase { + initWith debug + applicationIdSuffix ".debug.firebase" + + versionNameSuffix applicationIdSuffix + matchingFallbacks = ["debug", "firebase"] + } + } + + testBuildType "firebase" + + testOptions { + animationsDisabled = true + unitTests.returnDefaultValues = true + unitTests.includeAndroidResources = true + execution 'ANDROID_TEST_ORCHESTRATOR' + } + + // used by Room, to test migrations + sourceSets { + androidTest.assets.srcDirs += files("$projectDir/schemas".toString()) + } + + flavorDimensions "product", "engine" + + productFlavors { + focus { + resConfigs Localization.KEPT_LOCALE + dimension "product" + + applicationIdSuffix ".rocket" + } + + preview { + dimension "product" + applicationId "gro.allizom.zelda.beta" + applicationIdSuffix "" + versionNameSuffix ".nightly" + } + + // We can build with two engines: webkit or gecko + webkit { + dimension "engine" + } + + } + + variantFilter { variant -> + def flavors = variant.flavors*.name + // We only need a nightly release for now + if (flavors.contains("preview") && variant.buildType.name != "release") { + setIgnore(true) + } + } + + sourceSets { + test { + resources { + // Make the default asset folder available as test resource folder. Robolectric seems + // to fail to read assets for our setup. With this we can just read the files directly + // and do not need to rely on Robolectric. + srcDir "${projectDir}/src/main/assets/" + } + } + + preview { + res.srcDir 'src/preview/res' + } + + // used by Room, to test migrations + androidTest.assets.srcDirs += files("$projectDir/schemas".toString()) + } +} + +repositories { + flatDir { + dirs 'libs' + } + mavenCentral() +} + +dependencies { + implementation project(':telemetry-annotation') + kapt project(':telemetry-compiler') + + implementation project(':third_party:subsampling-scale-image-view') + implementation project(':third_party:glide:annotation') + implementation project(':third_party:glide:library') + kapt "com.github.bumptech.glide:compiler:${Versions.glide}" + + implementation project(':firebase') + implementation project(':feature-tabs') + implementation project(':HttpRequest') + implementation project(':httptask') + implementation project(':urlutils') + implementation project(':fileutils') + implementation project(':icon') + implementation project(':logger') + implementation project(':threadutils') + implementation project(':cachedrequestloader') + implementation project(':permissionhandler') + + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${Versions.kotlin}" + + // We didn't use CustomTabs so far. This is a build hack to force Android-Components to use + // same version of support library as we are. Android-Components depends on CustomTabs which + // version will be override by this. + // We can get rid of this once Android-Components' issue #404 has been resolve. + implementation "com.android.support:customtabs:${Versions.support}" + implementation "com.android.support:support-v4:${Versions.support}" + implementation "com.android.support:appcompat-v7:${Versions.support}" + implementation "com.android.support:design:${Versions.support}" + implementation "com.android.support:cardview-v7:${Versions.support}" + implementation "com.android.support:recyclerview-v7:${Versions.support}" + implementation "com.android.support.constraint:constraint-layout:${Versions.constraint}" + implementation "android.arch.work:work-runtime:${Versions.arch_work}" + + + // Architecture components + implementation "android.arch.lifecycle:extensions:${Versions.lifecycle}" + implementation "android.arch.lifecycle:common-java8:${Versions.lifecycle}" + implementation "android.arch.persistence.room:runtime:${Versions.room}" + implementation "android.arch.navigation:navigation-fragment:${Versions.navigation}" + kapt "android.arch.persistence.room:compiler:${Versions.room}" + + implementation("com.google.code.findbugs:annotations:${Versions.findbugs}", { + // We really only need the SuppressFBWarnings annotation, everything else can be ignored. + // Without this we get weird failures due to dependencies. + transitive = false + }) + + implementation "org.mozilla.components:browser-session:${Versions.android_components}" + implementation "org.mozilla.components:service-telemetry:${Versions.android_components}" + implementation "org.mozilla.components:browser-domains:${Versions.android_components}" + implementation "org.mozilla.components:ui-autocomplete:${Versions.android_components}" + + implementation "com.adjust.sdk:adjust-android:${Versions.adjust}" + implementation "com.google.android.gms:play-services-analytics:${Versions.firebase}" // Required by Adjust + // Required by Adjust + + implementation "com.airbnb.android:lottie:${Versions.lottie}" + + testImplementation "junit:junit:${Versions.junit}" + testImplementation "org.robolectric:robolectric:${Versions.robolectric}" + testImplementation "org.mockito:mockito-core:${Versions.mockito}" + + androidTestImplementation("com.android.support.test.espresso:espresso-core:${Versions.espresso}", { + exclude group: 'com.android.support', module: 'support-annotations' + }) + androidTestImplementation "com.android.support.test:runner:${Versions.test_runner}" + androidTestImplementation "com.android.support.test.espresso:espresso-idling-resource:${Versions.espresso}" + androidTestImplementation "com.android.support:support-annotations:${Versions.support}" + androidTestImplementation "com.android.support.test.uiautomator:uiautomator-v18:${Versions.uiautomator}" + androidTestImplementation "com.squareup.okhttp3:mockwebserver:${Versions.mockwebserver}" + androidTestImplementation "android.arch.persistence.room:testing:${Versions.room}" + androidTestImplementation "android.arch.core:core-testing:${Versions.arch_core}" + androidTestImplementation("com.android.support.test.espresso:espresso-contrib:${Versions.espresso}", { + exclude group: 'com.android.support', module: 'appcompat' + exclude group: 'com.android.support', module: 'support-v4' + exclude module: 'recyclerview-v7' + }) + androidTestImplementation "com.android.support.test.espresso:espresso-web:${Versions.espresso}" + androidTestImplementation "com.android.support.test.espresso:espresso-intents:${Versions.espresso}" + androidTestImplementation "tools.fastlane:screengrab:${Versions.fastlane_screengrab}" + androidTestImplementation "com.jraska:falcon:${Versions.jraska_falcon}" + androidTestUtil "com.android.support.test:orchestrator:${Versions.test_runner}" + + // LeakCanary + debugImplementation "com.squareup.leakcanary:leakcanary-android:${Versions.leakcanary}" + coverageImplementation "com.squareup.leakcanary:leakcanary-android-no-op:${Versions.leakcanary}" + releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:${Versions.leakcanary}" + firebaseImplementation "com.squareup.leakcanary:leakcanary-android:${Versions.leakcanary}" + + implementation project(':bhaskar') + implementation project(':newspoint') + implementation project(':partnerrepository') +} + +// ------------------------------------------------------------------------------------------------- +// LeakCanary - Ensure the no-op dependency is always used in JVM tests. +// ------------------------------------------------------------------------------------------------- + +configurations.all { config -> + if (config.name.contains('UnitTest') || config.name.contains('AndroidTest')) { + config.resolutionStrategy.eachDependency { details -> + if (details.requested.group == 'com.squareup.leakcanary' && details.requested.name == 'leakcanary-android') { + details.useTarget(group: details.requested.group, name: 'leakcanary-android-no-op', version: details.requested.version) + } + } + } +} + +// ------------------------------------------------------------------------------------------------- +// Generate blocklists +// ------------------------------------------------------------------------------------------------- + +def blockListOutputDir = 'src/webkit/res/raw' + +task buildBlocklists(type: Copy) { + from('../shavar-prod-lists') { + include '*.json' + } + into blockListOutputDir + + // Android can't handle dashes in the filename, so we need to rename: + rename 'disconnect-blacklist.json', 'blocklist.json' + rename 'disconnect-entitylist.json', 'entitylist.json' + // google_mapping.json already has an expected name +} + +clean.doLast { + file(blockListOutputDir).deleteDir() +} + +tasks.whenTaskAdded { task -> + def name = task.name + if (name.contains("generate") && name.contains("Webkit") && name.contains("Resources")) { + task.dependsOn buildBlocklists + } +} + +// ------------------------------------------------------------------------------------------------- +// Adjust: Read token from environment variable (Only release builds) +// ------------------------------------------------------------------------------------------------- + +android.applicationVariants.all { variant -> + def variantName = variant.getName() + + print(variantName + ": ") + + // release and nightly will have Adjust. just nightly will use sandbox environment. + if (variantName.contains("Release")) { + def token = System.getenv("ADJUST_TOKEN_FOCUS") ?: null + + if (token != null) { + buildConfigField 'String', 'ADJUST_TOKEN', '"' + token + '"' + if (variantName.contains("preview")) { + buildConfigField 'String', 'ADJUST_ENVIRONMENT', 'com.adjust.sdk.AdjustConfig.ENVIRONMENT_SANDBOX' + } else if (variantName.contains("focus")) { + buildConfigField 'String', 'ADJUST_ENVIRONMENT', 'com.adjust.sdk.AdjustConfig.ENVIRONMENT_PRODUCTION' + } else { + buildConfigField 'String', 'ADJUST_ENVIRONMENT', 'null' + } + println "Added adjust token set from environment variable" + + def tracker = System.getenv("ADJUST_SIDELOAD_TRACKER") ?: null + if (tracker != null) { + buildConfigField 'String', 'ADJUST_DEFAULT_TRACKER', '"' + tracker + '"' + } else { + buildConfigField 'String', 'ADJUST_DEFAULT_TRACKER', 'null' + logger.error(variant.getName() + ": Not setting adjust default tracker (environment variable not set)") + } + } else { + buildConfigField 'String', 'ADJUST_TOKEN', 'null' + buildConfigField 'String', 'ADJUST_ENVIRONMENT', 'null' + buildConfigField 'String', 'ADJUST_DEFAULT_TRACKER', 'null' + println("Not setting adjust token (environment variable not set)") + } + } else { + buildConfigField 'String', 'ADJUST_TOKEN', 'null' + buildConfigField 'String', 'ADJUST_ENVIRONMENT', 'null' + buildConfigField 'String', 'ADJUST_DEFAULT_TRACKER', 'null' + + println("Not setting adjust token (Not a focus release build)") + } + if (variant.buildType.name == "release" || variant.buildType.name == "firebase") { + variant.assemble.doFirst { + if (SystemEnv.google_app_id == null || SystemEnv.default_web_client_id == null || + SystemEnv.firebase_database_url == null || SystemEnv.gcm_defaultSenderId == null || + SystemEnv.google_api_key == null || SystemEnv.google_crash_reporting_api_key == null || + SystemEnv.project_id == null) { + logger.warn("If you want to enable Firebase, please follow the steps:") + logger.warn("1. Download google-services.json and put it in the folder where you run below command.") + logger.warn("2. Run 'python./tools/firebase/firebase_setup.py' and follow the steps.\n") + } + } + } +} + +tasks.whenTaskAdded { task -> + if (name.contains("compile")) { + task.dependsOn generatePreviewLocaleList + task.dependsOn generateFocusLocaleList + } +} + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { + kotlinOptions { + kotlinOptions.allWarningsAsErrors = true + } +} + + + +afterEvaluate { + check.dependsOn 'findbugs', 'pmd', 'checkstyle', 'checkTelemetryDocDirty', 'ktlint' +} + +task checkTelemetryDocDirty() { + + doLast { + Process p = Runtime.getRuntime().exec("git diff ./docs/events.md"); + p.waitFor(); + + BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); + + StringBuilder sb = new StringBuilder(); + String line = ""; + while ((line = reader.readLine()) != null) { + sb.append(line + "\n"); + } + if (sb.length() > 0) { + throw new GradleException("events.md is drity, please commit the change first.\n" + sb.toString()) + } + } +} diff --git a/tests/source-files/realm/react-native/android/build.gradle b/tests/source-files/realm/react-native/android/build.gradle new file mode 100644 index 00000000..d6244d2b --- /dev/null +++ b/tests/source-files/realm/react-native/android/build.gradle @@ -0,0 +1,409 @@ +buildscript { + repositories { + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.1.4' + classpath 'de.undercouch:gradle-download-task:1.2' + } +} + +allprojects { + repositories { + google() + jcenter() + mavenLocal() + maven { + // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm + url "$projectDir/../../tests/react-test-app/node_modules/react-native/android" + } + } +} + +apply plugin: 'com.android.library' +apply plugin: 'maven' +apply plugin: 'signing' +apply plugin: 'de.undercouch.download' + +import de.undercouch.gradle.tasks.download.Download +import org.apache.tools.ant.taskdefs.condition.Os +import org.apache.tools.ant.filters.ReplaceTokens + +// We download various C++ open-source dependencies into downloads. +// We then copy both the downloaded code and our custom makefiles and headers into third-party-ndk. +// After that we build native code from src/main/jni with module path pointing at third-party-ndk. + + +ext.coreVersion = getDependenciesVersion("REALM_CORE_VERSION").trim() +ext.syncVersion = getDependenciesVersion("REALM_SYNC_VERSION").trim() +def currentVersion = getDependenciesVersion("VERSION").trim() +println "Realm Core Version: $ext.coreVersion" +println "Realm Sync Version: $ext.syncVersion" + +def downloadsDir = new File("$projectDir/downloads") +def jscDownloadDir = new File("$projectDir/src/main/jni/jsc") +def coreDownloadDir = new File("$projectDir/src/main/jni") +def publishDir = new File("$projectDir/../../android/") +// to build with sync run: ./gradlew assembleDebug -PbuildWithSync=true +ext.buildSync = project.hasProperty('buildWithSync') ? project.getProperty('buildWithSync').toBoolean() : true + +task generateVersionClass(type: Copy) { + from 'src/main/templates/Version.java' + into 'build/generated-src/main/java/io/realm/react' + filter(ReplaceTokens, tokens: [version: currentVersion]) + outputs.upToDateWhen { false } +} + +task createNativeDepsDirectories { + downloadsDir.mkdirs() +} + +task downloadJSCHeaders(type: Download) { + def jscAPIBaseURL = 'https://svn.webkit.org/repository/webkit/!svn/bc/174650/trunk/Source/JavaScriptCore/API/' + def jscHeaderFiles = ['JSBase.h', 'JSContextRef.h', 'JSObjectRef.h', 'JSRetainPtr.h', 'JSStringRef.h', 'JSValueRef.h', 'WebKitAvailability.h'] + + def output = new File(jscDownloadDir, 'JavaScriptCore') + output.mkdirs() + src(jscHeaderFiles.collect { headerName -> "$jscAPIBaseURL$headerName" }) + onlyIfNewer true + overwrite false + dest output + } + +task downloadRealmCore(type: Download) { + if (project.buildSync) { + src "https://static.realm.io/downloads/sync/realm-sync-android-${project.syncVersion}.tar.gz" + } else { + src "https://static.realm.io/downloads/core/realm-core-android-${project.coreVersion}.tar.gz" + } + onlyIfNewer true + overwrite true + if (project.buildSync) { + dest new File(downloadsDir, "realm-core-android-${project.syncVersion}.tar.gz") + } else { + dest new File(downloadsDir, "realm-core-android-${project.coreVersion}.tar.gz") + } +} + +task prepareRealmCore(dependsOn: downloadRealmCore, type:Copy) { + from tarTree(downloadRealmCore.dest) + into "$coreDownloadDir/core" + rename { String fileName -> + fileName.replace("-arm-", "-armeabi-") + } +} + +task downloadOpenSSL_x86(type: Download) { + src "https://static.realm.io/downloads/openssl/1.0.2k/Android/x86/openssl-release-1.0.2k-Android-x86.tar.gz" + onlyIfNewer true + overwrite true + dest new File(downloadsDir, "openssl-release-1.0.2k-Android-x86.tar.gz") +} + +task prepareOpenSSL_x86(dependsOn: downloadOpenSSL_x86, type:Copy) { + from tarTree(downloadOpenSSL_x86.dest) + into "$coreDownloadDir/core" +} + +task downloadOpenSSL_arm(type: Download) { + src "https://static.realm.io/downloads/openssl/1.0.2k/Android/armeabi-v7a/openssl-release-1.0.2k-Android-armeabi-v7a.tar.gz" + onlyIfNewer true + overwrite true + dest new File(downloadsDir, "openssl-release-1.0.2k-Android-armeabi-v7a.tar.gz") +} + +task prepareOpenSSL_arm(dependsOn: downloadOpenSSL_arm, type:Copy) { + from tarTree(downloadOpenSSL_arm.dest) + into "$coreDownloadDir/core" + rename { String fileName -> + fileName.replace("-arm-", "-armeabi-") + } +} + +def getDependenciesVersion(keyName) { + def inputFile = new File(buildscript.sourceFile.getParent() + "/../../dependencies.list") + def line + inputFile.withReader { reader -> + while ((line = reader.readLine())!=null) { + def (key, value) = line.tokenize('=') + if (keyName == key) { + return value + } + } + + throw new GradleException("${keyName} not found in dependencies.list.") + } +} + +def getNdkBuildName() { + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + return "ndk-build.cmd" + } else { + return "ndk-build" + } +} + +def findNdkBuildFullPath() { + // we allow to provide full path to ndk-build tool + if (hasProperty('ndk.command')) { + return property('ndk.command') + } + // or just a path to the containing directory + if (hasProperty('ndk.path')) { + def ndkDir = property('ndk.path') + return new File(ndkDir, getNdkBuildName()).getAbsolutePath() + } + if (System.getenv('ANDROID_NDK') != null) { + def ndkDir = System.getenv('ANDROID_NDK') + return new File(ndkDir, getNdkBuildName()).getAbsolutePath() + } + if (System.getenv('ANDROID_NDK_HOME') != null) { + def ndkDir = System.getenv('ANDROID_NDK_HOME') + return new File(ndkDir, getNdkBuildName()).getAbsolutePath() + } + def ndkDir = android.hasProperty('plugin') ? android.plugin.ndkFolder : + plugins.getPlugin('com.android.library').sdkHandler.getNdkFolder() + if (ndkDir) { + return new File(ndkDir, getNdkBuildName()).getAbsolutePath() + } + return null +} + +def checkNdkVersion(ndkBuildFullPath) { + def ndkPath = new File(ndkBuildFullPath).getParent() + def detectedNdkVersion + def releaseFile = new File(ndkPath, 'RELEASE.TXT') + def propertyFile = new File(ndkPath, 'source.properties') + if (releaseFile.isFile()) { + detectedNdkVersion = releaseFile.text.trim().split()[0].split('-')[0] + } else if (propertyFile.isFile()) { + detectedNdkVersion = getValueFromPropertiesFile(propertyFile, 'Pkg.Revision') + if (detectedNdkVersion == null) { + throw new GradleException("Failed to obtain the NDK version information from ${ndkPath}/source.properties") + } + } else { + throw new GradleException("Neither ${releaseFile.getAbsolutePath()} nor ${propertyFile.getAbsolutePath()} is a file.") + } + if (detectedNdkVersion != project.ndkVersion) { + throw new GradleException("Your NDK version: ${detectedNdkVersion}." + + " Realm JNI must be compiled with the version ${project.ndkVersion} of NDK.") + } +} + +static def getValueFromPropertiesFile(File propFile, String key) { + if (!propFile.isFile() || !propFile.canRead()) { + return null + } + def prop = new Properties() + def reader = propFile.newReader() + try { + prop.load(reader) + } finally { + reader.close() + } + return prop.get(key) +} + +def getNdkBuildFullPath() { + def ndkBuildFullPath = findNdkBuildFullPath() + if (ndkBuildFullPath == null) { + throw new GradleScriptException( + "ndk-build binary cannot be found, check if you've set " + + "\$ANDROID_NDK environment variable correctly or if ndk.dir is " + + "setup in local.properties", + null) + } + if (!new File(ndkBuildFullPath).canExecute()) { + throw new GradleScriptException( + "ndk-build binary " + ndkBuildFullPath + " doesn't exist or isn't executable.\n" + + "Check that the \$ANDROID_NDK environment variable, or ndk.dir in local.proerties, is set correctly.\n" + + "(On Windows, make sure you escape backslashes in local.properties or use forward slashes, e.g. C:\\\\ndk or C:/ndk rather than C:\\ndk)", + null) + } + + checkNdkVersion(ndkBuildFullPath); + + return ndkBuildFullPath +} + +task buildReactNdkLib(dependsOn: [downloadJSCHeaders,prepareRealmCore,prepareOpenSSL_x86,prepareOpenSSL_arm], type: Exec) { + inputs.files('src/main/jni') + outputs.dir("$buildDir/realm-react-ndk/all") + commandLine getNdkBuildFullPath(), + '-e', + project.buildSync ? 'BUILD_TYPE_SYNC=1' : 'BUILD_TYPE_SYNC=0', + 'NDK_PROJECT_PATH=null', + "NDK_APPLICATION_MK=$projectDir/src/main/jni/Application.mk", + 'NDK_OUT=' + temporaryDir, + "NDK_LIBS_OUT=$buildDir/realm-react-ndk/all", + '-C', file('src/main/jni').absolutePath, + 'NDK_LOG=1', + 'NDK_DEBUG=' + (DEBUG_BUILD.toBoolean() ? '1' : '0'), + '--jobs', Runtime.runtime.availableProcessors(), + 'V=1' +} + +task cleanReactNdkLib(type: Exec) { + commandLine getNdkBuildFullPath(), + '-C', file('src/main/jni').absolutePath, + 'clean' +} + +task packageReactNdkLibs(dependsOn: buildReactNdkLib, type: Copy) { + from "$buildDir/realm-react-ndk/all" + exclude '**/libjsc.so' + exclude '**/gdbserver' + exclude '**/gdb.setup' + into "$buildDir/realm-react-ndk/exported" +} + +android { + compileSdkVersion 26 + + defaultConfig { + minSdkVersion 16 + targetSdkVersion 26 + } + + sourceSets.main { + java.srcDir "$buildDir/generated-src/main/java" + jni.srcDirs = [] + jniLibs.srcDir "$buildDir/realm-react-ndk/exported" + res.srcDirs = ['src/main/res/devsupport', 'src/main/res/shell'] + } + + tasks.withType(JavaCompile) { + compileTask -> compileTask.dependsOn generateVersionClass, packageReactNdkLibs + } + + clean.dependsOn cleanReactNdkLib + + lintOptions { + abortOnError false + } +} + +task publishAndroid(dependsOn: [generateVersionClass, packageReactNdkLibs], type: Sync) { + // Copy task can only have one top level + into "$publishDir" + + // copy java source + into ('/src/main') { + from "$projectDir/src/main", "$buildDir/generated-src/main" + exclude '**/jni/**', '**/templates/**' + } + + // add compiled shared object + into ('/src/main/jniLibs') { + from "$buildDir/realm-react-ndk/exported/" + } + + // copy gradle wrapper files + FileTree gradleWrapper = fileTree(projectDir).include('gradlew*').include('gradle/**') + into ('/') { + from gradleWrapper + } + + // copy and rename template build.gradle + into ('/') { + from "$projectDir/publish_android_template" + rename { String fileName -> + 'build.gradle' + } + } + + // copy analytics script + into ('/') { + from "$projectDir/analytics_template" + rename { String fileName -> + 'analytics.gradle' + } + } +} + +// publishing into maven local + +def configureRealmReactNativePom(def pom) { + pom.project { + name POM_NAME + artifactId POM_ARTIFACT_ID + packaging POM_PACKAGING + description POM_DESCRIPTION + url 'https://github.com/realm/realm-js' + + issueManagement { + system 'github' + url 'https://github.com/realm/realm-js/issues' + } + + scm { + url 'scm:https://github.com/realm/realm-js' + connection 'scm:git@github.com:realm/realm-js.git' + developerConnection 'scm:git@github.com:realm/realm-js.git' + } + + licenses { + license { + name 'The Apache Software License, Version 2.0' + url 'http://www.apache.org/licenses/LICENSE-2.0.txt' + distribution 'repo' + } + } + } +} + +afterEvaluate { project -> + task androidSourcesJar(type: Jar) { + classifier = 'sources' + from android.sourceSets.main.java.srcDirs + include '**/*.java' + } + + android.libraryVariants.all { variant -> + def name = variant.name.capitalize() + task "jar${name}"(type: Jar, dependsOn: variant.javaCompile) { + from variant.javaCompile.destinationDir + } + } + + artifacts { + archives androidSourcesJar + } + + version = currentVersion + group = GROUP + + signing { + required { false } + sign configurations.archives + } + + task installArchives(type: Upload) { + configuration = configurations.archives + repositories.mavenDeployer { + beforeDeployment { + MavenDeployment deployment -> signing.signPom(deployment) + } + + repository url: "file://${System.properties['user.home']}/.m2/repository" + configureRealmReactNativePom pom + } + } +} + +def dependencyType = "implementation" +def providedDependencyType = "compileOnly" +try { + project.getConfigurations().getByName("implementation") +} catch (UnknownConfigurationException e) { + // Pre 3.0 Android Gradle Plugin + dependencyType = "compile" + providedDependencyType = "provided" +} + +project.dependencies { + add(providedDependencyType, 'com.squareup.okhttp3:okhttp:3.9.0') + add(providedDependencyType, 'com.facebook.react:react-native:+') + add(dependencyType, 'org.nanohttpd:nanohttpd:2.2.0') +} diff --git a/tests/source-files/ut.ewh.audiometrytest/app/build.gradle b/tests/source-files/ut.ewh.audiometrytest/app/build.gradle new file mode 100644 index 00000000..640b6678 --- /dev/null +++ b/tests/source-files/ut.ewh.audiometrytest/app/build.gradle @@ -0,0 +1,41 @@ +apply plugin: 'android' + +android { + compileSdkVersion 21 + buildToolsVersion "21.1.1" + + defaultConfig { + minSdkVersion 8 + targetSdkVersion 21 + versionCode 14 + versionName "1.65" + } + signingConfigs{ + releaseSign{ + storeFile file("/Users/reecestevens/keys/keystore.jks") + //storePassword System.console().readLine("\nKeystore password: ") + storePassword System.getenv("KSTOREPWD") + keyAlias "AppKey" + //keyPassword System.console().readLine("\nKey password: ") + keyPassword System.getenv("KEYPWD") + } + } + buildTypes { + release { + minifyEnabled true; + debuggable false + signingConfig signingConfigs.releaseSign + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' + } + } +} + +repositories { + maven { url "https://jitpack.io" } +} + +dependencies { + compile 'com.android.support:appcompat-v7:21.0.2' + compile 'com.github.PhilJay:MPAndroidChart:v2.0.9' + compile fileTree(dir: 'libs', include: ['*.jar']) +}