Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ internal class DefaultEditManager(
}

override fun findMaxAppVersionCode(): Long {
return tracks.findHighestTrack()?.releases.orEmpty()
.flatMap { it.versionCodes.orEmpty() }
.maxOrNull() ?: 1
return publisher.findMaxAppVersionCode(editId).toLong()
}

override fun findLeastStableTrackName(): String? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ internal class DefaultPlayPublisher(
}
}

override fun findMaxAppVersionCode(editId: String): Int {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this pulled out into a new fn? This module isn't supposed to have logic so this code should go back in DefaultEditManager.kt

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, thanks for the feedback. I wasn't aware of this. The reason was simplicity: The new function's logic needs Bundles and APKs from the Android Publisher. Both of these aren't available in DefaultEditManager, yet, and I was reluctant to introduce two new dependencies there. But I totally get your point and would change it.
But - the fix didn't work anyway. It looks like Track.releases, Bundles.list and Apks.list all only contain active versions. So for now I don't see a way of fixing the issue when using the ResolutionStrategy.AUTO. Also since I manually set my versionCode yesterday to be able to release my app update, I can't reproduce the issue on my machine anymore.

val maxBundle = publisher.edits().bundles().list(appId, editId).execute()
?.bundles.orEmpty()
.maxOfOrNull { it.versionCode ?: 0 } ?: 0

val maxApk = publisher.edits().apks().list(appId, editId).execute()
?.apks.orEmpty()
.maxOfOrNull { it.versionCode ?: 0 } ?: 0

return maxOf(maxBundle, maxApk).takeIf { it > 0 } ?: 1
}

override fun listTracks(editId: String): List<Track> {
return publisher.edits().tracks().list(appId, editId).execute()?.tracks.orEmpty()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ internal interface InternalPlayPublisher : PlayPublisher {

fun updateTrack(editId: String, track: Track)

fun findMaxAppVersionCode(editId: String): Int

@Throws(IOException::class)
fun uploadBundle(editId: String, bundleFile: File): Bundle

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import com.google.api.services.androidpublisher.model.Image
import com.google.api.services.androidpublisher.model.Listing
import com.google.api.services.androidpublisher.model.LocalizedText
import com.google.api.services.androidpublisher.model.Track
import com.google.api.services.androidpublisher.model.TrackRelease
import com.google.common.truth.Truth.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
Expand All @@ -29,7 +28,8 @@ import java.io.File
class DefaultEditManagerTest {
private var mockPublisher = mock(InternalPlayPublisher::class.java)
private var mockTracks = mock(TrackManager::class.java)
private var edits: EditManager = DefaultEditManager(mockPublisher, mockTracks, "edit-id")
private val editId = "edit-id"
private var edits: EditManager = DefaultEditManager(mockPublisher, mockTracks, editId)

private var mockFile = mock(File::class.java)

Expand Down Expand Up @@ -149,7 +149,7 @@ class DefaultEditManagerTest {
)

verify(mockPublisher)
.uploadDeobfuscationFile(eq("edit-id"), eq(mockFile), eq(888), eq("proguard"))
.uploadDeobfuscationFile(eq(editId), eq(mockFile), eq(888), eq("proguard"))
}

@Test
Expand All @@ -169,7 +169,7 @@ class DefaultEditManagerTest {
)

verify(mockPublisher)
.uploadDeobfuscationFile(eq("edit-id"), eq(mockFile), eq(888), eq("nativeCode"))
.uploadDeobfuscationFile(eq(editId), eq(mockFile), eq(888), eq("nativeCode"))
}

@Test
Expand Down Expand Up @@ -223,8 +223,8 @@ class DefaultEditManagerTest {
patchObbRetainable = 321
)

verify(mockPublisher).attachObb(eq("edit-id"), eq("main"), eq(888), eq(123))
verify(mockPublisher).attachObb(eq("edit-id"), eq("patch"), eq(888), eq(321))
verify(mockPublisher).attachObb(eq(editId), eq("main"), eq(888), eq(123))
verify(mockPublisher).attachObb(eq(editId), eq("patch"), eq(888), eq(321))
}

@Test
Expand Down Expand Up @@ -324,70 +324,14 @@ class DefaultEditManagerTest {
}

@Test
fun `findMaxAppVersionCode returns 1 on empty tracks`() {
`when`(mockTracks.findHighestTrack()).thenReturn(null)

val max = edits.findMaxAppVersionCode()

assertThat(max).isEqualTo(1)
}

@Test
fun `findMaxAppVersionCode returns 1 on null releases`() {
`when`(mockTracks.findHighestTrack()).thenReturn(Track())

val max = edits.findMaxAppVersionCode()

assertThat(max).isEqualTo(1)
}

@Test
fun `findMaxAppVersionCode succeeds with single track, single release, singe version code`() {
`when`(mockTracks.findHighestTrack()).thenReturn(Track().apply {
releases = listOf(
TrackRelease().apply {
versionCodes = listOf(5)
}
)
})
fun `findMaxAppVersionCode delegates to publisher`() {
`when`(mockPublisher.findMaxAppVersionCode(editId)).thenReturn(91)

val max = edits.findMaxAppVersionCode()

assertThat(max).isEqualTo(5)
assertThat(max).isEqualTo(91)
}

@Test
fun `findMaxAppVersionCode succeeds with single track, single release, multi version code`() {
`when`(mockTracks.findHighestTrack()).thenReturn(Track().apply {
releases = listOf(
TrackRelease().apply {
versionCodes = listOf(5, 4, 8, 7)
}
)
})

val max = edits.findMaxAppVersionCode()

assertThat(max).isEqualTo(8)
}

@Test
fun `findMaxAppVersionCode succeeds with single track, multi release, multi version code`() {
`when`(mockTracks.findHighestTrack()).thenReturn(Track().apply {
releases = listOf(
TrackRelease().apply {
versionCodes = listOf(5, 4, 8, 7)
},
TrackRelease().apply {
versionCodes = listOf(85, 7, 36, 5)
}
)
})

val max = edits.findMaxAppVersionCode()

assertThat(max).isEqualTo(85)
}

@Test
fun `findLeastStableTrackName returns null on null track`() {
Expand Down Expand Up @@ -453,7 +397,7 @@ class DefaultEditManagerTest {
fun `publishAppDetails forwards data to publisher`() {
edits.publishAppDetails("lang", "email", "phone", "website")

verify(mockPublisher).updateDetails(eq("edit-id"), eq(AppDetails().apply {
verify(mockPublisher).updateDetails(eq(editId), eq(AppDetails().apply {
defaultLanguage = "lang"
contactEmail = "email"
contactPhone = "phone"
Expand All @@ -465,7 +409,7 @@ class DefaultEditManagerTest {
fun `publishListing forwards data to publisher`() {
edits.publishListing("lang", "title", "short", "full", "url")

verify(mockPublisher).updateListing(eq("edit-id"), eq("lang"), eq(Listing().apply {
verify(mockPublisher).updateListing(eq(editId), eq("lang"), eq(Listing().apply {
title = "title"
shortDescription = "short"
fullDescription = "full"
Expand All @@ -477,8 +421,8 @@ class DefaultEditManagerTest {
fun `publishImages forwards data to publisher`() {
edits.publishImages("lang", "phoneScreenshots", listOf(mockFile))

verify(mockPublisher).deleteImages(eq("edit-id"), eq("lang"), eq("phoneScreenshots"))
verify(mockPublisher).deleteImages(eq(editId), eq("lang"), eq("phoneScreenshots"))
verify(mockPublisher).uploadImage(
eq("edit-id"), eq("lang"), eq("phoneScreenshots"), eq(mockFile))
eq(editId), eq("lang"), eq("phoneScreenshots"), eq(mockFile))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package com.github.triplet.gradle.androidpublisher.internal

import com.google.api.services.androidpublisher.AndroidPublisher
import com.google.api.services.androidpublisher.model.Apk
import com.google.api.services.androidpublisher.model.ApksListResponse
import com.google.api.services.androidpublisher.model.Bundle
import com.google.api.services.androidpublisher.model.BundlesListResponse
import com.google.common.truth.Truth.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.mockito.Mockito.mock
import org.mockito.Mockito.`when`

class DefaultPlayPublisherTest {
private val mockAndroidPublisher = mock(AndroidPublisher::class.java)
private val appId = "appId"
private val editId = "editId"

private val mockEdits = mock(AndroidPublisher.Edits::class.java)

private val mockBundles = mock(AndroidPublisher.Edits.Bundles::class.java)
private val mockBundlesList = mock(AndroidPublisher.Edits.Bundles.List::class.java)
private val mockBundlesResponse = mock(BundlesListResponse::class.java)

private val mockApks = mock(AndroidPublisher.Edits.Apks::class.java)
private val mockApksList = mock(AndroidPublisher.Edits.Apks.List::class.java)
private val mockApksResponse = mock(ApksListResponse::class.java)

private val publisher = DefaultPlayPublisher(mockAndroidPublisher, appId)

@BeforeEach
fun setUp() {
`when`(mockAndroidPublisher.edits()).thenReturn(mockEdits)

`when`(mockEdits.bundles()).thenReturn(mockBundles)
`when`(mockBundles.list(appId, editId)).thenReturn(mockBundlesList)
`when`(mockBundlesList.execute()).thenReturn(mockBundlesResponse)

`when`(mockEdits.apks()).thenReturn(mockApks)
`when`(mockApks.list(appId, editId)).thenReturn(mockApksList)
`when`(mockApksList.execute()).thenReturn(mockApksResponse)
}

@Test
fun `findMaxAppVersionCode returns 1 on null bundles and null apks`() {
`when`(mockBundlesResponse.bundles).thenReturn(null)
`when`(mockApksResponse.apks).thenReturn(null)

val max = publisher.findMaxAppVersionCode(editId)

assertThat(max).isEqualTo(1)
}

@Test
fun `findMaxAppVersionCode returns 1 on empty bundles and empty apks`() {
`when`(mockBundlesResponse.bundles).thenReturn(emptyList())
`when`(mockApksResponse.apks).thenReturn(emptyList())

val max = publisher.findMaxAppVersionCode(editId)

assertThat(max).isEqualTo(1)
}

private fun bundle(versionCode: Int): Bundle {
val bundle = Bundle()
bundle.versionCode = versionCode
return bundle
}

private fun apk(versionCode: Int): Apk {
val apk = Apk()
apk.versionCode = versionCode
return apk
}

@Test
fun `findMaxAppVersionCode succeeds with single bundle, no apks`() {
`when`(mockBundlesResponse.bundles).thenReturn(listOf(bundle(5)))
`when`(mockApksResponse.apks).thenReturn(emptyList())

val max = publisher.findMaxAppVersionCode(editId)

assertThat(max).isEqualTo(5)
}

@Test
fun `findMaxAppVersionCode succeeds with no bundles, single apk`() {
`when`(mockBundlesResponse.bundles).thenReturn(emptyList())
`when`(mockApksResponse.apks).thenReturn(listOf(apk(6)))

val max = publisher.findMaxAppVersionCode(editId)

assertThat(max).isEqualTo(6)
}

@Test
fun `findMaxAppVersionCode succeeds with multiple bundles and apks, max in bundles`() {
`when`(mockBundlesResponse.bundles).thenReturn(
listOf(
bundle(5),
bundle(12),
bundle(8),
)
)
`when`(mockApksResponse.apks).thenReturn(
listOf(
apk(3),
apk(7),
apk(2),
)
)

val max = publisher.findMaxAppVersionCode(editId)

assertThat(max).isEqualTo(12)
}

@Test
fun `findMaxAppVersionCode succeeds with multiple bundles and apks, max in apks`() {
`when`(mockBundlesResponse.bundles).thenReturn(
listOf(
bundle(5),
bundle(2),
bundle(8),
)
)
`when`(mockApksResponse.apks).thenReturn(
listOf(
apk(3),
apk(15),
apk(12),
)
)

val max = publisher.findMaxAppVersionCode(editId)

assertThat(max).isEqualTo(15)
}
}
Loading