From 7390cb68e3bd054b30c43736ff8c10a093477d25 Mon Sep 17 00:00:00 2001 From: daviss Date: Fri, 20 Sep 2024 11:33:49 -0700 Subject: [PATCH 1/3] remove unused string --- protosimplestore/src/main/res/values/strings.xml | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 protosimplestore/src/main/res/values/strings.xml diff --git a/protosimplestore/src/main/res/values/strings.xml b/protosimplestore/src/main/res/values/strings.xml deleted file mode 100644 index 7bf4e46..0000000 --- a/protosimplestore/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - Proto SimpleStore - From ee0fce2fbc3834df6d25a5ed4ede25e58d2d097b Mon Sep 17 00:00:00 2001 From: daviss Date: Fri, 20 Sep 2024 12:08:17 -0700 Subject: [PATCH 2/3] fix github action yaml file --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index df0a981..59cc6d2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,7 +14,7 @@ on: jobs: build: name: JDK ${{ matrix.java_version }} - runs-on: macOS-latest + runs-on: macos-13 strategy: matrix: java_version: [11] @@ -53,7 +53,7 @@ jobs: abi: x86 - name: Full check run: ./gradlew check --stacktrace - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: Sample App path: sample/build/outputs From 8f43f6a190d2141f363b45548bd996e58019fa5c Mon Sep 17 00:00:00 2001 From: psteiger Date: Sat, 21 Sep 2024 17:13:20 -0400 Subject: [PATCH 3/3] - Move to Version Catalogs. - Use precompiled scripts for common build logic. - Bump library versions. - Bump Gradle version. - Use JVM Toolchain (Java 11). - Resolve IDE warnings that has an obviously safe resolution: finalize vars, use try-with-resources, etc, when applicable. --- .github/workflows/main.yml | 2 +- .github/workflows/release.yml | 4 +- .gitignore | 1 - build.gradle | 93 ++----------------- conventions/.gitignore | 1 + conventions/build.gradle.kts | 53 +++++++++++ conventions/settings.gradle.kts | 24 +++++ .../main/kotlin/android-convention.gradle.kts | 37 ++++++++ .../main/kotlin/dokka-convention.gradle.kts | 26 ++++++ .../kotlin/errorprone-convention.gradle.kts | 45 +++++++++ .../kotlin/protobuf-convention.gradle.kts | 37 ++++++++ .../kotlin/spotless-convention.gradle.kts | 52 +++++++++++ gradle.properties | 4 +- gradle/dependencies.gradle | 84 ----------------- gradle/libs.versions.toml | 42 +++++++++ gradle/test-libs.versions.toml | 19 ++++ gradle/wrapper/gradle-wrapper.properties | 2 +- protosimplestore/.gitignore | 1 + protosimplestore/build.gradle | 59 ++++-------- protosimplestore/src/main/AndroidManifest.xml | 4 +- .../proto/impl/SimpleProtoStoreImpl.java | 1 - .../proto/SimpleProtoStoreImplTest.java | 9 +- sample/build.gradle | 44 ++++----- sample/src/main/AndroidManifest.xml | 7 +- .../uber/simplestore/sample/JavaActivity.java | 3 +- .../uber/simplestore/sample/KotlinActivity.kt | 1 - settings.gradle | 32 ++++--- simplestore/build.gradle | 52 ++++------- .../uber/simplestore/SanityEspressoTest.java | 49 +++++----- simplestore/src/main/AndroidManifest.xml | 4 +- .../impl/AndroidDirectoryProvider.java | 2 +- .../com/uber/simplestore/impl/AtomicFile.java | 9 +- .../simplestore/impl/SimpleStoreFactory.java | 3 +- .../simplestore/impl/SimpleStoreImpl.java | 5 +- .../primitive/PrimitiveSimpleStoreImpl.java | 1 - .../uber/simplestore/impl/AtomicFileTest.java | 38 +------- .../impl/SimpleStoreFactoryTest.java | 2 +- .../simplestore/impl/SimpleStoreImplTest.java | 9 +- testing/build.gradle | 38 +++----- testing/src/main/AndroidManifest.xml | 4 +- .../simplestore/fakes/FakeSimpleStore.java | 1 - testing/src/main/res/values/strings.xml | 4 +- .../uber/simplestore/fakes/FakeUnitTest.java | 46 ++++----- 43 files changed, 520 insertions(+), 434 deletions(-) create mode 100644 conventions/.gitignore create mode 100644 conventions/build.gradle.kts create mode 100644 conventions/settings.gradle.kts create mode 100644 conventions/src/main/kotlin/android-convention.gradle.kts create mode 100644 conventions/src/main/kotlin/dokka-convention.gradle.kts create mode 100644 conventions/src/main/kotlin/errorprone-convention.gradle.kts create mode 100644 conventions/src/main/kotlin/protobuf-convention.gradle.kts create mode 100644 conventions/src/main/kotlin/spotless-convention.gradle.kts delete mode 100644 gradle/dependencies.gradle create mode 100644 gradle/libs.versions.toml create mode 100644 gradle/test-libs.versions.toml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 59cc6d2..630b26d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,7 +17,7 @@ jobs: runs-on: macos-13 strategy: matrix: - java_version: [11] + java_version: [17] steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 25c891a..83f4d9b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,10 +11,10 @@ jobs: steps: - name: Checkout uses: actions/checkout@v2 - - name: Install JDK 11 + - name: Install JDK 17 uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - name: Gradle Wrapper Validation uses: gradle/wrapper-validation-action@v1 - name: Cache gradle packages diff --git a/.gitignore b/.gitignore index 68e3592..bde6d80 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -protosimplestore/test *.iml .gradle /local.properties diff --git a/build.gradle b/build.gradle index 5d968b4..026bcb5 100644 --- a/build.gradle +++ b/build.gradle @@ -1,23 +1,15 @@ -import net.ltgt.gradle.errorprone.CheckSeverity import org.jetbrains.dokka.gradle.DokkaTaskPartial -buildscript { - apply from: rootProject.file('gradle/dependencies.gradle') - repositories { - google() - mavenCentral() - gradlePluginPortal() - } - dependencies { - classpath "com.android.tools.build:gradle:${deps.build.gradlePlugins.android}" - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${deps.build.gradlePlugins.kotlin}" - classpath "net.ltgt.gradle:gradle-errorprone-plugin:${deps.build.gradlePlugins.errorProne}" - classpath "net.ltgt.gradle:gradle-nullaway-plugin:${deps.build.gradlePlugins.nullAway}" - classpath "com.diffplug.spotless:spotless-plugin-gradle:${deps.build.gradlePlugins.spotless}" - classpath "com.google.protobuf:protobuf-gradle-plugin:${deps.build.gradlePlugins.protobuf}" - classpath "com.vanniktech:gradle-maven-publish-plugin:${deps.build.gradlePlugins.mavenPublish}" - classpath "org.jetbrains.dokka:dokka-gradle-plugin:${deps.build.gradlePlugins.dokka}" - } +plugins { + alias(libs.plugins.android.application) apply false + alias(libs.plugins.android.library) apply false + alias(libs.plugins.kotlin.android) apply false + alias(libs.plugins.errorprone) apply false + alias(libs.plugins.nullaway) apply false + alias(libs.plugins.spotless) apply false + alias(libs.plugins.protobuf) apply false + alias(libs.plugins.gradle.maven.publish) apply false + alias(libs.plugins.dokka) apply false } apply plugin: 'org.jetbrains.dokka' @@ -26,68 +18,3 @@ tasks.dokkaHtmlMultiModule { outputDirectory.set(new File(rootDir,"docs/0.x")) includes.from(project.layout.projectDirectory.file("README.md")) } - -subprojects { - var isSample = project.name == "sample" - repositories { - google() - mavenCentral() - } - - apply from: rootProject.file('gradle/dependencies.gradle') - apply plugin: 'com.diffplug.gradle.spotless' - spotless { - format 'misc', { - target '**/*.md', '**/.gitignore' - - indentWithTabs() - trimTrailingWhitespace() - endWithNewline() - } - java { - target "**/*.java" - googleJavaFormat(deps.versions.gjf) - licenseHeaderFile rootProject.file('spotless/copyright.java') - removeUnusedImports() - trimTrailingWhitespace() - endWithNewline() - } - groovyGradle { - target '**/*.gradle' - trimTrailingWhitespace() - endWithNewline() - } - } - - apply plugin: 'net.ltgt.errorprone' - apply plugin: 'net.ltgt.nullaway' - dependencies { - errorproneJavac deps.build.errorProneJavac - errorprone deps.build.nullAway - errorprone deps.build.errorProne - } - tasks.withType(JavaCompile).configureEach { - options.errorprone.nullaway { - severity = CheckSeverity.ERROR - annotatedPackages.add("com.uber") - unannotatedSubPackages.add("com.uber.simplestore.proto") - treatGeneratedAsUnannotated = true - } - options.errorprone.disableWarningsInGeneratedCode = true - } - - if (!isSample) { - apply plugin: 'org.jetbrains.dokka' - tasks.withType(DokkaTaskPartial).configureEach { - outputDirectory.set(new File(buildDir, "docs/partial")) - moduleName.set(project.property("POM_ARTIFACT_ID").toString()) - moduleVersion.set(project.property("VERSION_NAME").toString()) - } - } -} - -task clean(type: Delete) { - delete rootProject.buildDir -} - -apply from: 'gradle/dependencies.gradle' diff --git a/conventions/.gitignore b/conventions/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/conventions/.gitignore @@ -0,0 +1 @@ +/build diff --git a/conventions/build.gradle.kts b/conventions/build.gradle.kts new file mode 100644 index 0000000..3f3692b --- /dev/null +++ b/conventions/build.gradle.kts @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2024. Uber Technologies + * + * 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. + */ +plugins { + `kotlin-dsl` + `kotlin-dsl-precompiled-script-plugins` + alias(libs.plugins.spotless) +} + +repositories { + google() + mavenCentral() + gradlePluginPortal() +} + +spotless { + groovyGradle { + target("**/*.gradle") + trimTrailingWhitespace() + endWithNewline() + } + + kotlinGradle { + target("**/*.gradle.kts") + trimTrailingWhitespace() + endWithNewline() + } +} + +dependencies { + // Workaround for using version catalog on precompiled scripts. + // https://github.com/gradle/gradle/issues/15383#issuecomment-779893192 + implementation(files((libs as Any).javaClass.superclass.protectionDomain.codeSource.location)) + implementation(gradleApi()) + implementation(libs.gradle.android.library.plugin) + implementation(libs.gradle.errorprone.plugin) + implementation(libs.gradle.nullaway.plugin) + implementation(libs.gradle.spotless.plugin) + implementation(libs.gradle.dokka.plugin) + implementation(libs.gradle.protobuf.plugin) +} diff --git a/conventions/settings.gradle.kts b/conventions/settings.gradle.kts new file mode 100644 index 0000000..03af48e --- /dev/null +++ b/conventions/settings.gradle.kts @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024. Uber Technologies + * + * 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. + */ +dependencyResolutionManagement { + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} + +rootProject.name = "conventions" diff --git a/conventions/src/main/kotlin/android-convention.gradle.kts b/conventions/src/main/kotlin/android-convention.gradle.kts new file mode 100644 index 0000000..c5cafaa --- /dev/null +++ b/conventions/src/main/kotlin/android-convention.gradle.kts @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024. Uber Technologies + * + * 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. + */ +plugins { + id("com.android.library") +} + +android { + compileSdk = 34 + + defaultConfig { + minSdk = 19 + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } +} + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } +} diff --git a/conventions/src/main/kotlin/dokka-convention.gradle.kts b/conventions/src/main/kotlin/dokka-convention.gradle.kts new file mode 100644 index 0000000..7181d14 --- /dev/null +++ b/conventions/src/main/kotlin/dokka-convention.gradle.kts @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024. Uber Technologies + * + * 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. + */ +import org.jetbrains.dokka.gradle.DokkaTaskPartial + +plugins { + id("org.jetbrains.dokka") +} + +tasks.withType().configureEach { + outputDirectory.set(File(layout.buildDirectory.asFile.get().path, "docs/partial")) + moduleName.set(project.property("POM_ARTIFACT_ID").toString()) + moduleVersion.set(project.property("VERSION_NAME").toString()) +} diff --git a/conventions/src/main/kotlin/errorprone-convention.gradle.kts b/conventions/src/main/kotlin/errorprone-convention.gradle.kts new file mode 100644 index 0000000..b0177e7 --- /dev/null +++ b/conventions/src/main/kotlin/errorprone-convention.gradle.kts @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024. Uber Technologies + * + * 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. + */ +import net.ltgt.gradle.errorprone.CheckSeverity +import net.ltgt.gradle.errorprone.errorprone +import net.ltgt.gradle.nullaway.nullaway +import org.gradle.accessors.dm.LibrariesForLibs + +plugins { + id("net.ltgt.errorprone") + id("net.ltgt.nullaway") +} + +val libs = the() + +dependencies { + errorproneJavac(libs.errorprone.javac) + errorprone(libs.errorprone) + errorprone(libs.nullaway) +} + +tasks.withType().configureEach { + options.errorprone { + disableWarningsInGeneratedCode = true + + nullaway { + severity = CheckSeverity.ERROR + annotatedPackages.add("com.uber") + unannotatedSubPackages.add("com.uber.simplestore.proto") + treatGeneratedAsUnannotated = true + } + } +} diff --git a/conventions/src/main/kotlin/protobuf-convention.gradle.kts b/conventions/src/main/kotlin/protobuf-convention.gradle.kts new file mode 100644 index 0000000..9b968b1 --- /dev/null +++ b/conventions/src/main/kotlin/protobuf-convention.gradle.kts @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024. Uber Technologies + * + * 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. + */ +import org.gradle.accessors.dm.LibrariesForLibs + +plugins { + id("com.google.protobuf") +} + +val libs = the() + +protobuf { + protoc { + artifact = "com.google.protobuf:protoc:${libs.versions.protobuf.get()}" + } + generateProtoTasks { + all().forEach { task -> + task.builtins { + create("java") { + option("lite") + } + } + } + } +} diff --git a/conventions/src/main/kotlin/spotless-convention.gradle.kts b/conventions/src/main/kotlin/spotless-convention.gradle.kts new file mode 100644 index 0000000..6d404dd --- /dev/null +++ b/conventions/src/main/kotlin/spotless-convention.gradle.kts @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2024. Uber Technologies + * + * 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. + */ +import org.gradle.accessors.dm.LibrariesForLibs + +plugins { + id("com.diffplug.spotless") +} + +val libs = the() + +spotless { + format("misc") { + target("**/*.md", "**/.gitignore") + indentWithTabs() + trimTrailingWhitespace() + endWithNewline() + } + + java { + target("src/*/java/**/*.java") + googleJavaFormat(libs.versions.javaFormat.get()) + licenseHeaderFile(rootProject.file("spotless/copyright.java")) + removeUnusedImports() + trimTrailingWhitespace() + endWithNewline() + } + + groovyGradle { + target("**/*.gradle") + trimTrailingWhitespace() + endWithNewline() + } + + kotlinGradle { + target("**/*.gradle.kts") + trimTrailingWhitespace() + endWithNewline() + } +} diff --git a/gradle.properties b/gradle.properties index 3c1b3b4..2a02724 100644 --- a/gradle.properties +++ b/gradle.properties @@ -36,4 +36,6 @@ GITHUB_DOWNLOAD_PREFIX=https\://github.com/uber/simple-store/releases/download/ GITHUB_BRANCH=master SONATYPE_HOST=DEFAULT -RELEASE_SIGNING_ENABLED=true \ No newline at end of file +RELEASE_SIGNING_ENABLED=true +# will be removed in AGP 9.0 +android.buildFeatures.buildConfig=true diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle deleted file mode 100644 index 83fa51e..0000000 --- a/gradle/dependencies.gradle +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2019. Uber Technologies - * - * 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. - */ - -def versions = [ - kotlin : '1.8.20', - errorProne : '2.5.1', - gjf : '1.7', - nullawayPlugin: '0.8.0', - protobuf : '3.22.3' -] - -def build = [ - buildToolsVersion : "30.0.3", - compileSdkVersion : 30, - ci : 'true' == System.getenv('CI'), - minSdkVersion : 19, - targetSdkVersion : 30, - javaVersion : JavaVersion.VERSION_1_8, - - errorProne : "com.google.errorprone:error_prone_core:${versions.errorProne}", - errorProneJavac : "com.google.errorprone:javac:9+181-r4173-1", - errorProneCheckApi : "com.google.errorprone:error_prone_check_api:${versions.errorProne}", - errorProneTestHelpers: "com.google.errorprone:error_prone_test_helpers:${versions.errorProne}", - nullAway : 'com.uber.nullaway:nullaway:0.8.0', - gradlePlugins : [ - android : '7.4.0', - kotlin : "${versions.kotlin}", - errorProne: '2.0.1', - nullAway : '1.3.0', - protobuf : '0.8.12', - spotless : '4.3.0', - mavenPublish : '0.27.0', - dokka : '1.6.10', - ] -] - -def androidx = [ - appCompat : "androidx.appcompat:appcompat:1.2.0" -] - -def test = [ - junit : 'junit:junit:4.13.1', - junitX : 'androidx.test.ext:junit:1.0.0', - truth : 'com.google.truth:truth:1.1', - truthX : 'androidx.test.ext:truth:1.5.0', - robolectric: 'org.robolectric:robolectric:4.4', - espresso : 'androidx.test.espresso:espresso-core:3.5.1', - runner : 'androidx.test:runner:1.5.2', - rules : 'androidx.test:rules:1.5.0', - orchestrator : 'androidx.test:orchestrator:1.4.2', -] - -def kotlin = [ - stdLibJdk8 : "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${versions.kotlin}" -] - -def external = [ - guavaAndroid: 'com.google.guava:guava:29.0-android', - findBugs : 'com.google.code.findbugs:jsr305:3.0.2', - protoLite : "com.google.protobuf:protobuf-javalite:${versions.protobuf}", - protoc : "${versions.protobuf}", -] - -ext.deps = [ - "build" : build, - "test" : test, - "androidx": androidx, - "kotlin" : kotlin, - "external": external, - "versions": versions -] diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..dc75e30 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,42 @@ +[versions] +agp = "8.6.1" +annotation = "1.8.2" +appcompat = "1.7.0" +guava = "33.2.1-android" +kotlin = "2.0.0" +errorProne = "4.0.1" +errorProneJavaC = "9+181-r4173-1" +nullAway = "1.3.0" +spotless = "6.25.0" +protobuf = "3.22.3" +protobufPlugin = "0.9.4" +gradleMavenPublishPlugin = "0.29.0" +dokka = "1.9.20" +javaFormat = "1.17.0" + +[libraries] +androidx-annotation = { group = "androidx.annotation", name = "annotation", version.ref = "annotation" } +androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } +protobuf-javalite = { group = "com.google.protobuf", name = "protobuf-javalite", version.ref = "protobuf" } +guava = { group = "com.google.guava", name = "guava", version.ref = "guava" } +nullaway = { group = "com.uber.nullaway", name = "nullaway", version.ref = "nullAway" } +errorprone = { group = "com.google.errorprone", name = "error_prone_core", version.ref = "errorProne" } +errorprone-javac = { group = "com.google.errorprone", name = "javac", version.ref = "errorProneJavaC" } +# Conventions +gradle-spotless-plugin = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" } +gradle-errorprone-plugin = { module = "net.ltgt.gradle:gradle-errorprone-plugin", version.ref = "errorProne" } +gradle-nullaway-plugin = { module = "net.ltgt.gradle:gradle-nullaway-plugin", version.ref = "nullAway" } +gradle-dokka-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "dokka" } +gradle-protobuf-plugin = { module = "com.google.protobuf:protobuf-gradle-plugin", version.ref = "protobufPlugin" } +gradle-android-library-plugin = { module = "com.android.library:com.android.library.gradle.plugin", version.ref = "agp" } + +[plugins] +android-application = { id = "com.android.application", version.ref = "agp" } +android-library = { id = "com.android.library", version.ref = "agp" } +kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +errorprone = { id = "net.ltgt.errorprone", version.ref = "errorProne" } +nullaway = { id = "net.ltgt.nullaway", version.ref = "nullAway" } +spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } +protobuf = { id = "com.google.protobuf", version.ref = "protobufPlugin" } +gradle-maven-publish = { id = "com.vanniktech.maven.publish", version.ref = "gradleMavenPublishPlugin" } +dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } \ No newline at end of file diff --git a/gradle/test-libs.versions.toml b/gradle/test-libs.versions.toml new file mode 100644 index 0000000..315f5b1 --- /dev/null +++ b/gradle/test-libs.versions.toml @@ -0,0 +1,19 @@ +[versions] +orchestrator = "1.5.0" +robolectric = "4.13" +rules = "1.6.1" +runner = "1.6.2" +junit = "4.13.2" +androidxJunit = "1.2.1" +truth = "1.4.4" +androidxTruth = "1.6.0" + +[libraries] +truth = { group = "com.google.truth", name = "truth", version.ref = "truth" } +androidx-truth = { group = "androidx.test.ext", name = "truth", version.ref = "androidxTruth" } +junit = { group = "junit", name = "junit", version.ref = "junit" } +androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidxJunit" } +robolectric = { group = "org.robolectric", name = "robolectric", version.ref = "robolectric" } +androidx-orchestrator = { group = "androidx.test", name = "orchestrator", version.ref = "orchestrator" } +androidx-rules = { group = "androidx.test", name = "rules", version.ref = "rules" } +androidx-runner = { group = "androidx.test", name = "runner", version.ref = "runner" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 60a3091..eb8bfb1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Dec 01 12:24:16 PST 2020 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/protosimplestore/.gitignore b/protosimplestore/.gitignore index 796b96d..c2316d5 100644 --- a/protosimplestore/.gitignore +++ b/protosimplestore/.gitignore @@ -1 +1,2 @@ /build +/files diff --git a/protosimplestore/build.gradle b/protosimplestore/build.gradle index f5d366d..d760966 100644 --- a/protosimplestore/build.gradle +++ b/protosimplestore/build.gradle @@ -1,19 +1,17 @@ plugins { - id 'com.android.library' - id 'kotlin-android' - id 'com.google.protobuf' - id 'com.diffplug.gradle.spotless' - id 'org.jetbrains.dokka' - id 'com.vanniktech.maven.publish' + alias(libs.plugins.kotlin.android) + alias(libs.plugins.gradle.maven.publish) + id("protobuf-convention") + id("spotless-convention") + id("dokka-convention") + id("errorprone-convention") + id("android-convention") } android { - compileSdkVersion deps.build.compileSdkVersion + namespace 'com.uber.simplestore.proto' defaultConfig { - minSdkVersion deps.build.minSdkVersion - targetSdkVersion deps.build.targetSdkVersion - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" // The following argument makes the Android Test Orchestrator run its // "pm clear" command after each test invocation. This command ensures @@ -24,44 +22,19 @@ android { testOptions { execution 'ANDROIDX_TEST_ORCHESTRATOR' } - - defaultConfig { - minSdkVersion deps.build.minSdkVersion - targetSdkVersion deps.build.targetSdkVersion - } - - compileOptions { - sourceCompatibility deps.build.javaVersion - targetCompatibility deps.build.javaVersion - } -} - -protobuf { - protoc { - artifact = "com.google.protobuf:protoc:${deps.external.protoc}" - } - generateProtoTasks { - all().each { task -> - task.builtins { - java { - option 'lite' - } - } - } - } } dependencies { implementation project(":simplestore") - implementation deps.external.findBugs - api deps.external.protoLite + api libs.protobuf.javalite - testImplementation deps.test.junit - testImplementation deps.test.truth - testImplementation deps.test.robolectric + testImplementation testLibs.junit + testImplementation testLibs.truth + testImplementation testLibs.robolectric - androidTestImplementation deps.test.runner - androidTestImplementation deps.test.rules + androidTestImplementation testLibs.androidx.runner + androidTestImplementation testLibs.androidx.rules + androidTestImplementation testLibs.androidx.rules - androidTestUtil deps.test.orchestrator + androidTestUtil testLibs.androidx.orchestrator } diff --git a/protosimplestore/src/main/AndroidManifest.xml b/protosimplestore/src/main/AndroidManifest.xml index 8e97d9e..5c3d365 100644 --- a/protosimplestore/src/main/AndroidManifest.xml +++ b/protosimplestore/src/main/AndroidManifest.xml @@ -1,2 +1,2 @@ - + + diff --git a/protosimplestore/src/main/java/com/uber/simplestore/proto/impl/SimpleProtoStoreImpl.java b/protosimplestore/src/main/java/com/uber/simplestore/proto/impl/SimpleProtoStoreImpl.java index 02230e2..6bf9c0d 100644 --- a/protosimplestore/src/main/java/com/uber/simplestore/proto/impl/SimpleProtoStoreImpl.java +++ b/protosimplestore/src/main/java/com/uber/simplestore/proto/impl/SimpleProtoStoreImpl.java @@ -27,7 +27,6 @@ import com.uber.simplestore.proto.SimpleProtoStore; import javax.annotation.Nullable; -@SuppressWarnings("UnstableApiUsage") public final class SimpleProtoStoreImpl implements SimpleProtoStore { private final SimpleStore simpleStore; private final NamespaceConfig config; diff --git a/protosimplestore/src/test/java/com/uber/simplestore/proto/SimpleProtoStoreImplTest.java b/protosimplestore/src/test/java/com/uber/simplestore/proto/SimpleProtoStoreImplTest.java index c2de564..1a8dc4c 100644 --- a/protosimplestore/src/test/java/com/uber/simplestore/proto/SimpleProtoStoreImplTest.java +++ b/protosimplestore/src/test/java/com/uber/simplestore/proto/SimpleProtoStoreImplTest.java @@ -35,13 +35,12 @@ import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; -@SuppressWarnings("UnstableApiUsage") @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) public class SimpleProtoStoreImplTest { private static final String TEST_KEY = "test"; private static final String FOO = "foo"; - private Context context = RuntimeEnvironment.systemContext; + private final Context context = RuntimeEnvironment.getApplication(); private final DirectoryProvider directoryProvider = new AndroidDirectoryProvider(context); @Test @@ -54,7 +53,7 @@ public void defaultInstanceWhenEmpty() throws Exception { } @Test - public void defaultInstanceWhenEmpty_withRequiredField() throws Exception { + public void defaultInstanceWhenEmpty_withRequiredField() { try (SimpleProtoStore store = SimpleProtoStoreFactory.create(directoryProvider, "")) { ListenableFuture future = store.get(TEST_KEY, TestProto.Required.parser()); @@ -111,8 +110,8 @@ public void failsGracefullyOnParsingFail() throws Exception { @Test public void whenCache_returnsDefaultOnParseFailure() throws Exception { - try (SimpleStore simpleStore = SimpleProtoStoreFactory.create(directoryProvider, "")) { - simpleStore.put(TEST_KEY, "garbage".getBytes(Charset.defaultCharset())).get(); + try (SimpleStore store = SimpleProtoStoreFactory.create(directoryProvider, "")) { + store.put(TEST_KEY, "garbage".getBytes(Charset.defaultCharset())).get(); } try (SimpleProtoStore store = diff --git a/sample/build.gradle b/sample/build.gradle index c9b59e7..9d9efb2 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -1,44 +1,38 @@ plugins { - id 'com.android.application' - id 'kotlin-android' - id 'com.google.protobuf' - id 'com.diffplug.gradle.spotless' + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.android) + id("protobuf-convention") + id("spotless-convention") } android { - buildToolsVersion deps.build.buildToolsVersion - compileSdkVersion deps.build.compileSdkVersion + namespace 'com.uber.simplestore.sample' + compileSdk 34 defaultConfig { - minSdkVersion deps.build.minSdkVersion - targetSdkVersion deps.build.targetSdkVersion + minSdkVersion 21 + targetSdkVersion 34 } compileOptions { - sourceCompatibility deps.build.javaVersion - targetCompatibility deps.build.javaVersion + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 } -} -protobuf { - protoc { - artifact = "com.google.protobuf:protoc:${deps.external.protoc}" + kotlinOptions { + jvmTarget = '11' } - generateProtoTasks { - all().each { task -> - task.builtins { - java { - option 'lite' - } - } - } +} + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) } } dependencies { - implementation deps.androidx.appCompat - implementation deps.external.protoLite - implementation deps.kotlin.stdLibJdk8 + implementation libs.androidx.appcompat + implementation libs.protobuf.javalite implementation project(":simplestore") implementation project(":protosimplestore") diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index 3d20116..0ce6339 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ + xmlns:tools="http://schemas.android.com/tools"> + android:exported="true"> @@ -17,7 +17,8 @@ + android:exported="true" + android:label="@string/kotlin_name"> diff --git a/sample/src/main/java/com/uber/simplestore/sample/JavaActivity.java b/sample/src/main/java/com/uber/simplestore/sample/JavaActivity.java index 6cfb245..4e6141c 100644 --- a/sample/src/main/java/com/uber/simplestore/sample/JavaActivity.java +++ b/sample/src/main/java/com/uber/simplestore/sample/JavaActivity.java @@ -36,7 +36,6 @@ import com.uber.simplestore.proto.impl.SimpleProtoStoreFactory; /** Store and retrieve a text field. */ -@SuppressWarnings("UnstableApiUsage") public class JavaActivity extends AppCompatActivity { private static final String NAMESPACE_EXTRA = "namespace"; @@ -92,7 +91,7 @@ private void initialize() { DirectoryProvider directoryProvider = new AndroidDirectoryProvider(this); simpleStore = SimpleProtoStoreFactory.create( - directoryProvider, "main" + nesting.toString(), NamespaceConfig.DEFAULT); + directoryProvider, "main" + nesting, NamespaceConfig.DEFAULT); loadMessage(); } diff --git a/sample/src/main/java/com/uber/simplestore/sample/KotlinActivity.kt b/sample/src/main/java/com/uber/simplestore/sample/KotlinActivity.kt index 44bfe27..888fb3d 100644 --- a/sample/src/main/java/com/uber/simplestore/sample/KotlinActivity.kt +++ b/sample/src/main/java/com/uber/simplestore/sample/KotlinActivity.kt @@ -20,7 +20,6 @@ import com.uber.simplestore.executors.StorageExecutors.mainExecutor as mainExecu /** * Store and retrieve a text field. */ -@Suppress("UnstableApiUsage") class KotlinActivity : AppCompatActivity() { private lateinit var textView: TextView private lateinit var simpleStore: SimpleProtoStore diff --git a/settings.gradle b/settings.gradle index c737ce3..433dfa1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,29 +1,35 @@ pluginManagement { - apply from: file('gradle/dependencies.gradle') - resolutionStrategy { - eachPlugin { - switch (requested.id.id) { - case 'net.ltgt.errorprone': - useVersion(deps.build.gradlePlugins.errorProne) - break - case 'net.ltgt.nullaway': - useVersion(deps.build.gradlePlugins.nullAway) - break + repositories { + google { + content { + includeGroupByRegex("com\\.android.*") + includeGroupByRegex("com\\.google.*") + includeGroupByRegex("androidx.*") } } - } - repositories { mavenCentral() - google() gradlePluginPortal() } } + +plugins { + // Provides repository for downloading JDKs. Used by JVM toolchain gradle config. + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' +} + dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() gradlePluginPortal() } + versionCatalogs { + testLibs { + from(files("gradle/test-libs.versions.toml")) + } + } } +includeBuild 'conventions' include ':simplestore', ':protosimplestore', ':testing', ':sample' diff --git a/simplestore/build.gradle b/simplestore/build.gradle index bdef651..1070b68 100644 --- a/simplestore/build.gradle +++ b/simplestore/build.gradle @@ -1,19 +1,16 @@ plugins { - id 'com.android.library' - id 'kotlin-android' - id 'com.diffplug.gradle.spotless' - id 'org.jetbrains.dokka' - id 'com.vanniktech.maven.publish' + alias(libs.plugins.kotlin.android) + alias(libs.plugins.gradle.maven.publish) + id("spotless-convention") + id("dokka-convention") + id("errorprone-convention") + id("android-convention") } android { - buildToolsVersion deps.build.buildToolsVersion - compileSdkVersion deps.build.compileSdkVersion + namespace 'com.uber.simplestore' defaultConfig { - minSdkVersion deps.build.minSdkVersion - targetSdkVersion deps.build.targetSdkVersion - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" // The following argument makes the Android Test Orchestrator run its // "pm clear" command after each test invocation. This command ensures @@ -24,33 +21,22 @@ android { testOptions { execution 'ANDROIDX_TEST_ORCHESTRATOR' } - - defaultConfig { - minSdkVersion deps.build.minSdkVersion - targetSdkVersion deps.build.targetSdkVersion - } - - compileOptions { - sourceCompatibility deps.build.javaVersion - targetCompatibility deps.build.javaVersion - } } dependencies { - implementation deps.external.findBugs - implementation deps.kotlin.stdLibJdk8 - api deps.external.guavaAndroid + implementation libs.androidx.annotation + api libs.guava - testImplementation deps.test.junit - testImplementation deps.test.junitX - testImplementation deps.test.truth - testImplementation deps.test.truthX - testImplementation deps.test.robolectric + testImplementation testLibs.junit + testImplementation testLibs.androidx.junit + testImplementation testLibs.truth + testImplementation testLibs.androidx.truth + testImplementation testLibs.robolectric - androidTestImplementation deps.test.runner - androidTestImplementation deps.test.rules - androidTestImplementation deps.test.junitX - androidTestImplementation deps.test.truthX + androidTestImplementation testLibs.androidx.runner + androidTestImplementation testLibs.androidx.rules + androidTestImplementation testLibs.androidx.junit + androidTestImplementation testLibs.androidx.truth - androidTestUtil deps.test.orchestrator + androidTestUtil testLibs.androidx.orchestrator } diff --git a/simplestore/src/androidTest/java/com/uber/simplestore/SanityEspressoTest.java b/simplestore/src/androidTest/java/com/uber/simplestore/SanityEspressoTest.java index ef47e68..6a27623 100644 --- a/simplestore/src/androidTest/java/com/uber/simplestore/SanityEspressoTest.java +++ b/simplestore/src/androidTest/java/com/uber/simplestore/SanityEspressoTest.java @@ -15,6 +15,7 @@ */ package com.uber.simplestore; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import android.content.Context; @@ -39,39 +40,39 @@ public class SanityEspressoTest { @Test public void defaultNamespace_bytes() throws Exception { - SimpleStore store = SimpleStoreFactory.create(directoryProvider, TEST_NAMESPACE); - store.put(KEY_ONE, SOME_BYTES).get(); - store.close(); - - SimpleStore storeTwo = SimpleStoreFactory.create(directoryProvider, TEST_NAMESPACE); - byte[] fromDisk = storeTwo.get(KEY_ONE).get(); - assertEquals(SOME_BYTES, fromDisk); - storeTwo.close(); + try (SimpleStore store = SimpleStoreFactory.create(directoryProvider, TEST_NAMESPACE)) { + store.put(KEY_ONE, SOME_BYTES).get(); + } + byte[] fromDisk; + try (SimpleStore store = SimpleStoreFactory.create(directoryProvider, TEST_NAMESPACE)) { + fromDisk = store.get(KEY_ONE).get(); + } + assertArrayEquals(SOME_BYTES, fromDisk); } @Test public void defaultNamespace_string() throws Exception { - SimpleStore store = SimpleStoreFactory.create(directoryProvider, TEST_NAMESPACE); - store.putString(KEY_ONE, SAMPLE_STRING).get(); - store.close(); - - SimpleStore storeTwo = SimpleStoreFactory.create(directoryProvider, TEST_NAMESPACE); - String fromDisk = storeTwo.getString(KEY_ONE).get(); + try (SimpleStore store = SimpleStoreFactory.create(directoryProvider, TEST_NAMESPACE)) { + store.putString(KEY_ONE, SAMPLE_STRING).get(); + } + String fromDisk; + try (SimpleStore store = SimpleStoreFactory.create(directoryProvider, TEST_NAMESPACE)) { + fromDisk = store.getString(KEY_ONE).get(); + } assertEquals(SAMPLE_STRING, fromDisk); - storeTwo.close(); } @Test public void cache() throws Exception { - SimpleStore store = - SimpleStoreFactory.create(directoryProvider, TEST_NAMESPACE, NamespaceConfig.CACHE); - store.putString(KEY_ONE, SAMPLE_STRING).get(); - store.close(); - - SimpleStore storeTwo = - SimpleStoreFactory.create(directoryProvider, TEST_NAMESPACE, NamespaceConfig.CACHE); - String fromDisk = storeTwo.getString(KEY_ONE).get(); + try (SimpleStore store = + SimpleStoreFactory.create(directoryProvider, TEST_NAMESPACE, NamespaceConfig.CACHE)) { + store.putString(KEY_ONE, SAMPLE_STRING).get(); + } + String fromDisk; + try (SimpleStore store = + SimpleStoreFactory.create(directoryProvider, TEST_NAMESPACE, NamespaceConfig.CACHE)) { + fromDisk = store.getString(KEY_ONE).get(); + } assertEquals(SAMPLE_STRING, fromDisk); - storeTwo.close(); } } diff --git a/simplestore/src/main/AndroidManifest.xml b/simplestore/src/main/AndroidManifest.xml index c52db86..5c3d365 100644 --- a/simplestore/src/main/AndroidManifest.xml +++ b/simplestore/src/main/AndroidManifest.xml @@ -1,2 +1,2 @@ - + + diff --git a/simplestore/src/main/java/com/uber/simplestore/impl/AndroidDirectoryProvider.java b/simplestore/src/main/java/com/uber/simplestore/impl/AndroidDirectoryProvider.java index 3d4e4be..df852c0 100644 --- a/simplestore/src/main/java/com/uber/simplestore/impl/AndroidDirectoryProvider.java +++ b/simplestore/src/main/java/com/uber/simplestore/impl/AndroidDirectoryProvider.java @@ -21,7 +21,7 @@ public class AndroidDirectoryProvider implements DirectoryProvider { - private Context context; + private final Context context; public AndroidDirectoryProvider(Context context) { this.context = context; diff --git a/simplestore/src/main/java/com/uber/simplestore/impl/AtomicFile.java b/simplestore/src/main/java/com/uber/simplestore/impl/AtomicFile.java index 2273d7a..c874582 100644 --- a/simplestore/src/main/java/com/uber/simplestore/impl/AtomicFile.java +++ b/simplestore/src/main/java/com/uber/simplestore/impl/AtomicFile.java @@ -177,18 +177,13 @@ public FileInputStream openRead() throws FileNotFoundException { * array which is returned. */ public byte[] readFully() throws IOException { - FileInputStream stream = openRead(); - try { + try (FileInputStream stream = openRead()) { int pos = 0; int avail = stream.available(); byte[] data = new byte[avail]; while (true) { int amt = stream.read(data, pos, data.length - pos); - // Log.i("foo", "Read " + amt + " bytes at " + pos - // + " of avail " + data.length); if (amt <= 0) { - // Log.i("foo", "**** FINISHED READING: pos=" + pos - // + " len=" + data.length); return data; } pos += amt; @@ -199,8 +194,6 @@ public byte[] readFully() throws IOException { data = newData; } } - } finally { - stream.close(); } } diff --git a/simplestore/src/main/java/com/uber/simplestore/impl/SimpleStoreFactory.java b/simplestore/src/main/java/com/uber/simplestore/impl/SimpleStoreFactory.java index 2481f44..6f7c3d5 100644 --- a/simplestore/src/main/java/com/uber/simplestore/impl/SimpleStoreFactory.java +++ b/simplestore/src/main/java/com/uber/simplestore/impl/SimpleStoreFactory.java @@ -40,7 +40,7 @@ public final class SimpleStoreFactory { private static final Object namespacesLock = new Object(); @GuardedBy("namespacesLock") - private static Map namespaces = new HashMap<>(); + private static final Map namespaces = new HashMap<>(); /** * Obtain a store for a namespace with default configuration. @@ -82,6 +82,7 @@ public static SimpleStore create( static void tombstone(SimpleStoreImpl store) { synchronized (namespacesLock) { if (store.tombstone()) { + //noinspection resource namespaces.remove(store.getNamespace()); } } diff --git a/simplestore/src/main/java/com/uber/simplestore/impl/SimpleStoreImpl.java b/simplestore/src/main/java/com/uber/simplestore/impl/SimpleStoreImpl.java index 42775ce..64cf2b4 100644 --- a/simplestore/src/main/java/com/uber/simplestore/impl/SimpleStoreImpl.java +++ b/simplestore/src/main/java/com/uber/simplestore/impl/SimpleStoreImpl.java @@ -39,7 +39,6 @@ import javax.annotation.Nullable; /** Asynchronous storage implementation. */ -@SuppressWarnings("UnstableApiUsage") final class SimpleStoreImpl implements SimpleStore { private static final int OPEN = 0; private static final int CLOSED = 1; @@ -50,7 +49,7 @@ final class SimpleStoreImpl implements SimpleStore { private final String namespace; @Nullable private File namespacedDirectory; - AtomicInteger available = new AtomicInteger(OPEN); + final AtomicInteger available = new AtomicInteger(OPEN); // Only touch from the serial executor. private final Map cache = new HashMap<>(); @@ -179,7 +178,7 @@ public ListenableFuture clear() { } try { File[] files = Objects.requireNonNull(namespacedDirectory).listFiles(File::isFile); - if (files != null && files.length > 0) { + if (files != null) { for (File f : files) { //noinspection ResultOfMethodCallIgnored f.delete(); diff --git a/simplestore/src/main/java/com/uber/simplestore/primitive/PrimitiveSimpleStoreImpl.java b/simplestore/src/main/java/com/uber/simplestore/primitive/PrimitiveSimpleStoreImpl.java index 3895e2f..6daf96c 100644 --- a/simplestore/src/main/java/com/uber/simplestore/primitive/PrimitiveSimpleStoreImpl.java +++ b/simplestore/src/main/java/com/uber/simplestore/primitive/PrimitiveSimpleStoreImpl.java @@ -22,7 +22,6 @@ import com.uber.simplestore.SimpleStore; import javax.annotation.Nullable; -@SuppressWarnings("UnstableApiUsage") final class PrimitiveSimpleStoreImpl implements PrimitiveSimpleStore { private final SimpleStore simpleStore; diff --git a/simplestore/src/test/java/com/uber/simplestore/impl/AtomicFileTest.java b/simplestore/src/test/java/com/uber/simplestore/impl/AtomicFileTest.java index 45dbc8c..540a8fc 100644 --- a/simplestore/src/test/java/com/uber/simplestore/impl/AtomicFileTest.java +++ b/simplestore/src/test/java/com/uber/simplestore/impl/AtomicFileTest.java @@ -24,6 +24,7 @@ import androidx.test.platform.app.InstrumentationRegistry; import java.io.*; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.List; import org.junit.After; @@ -51,7 +52,7 @@ private enum WriteAction { READ_FINISH } - private static final Charset UTF_8 = Charset.forName("UTF-8"); + private static final Charset UTF_8 = StandardCharsets.UTF_8; private static final byte[] BASE_BYTES = "base".getBytes(UTF_8); private static final byte[] EXISTING_NEW_BYTES = "unnew".getBytes(UTF_8); private static final byte[] NEW_BYTES = "new".getBytes(UTF_8); @@ -335,14 +336,7 @@ public void testAtomicFile() throws Exception { break; case READ_FINISH: // We are only using this action when there is no base file. - assertThrows( - FileNotFoundException.class, - new ThrowingRunnable() { - @Override - public void run() throws Throwable { - atomicFile.openRead(); - } - }); + assertThrows(FileNotFoundException.class, atomicFile::openRead); atomicFile.finishWrite(outputStream); break; default: @@ -356,14 +350,7 @@ public void run() throws Throwable { assertArrayEquals(mExpectedBytes, readAllBytes(inputStream)); } } else { - assertThrows( - FileNotFoundException.class, - new ThrowingRunnable() { - @Override - public void run() throws Throwable { - atomicFile.openRead(); - } - }); + assertThrows(FileNotFoundException.class, atomicFile::openRead); } } @@ -409,21 +396,4 @@ private static void sneakyThrow(@NonNull Throwable private interface ThrowingRunnable { void run() throws Throwable; } - - // JUnit on API 17 somehow turns null parameters into the string "null". Wrapping the parameters - // inside a class solves this problem. - private static class Parameters { - @Nullable public String[] existingFileNames; - @Nullable public WriteAction writeAction; - @Nullable public byte[] expectedBytes; - - Parameters( - @Nullable String[] existingFileNames, - @Nullable WriteAction writeAction, - @Nullable byte[] expectedBytes) { - this.existingFileNames = existingFileNames; - this.writeAction = writeAction; - this.expectedBytes = expectedBytes; - } - } } diff --git a/simplestore/src/test/java/com/uber/simplestore/impl/SimpleStoreFactoryTest.java b/simplestore/src/test/java/com/uber/simplestore/impl/SimpleStoreFactoryTest.java index 82c4120..53c6911 100644 --- a/simplestore/src/test/java/com/uber/simplestore/impl/SimpleStoreFactoryTest.java +++ b/simplestore/src/test/java/com/uber/simplestore/impl/SimpleStoreFactoryTest.java @@ -28,7 +28,7 @@ @RunWith(RobolectricTestRunner.class) public final class SimpleStoreFactoryTest { - private final Context context = RuntimeEnvironment.systemContext; + private final Context context = RuntimeEnvironment.getApplication(); private final DirectoryProvider directoryProvider = new AndroidDirectoryProvider(context); @Test diff --git a/simplestore/src/test/java/com/uber/simplestore/impl/SimpleStoreImplTest.java b/simplestore/src/test/java/com/uber/simplestore/impl/SimpleStoreImplTest.java index 54947d8..2063608 100644 --- a/simplestore/src/test/java/com/uber/simplestore/impl/SimpleStoreImplTest.java +++ b/simplestore/src/test/java/com/uber/simplestore/impl/SimpleStoreImplTest.java @@ -28,7 +28,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import javax.annotation.Nonnull; -import org.checkerframework.checker.nullness.compatqual.NullableDecl; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; @@ -180,7 +179,7 @@ public void operationsBeforeCloseSucceed() throws Exception { store.put(TEST_KEY, VALUE_TWO), new FutureCallback() { @Override - public void onSuccess(@NullableDecl byte[] result) { + public void onSuccess(byte[] result) { assertThat(result).isEqualTo(VALUE_TWO); } @@ -194,7 +193,7 @@ public void onFailure(@Nonnull Throwable t) { store.get(TEST_KEY), new FutureCallback() { @Override - public void onSuccess(@NullableDecl byte[] result) { + public void onSuccess(byte[] result) { assertThat(result).isEqualTo(VALUE_TWO); } @@ -255,8 +254,8 @@ public void oneInstancePerNamespace() { try (SimpleStore ignoredOuter = SimpleStoreFactory.create(directoryProvider, "")) { try (SimpleStore ignored = SimpleStoreFactory.create(directoryProvider, someNamespace, NamespaceConfig.DEFAULT)) { - try { - SimpleStoreFactory.create(directoryProvider, someNamespace, NamespaceConfig.DEFAULT); + try (SimpleStore ignored2 = + SimpleStoreFactory.create(directoryProvider, someNamespace, NamespaceConfig.DEFAULT)) { fail(); } catch (IllegalStateException e) { // expected. diff --git a/testing/build.gradle b/testing/build.gradle index 3b82241..8f7d961 100644 --- a/testing/build.gradle +++ b/testing/build.gradle @@ -1,36 +1,22 @@ plugins { - id 'com.android.library' - id 'kotlin-android' - id 'com.diffplug.gradle.spotless' - id 'org.jetbrains.dokka' - id 'com.vanniktech.maven.publish' + alias(libs.plugins.kotlin.android) + alias(libs.plugins.spotless) + alias(libs.plugins.dokka) + alias(libs.plugins.gradle.maven.publish) + id("spotless-convention") + id("dokka-convention") + id("errorprone-convention") + id("android-convention") } android { - buildToolsVersion deps.build.buildToolsVersion - compileSdkVersion deps.build.compileSdkVersion - - defaultConfig { - minSdkVersion deps.build.minSdkVersion - targetSdkVersion deps.build.targetSdkVersion - } - - defaultConfig { - minSdkVersion deps.build.minSdkVersion - targetSdkVersion deps.build.targetSdkVersion - } - - compileOptions { - sourceCompatibility deps.build.javaVersion - targetCompatibility deps.build.javaVersion - } + namespace 'com.uber.simplestore.fakes' } dependencies { implementation project(":simplestore") - implementation deps.external.guavaAndroid - implementation deps.external.findBugs + implementation libs.guava - testImplementation deps.test.junit - testImplementation deps.test.truth + testImplementation testLibs.junit + testImplementation testLibs.truth } diff --git a/testing/src/main/AndroidManifest.xml b/testing/src/main/AndroidManifest.xml index 256cc45..5c3d365 100644 --- a/testing/src/main/AndroidManifest.xml +++ b/testing/src/main/AndroidManifest.xml @@ -1,2 +1,2 @@ - + + diff --git a/testing/src/main/java/com/uber/simplestore/fakes/FakeSimpleStore.java b/testing/src/main/java/com/uber/simplestore/fakes/FakeSimpleStore.java index 1a140b7..c0c7048 100644 --- a/testing/src/main/java/com/uber/simplestore/fakes/FakeSimpleStore.java +++ b/testing/src/main/java/com/uber/simplestore/fakes/FakeSimpleStore.java @@ -24,7 +24,6 @@ import java.util.HashMap; import javax.annotation.Nullable; -@SuppressWarnings("UnstableApiUsage") public final class FakeSimpleStore implements SimpleStore { private boolean closed = false; diff --git a/testing/src/main/res/values/strings.xml b/testing/src/main/res/values/strings.xml index 97e0796..2c5844d 100644 --- a/testing/src/main/res/values/strings.xml +++ b/testing/src/main/res/values/strings.xml @@ -1,3 +1 @@ - - Fakes - + diff --git a/testing/src/test/java/com/uber/simplestore/fakes/FakeUnitTest.java b/testing/src/test/java/com/uber/simplestore/fakes/FakeUnitTest.java index 65f1dba..1f852aa 100644 --- a/testing/src/test/java/com/uber/simplestore/fakes/FakeUnitTest.java +++ b/testing/src/test/java/com/uber/simplestore/fakes/FakeUnitTest.java @@ -30,17 +30,19 @@ public class FakeUnitTest { @Test public void saves() throws Exception { - SimpleStore store = new FakeSimpleStore(); - store.putString(TEST_KEY, "bar").get(); - assertThat(store.getString(TEST_KEY).get()).isEqualTo("bar"); + try (SimpleStore store = new FakeSimpleStore()) { + store.putString(TEST_KEY, "bar").get(); + assertThat(store.getString(TEST_KEY).get()).isEqualTo("bar"); + } } @Test public void nullClears() throws Exception { - SimpleStore store = new FakeSimpleStore(); - store.putString(TEST_KEY, "bar").get(); - store.put(TEST_KEY, null).get(); - assertThat(store.contains(TEST_KEY).get()).isFalse(); + try (SimpleStore store = new FakeSimpleStore()) { + store.putString(TEST_KEY, "bar").get(); + store.put(TEST_KEY, null).get(); + assertThat(store.contains(TEST_KEY).get()).isFalse(); + } } @Test @@ -55,14 +57,15 @@ public void clear_noChildren() throws Exception { @Test public void handlesAbsence() throws Exception { - SimpleStore store = new FakeSimpleStore(); - assertThat(store.getString(TEST_KEY).get()).isEqualTo(""); - assertThat(store.get(TEST_KEY).get()).hasLength(0); - assertThat(store.contains(TEST_KEY).get()).isFalse(); + try (SimpleStore store = new FakeSimpleStore()) { + assertThat(store.getString(TEST_KEY).get()).isEqualTo(""); + assertThat(store.get(TEST_KEY).get()).hasLength(0); + assertThat(store.contains(TEST_KEY).get()).isFalse(); + } } @Test - public void throwsAfterClose() throws Exception { + public void throwsAfterClose() { SimpleStore store = new FakeSimpleStore(); store.close(); try { @@ -74,16 +77,17 @@ public void throwsAfterClose() throws Exception { } @Test - public void supportsFailure() throws Exception { - FakeSimpleStore store = new FakeSimpleStore(); - store.setFailureType(new IOException("foo")); + public void supportsFailure() { + try (FakeSimpleStore store = new FakeSimpleStore()) { + store.setFailureType(new IOException("foo")); - ListenableFuture future = store.getString(TEST_KEY); - try { - future.get(); - fail(); - } catch (Exception e) { - assertThat(e).hasCauseThat().isInstanceOf(IOException.class); + ListenableFuture future = store.getString(TEST_KEY); + try { + future.get(); + fail(); + } catch (Exception e) { + assertThat(e).hasCauseThat().isInstanceOf(IOException.class); + } } } }