diff options
author | Alon Albert <aalbert@google.com> | 2022-07-26 13:30:20 -0700 |
---|---|---|
committer | TreeHugger Robot <treehugger-gerrit@google.com> | 2022-07-29 21:07:52 +0000 |
commit | cd9d1ab90d1563932f78898604b5ef61ece4dbb1 (patch) | |
tree | 7cf85c2c7c247f12951d9c48b669b754c2b3c1e0 /logcat | |
parent | 75fc66fd9275de3b87bdd3257bc7ef99352dd019 (diff) | |
download | idea-cd9d1ab90d1563932f78898604b5ef61ece4dbb1.tar.gz |
Use AndroidModel.getAllApplicationIds() To Get App Ids
See b/236114272
Fixes: 233630777
Test: Added
Change-Id: I8567cc5857e44076b36f852adc491bd4c150ced3
Diffstat (limited to 'logcat')
-rw-r--r-- | logcat/BUILD | 2 | ||||
-rw-r--r-- | logcat/intellij.android.logcat.iml | 1 | ||||
-rw-r--r-- | logcat/intellij.android.logcat.tests.iml | 1 | ||||
-rw-r--r-- | logcat/src/META-INF/logcat.xml | 3 | ||||
-rw-r--r-- | logcat/src/com/android/tools/idea/logcat/LogcatHeaderPanel.kt | 3 | ||||
-rw-r--r-- | logcat/src/com/android/tools/idea/logcat/LogcatMainPanel.kt | 25 | ||||
-rw-r--r-- | logcat/src/com/android/tools/idea/logcat/ProjectApplicationIdsProvider.kt (renamed from logcat/src/com/android/tools/idea/logcat/ProjectPackageNamesProvider.kt) | 25 | ||||
-rw-r--r-- | logcat/src/com/android/tools/idea/logcat/ProjectApplicationIdsProviderImpl.kt | 50 | ||||
-rw-r--r-- | logcat/testSrc/com/android/tools/idea/logcat/FakeProjectApplicationIdsProvider.kt | 39 | ||||
-rw-r--r-- | logcat/testSrc/com/android/tools/idea/logcat/LogcatMainPanelTest.kt | 56 | ||||
-rw-r--r-- | logcat/testSrc/com/android/tools/idea/logcat/ProjectApplicationIdsProviderImplTest.kt | 126 |
11 files changed, 300 insertions, 31 deletions
diff --git a/logcat/BUILD b/logcat/BUILD index 54a310c87ea..2d9dad64644 100644 --- a/logcat/BUILD +++ b/logcat/BUILD @@ -27,6 +27,7 @@ iml_module( "//tools/adt/idea/.idea/libraries:studio-analytics-proto", "//tools/adt/idea/.idea/libraries:kotlinx-coroutines-guava", "//tools/adt/idea/android-adb-ui:intellij.android.adb.ui[module]", + "//tools/adt/idea/project-system:intellij.android.projectSystem[module]", ], ) @@ -61,5 +62,6 @@ iml_module( "//tools/adt/idea/android-adb:intellij.android.adb[module, test]", "//tools/base/fakeadbserver:studio.android.sdktools.fakeadbserver[module, test]", "//tools/base/adblib-ddmlibcompatibility:studio.android.sdktools.adblib.ddmlibcompatibility[module, test]", + "//tools/adt/idea/project-system:intellij.android.projectSystem[module, test]", ], ) diff --git a/logcat/intellij.android.logcat.iml b/logcat/intellij.android.logcat.iml index b92af772d43..cb6c94adbc0 100644 --- a/logcat/intellij.android.logcat.iml +++ b/logcat/intellij.android.logcat.iml @@ -23,5 +23,6 @@ <orderEntry type="library" name="studio-analytics-proto" level="project" /> <orderEntry type="library" name="kotlinx-coroutines-guava" level="project" /> <orderEntry type="module" module-name="intellij.android.adb.ui" /> + <orderEntry type="module" module-name="intellij.android.projectSystem" /> </component> </module>
\ No newline at end of file diff --git a/logcat/intellij.android.logcat.tests.iml b/logcat/intellij.android.logcat.tests.iml index da7ed0ea38f..b3c5cbfbb3b 100644 --- a/logcat/intellij.android.logcat.tests.iml +++ b/logcat/intellij.android.logcat.tests.iml @@ -28,6 +28,7 @@ <orderEntry type="module" module-name="intellij.android.adb" scope="TEST" /> <orderEntry type="module" module-name="android.sdktools.fakeadbserver" scope="TEST" /> <orderEntry type="module" module-name="android.sdktools.adblib.ddmlibcompatibility" scope="TEST" /> + <orderEntry type="module" module-name="intellij.android.projectSystem" scope="TEST" /> </component> <component name="TestModuleProperties" production-module="intellij.android.logcat" /> </module>
\ No newline at end of file diff --git a/logcat/src/META-INF/logcat.xml b/logcat/src/META-INF/logcat.xml index 37f40b55f57..149bbfaff90 100644 --- a/logcat/src/META-INF/logcat.xml +++ b/logcat/src/META-INF/logcat.xml @@ -57,6 +57,9 @@ <applicationService serviceImplementation="com.android.tools.idea.logcat.filters.AndroidLogcatNamedFilters"/> <applicationService serviceImplementation="com.android.tools.idea.logcat.filters.AndroidLogcatFilterHistory"/> <applicationService serviceImplementation="com.android.tools.idea.ui.screenrecording.ScreenRecorderPersistentOptions"/> + <projectService + serviceInterface="com.android.tools.idea.logcat.ProjectApplicationIdsProvider" + serviceImplementation="com.android.tools.idea.logcat.ProjectApplicationIdsProviderImpl"/> <additionalTextAttributes scheme="Default" file="colorSchemes/LogcatColorSchemeDefault.xml"/> <additionalTextAttributes scheme="Darcula" file="colorSchemes/LogcatColorSchemeDarcula.xml"/> diff --git a/logcat/src/com/android/tools/idea/logcat/LogcatHeaderPanel.kt b/logcat/src/com/android/tools/idea/logcat/LogcatHeaderPanel.kt index 5fcd717d443..54a8962b216 100644 --- a/logcat/src/com/android/tools/idea/logcat/LogcatHeaderPanel.kt +++ b/logcat/src/com/android/tools/idea/logcat/LogcatHeaderPanel.kt @@ -46,7 +46,7 @@ import javax.swing.JPanel internal class LogcatHeaderPanel( project: Project, val logcatPresenter: LogcatPresenter, - packageNamesProvider: PackageNamesProvider, + private val filterParser: LogcatFilterParser, filter: String, initialDevice: Device?, adbSession: AdbSession, @@ -55,7 +55,6 @@ internal class LogcatHeaderPanel( logcatPresenter, initialDevice, DeviceComboBoxDeviceTracker(project, initialDevice, adbSession)) - private val filterParser = LogcatFilterParser(project, packageNamesProvider) private val filterComponent: FilterTextComponent = FilterTextComponent.createComponent(project, logcatPresenter, filterParser, filter) diff --git a/logcat/src/com/android/tools/idea/logcat/LogcatMainPanel.kt b/logcat/src/com/android/tools/idea/logcat/LogcatMainPanel.kt index 5d41dfbb87f..35deaae85bc 100644 --- a/logcat/src/com/android/tools/idea/logcat/LogcatMainPanel.kt +++ b/logcat/src/com/android/tools/idea/logcat/LogcatMainPanel.kt @@ -32,6 +32,8 @@ import com.android.tools.idea.logcat.LogcatPanelConfig.FormattingConfig import com.android.tools.idea.logcat.LogcatPanelConfig.FormattingConfig.Custom import com.android.tools.idea.logcat.LogcatPanelConfig.FormattingConfig.Preset import com.android.tools.idea.logcat.LogcatPresenter.Companion.LOGCAT_PRESENTER_ACTION +import com.android.tools.idea.logcat.ProjectApplicationIdsProvider.Companion.PROJECT_APPLICATION_IDS_CHANGED_TOPIC +import com.android.tools.idea.logcat.ProjectApplicationIdsProvider.ProjectApplicationIdsListener import com.android.tools.idea.logcat.actions.ClearLogcatAction import com.android.tools.idea.logcat.actions.CreateScratchFileAction import com.android.tools.idea.logcat.actions.LogcatFoldLinesLikeThisAction @@ -175,7 +177,6 @@ internal class LogcatMainPanel( androidProjectDetector: AndroidProjectDetector = AndroidProjectDetectorImpl(), hyperlinkDetector: HyperlinkDetector? = null, foldingDetector: FoldingDetector? = null, - packageNamesProvider: PackageNamesProvider = ProjectPackageNamesProvider(project), adbSession: AdbSession = AdbLibService.getInstance(project).session, private val logcatService: LogcatService = LogcatServiceImpl(project, { AdbLibService.getInstance(project).session.deviceServices }, ProcessNameMonitor.getInstance(project)), @@ -205,18 +206,19 @@ internal class LogcatMainPanel( private val tags = MostRecentlyAddedSet<String>(MAX_TAGS) private val packages = MostRecentlyAddedSet<String>(MAX_PACKAGE_NAMES) private val processNames = MostRecentlyAddedSet<String>(MAX_PROCESS_NAMES) + private val packageNamesProvider: ProjectApplicationIdsProvider = ProjectApplicationIdsProvider.getInstance(project) + private val logcatFilterParser = LogcatFilterParser(project, packageNamesProvider, androidProjectDetector) @VisibleForTesting val headerPanel = LogcatHeaderPanel( project, logcatPresenter = this, - packageNamesProvider, + logcatFilterParser, state?.filter ?: getDefaultFilter(project, androidProjectDetector), state?.device, adbSession, ) - private val logcatFilterParser = LogcatFilterParser(project, packageNamesProvider, androidProjectDetector) @VisibleForTesting internal val messageProcessor = MessageProcessor( @@ -283,11 +285,18 @@ internal class LogcatMainPanel( .setFilter(logcatFilterParser.getUsageTrackingEvent(headerPanel.filter)) .setFormatConfiguration(state?.formattingConfig.toUsageTracking()))) - project.messageBus.connect(this).subscribe(ClearLogcatListener.TOPIC, ClearLogcatListener { - if (connectedDevice.get()?.serialNumber == it) { - clearMessageView() - } - }) + project.messageBus.let { messageBus -> + messageBus.connect(this).subscribe(ClearLogcatListener.TOPIC, ClearLogcatListener { + if (connectedDevice.get()?.serialNumber == it) { + clearMessageView() + } + }) + messageBus.connect(this).subscribe(PROJECT_APPLICATION_IDS_CHANGED_TOPIC, ProjectApplicationIdsListener { + if (getFilter().contains(LogcatFilter.MY_PACKAGE)) { + reloadMessages() + } + }) + } coroutineScope.launch(workerThread) { headerPanel.trackSelectedDevice().collect { device -> diff --git a/logcat/src/com/android/tools/idea/logcat/ProjectPackageNamesProvider.kt b/logcat/src/com/android/tools/idea/logcat/ProjectApplicationIdsProvider.kt index 4569cbd8273..f75e3c1284d 100644 --- a/logcat/src/com/android/tools/idea/logcat/ProjectPackageNamesProvider.kt +++ b/logcat/src/com/android/tools/idea/logcat/ProjectApplicationIdsProvider.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,15 +15,20 @@ */ package com.android.tools.idea.logcat -import com.android.tools.idea.model.AndroidModuleInfo -import com.intellij.openapi.module.ModuleManager import com.intellij.openapi.project.Project +import com.intellij.util.messages.Topic -class ProjectPackageNamesProvider(project: Project) : PackageNamesProvider { - private val moduleManager = ModuleManager.getInstance(project) +/** + * Provides a set of application ids associated with the project + */ +internal interface ProjectApplicationIdsProvider : PackageNamesProvider { + fun interface ProjectApplicationIdsListener { + fun applicationIdsChanged(applicationIds: Set<String>) + } + + companion object { + fun getInstance(project: Project): ProjectApplicationIdsProvider = project.getService(ProjectApplicationIdsProvider::class.java) - // TODO(b/206675088): Maybe get package names from run configurations too? - // TODO(b/206675088): Maybe get notified when the set of package names might change? - override fun getPackageNames(): Set<String> = - moduleManager.modules.mapNotNullTo(mutableSetOf()) { AndroidModuleInfo.getInstance(it)?.`package` } -}
\ No newline at end of file + val PROJECT_APPLICATION_IDS_CHANGED_TOPIC = Topic("ProjectApplicationIdsChanged", ProjectApplicationIdsListener::class.java) + } +} diff --git a/logcat/src/com/android/tools/idea/logcat/ProjectApplicationIdsProviderImpl.kt b/logcat/src/com/android/tools/idea/logcat/ProjectApplicationIdsProviderImpl.kt new file mode 100644 index 00000000000..e3819001239 --- /dev/null +++ b/logcat/src/com/android/tools/idea/logcat/ProjectApplicationIdsProviderImpl.kt @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.tools.idea.logcat + +import com.android.tools.idea.logcat.ProjectApplicationIdsProvider.Companion.PROJECT_APPLICATION_IDS_CHANGED_TOPIC +import com.android.tools.idea.model.AndroidModel +import com.android.tools.idea.projectsystem.PROJECT_SYSTEM_SYNC_TOPIC +import com.android.tools.idea.projectsystem.ProjectSystemSyncManager +import com.android.tools.idea.projectsystem.ProjectSystemSyncManager.SyncResult +import com.android.tools.idea.projectsystem.getAndroidFacets +import com.intellij.openapi.project.Project + +/** + * Prod implementation of [ProjectApplicationIdsProvider] + */ +internal class ProjectApplicationIdsProviderImpl(private val project: Project) : ProjectApplicationIdsProvider { + private var applicationIds = loadApplicationIds() + + init { + project.messageBus.connect(project).subscribe(PROJECT_SYSTEM_SYNC_TOPIC, RefreshApplicationIds()) + } + + override fun getPackageNames(): Set<String> = applicationIds + + private fun loadApplicationIds(): Set<String> = + project.getAndroidFacets().flatMapTo(mutableSetOf()) { AndroidModel.get(it)?.allApplicationIds ?: emptyList() } + + private inner class RefreshApplicationIds : ProjectSystemSyncManager.SyncResultListener { + override fun syncEnded(result: SyncResult) { + val newIds = loadApplicationIds() + if (newIds != applicationIds) { + applicationIds = newIds + project.messageBus.syncPublisher(PROJECT_APPLICATION_IDS_CHANGED_TOPIC).applicationIdsChanged(newIds) + } + } + } +}
\ No newline at end of file diff --git a/logcat/testSrc/com/android/tools/idea/logcat/FakeProjectApplicationIdsProvider.kt b/logcat/testSrc/com/android/tools/idea/logcat/FakeProjectApplicationIdsProvider.kt new file mode 100644 index 00000000000..5f587bf2bc3 --- /dev/null +++ b/logcat/testSrc/com/android/tools/idea/logcat/FakeProjectApplicationIdsProvider.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.tools.idea.logcat + +import com.android.annotations.concurrency.UiThread +import com.android.tools.idea.logcat.ProjectApplicationIdsProvider.Companion.PROJECT_APPLICATION_IDS_CHANGED_TOPIC +import com.intellij.openapi.project.Project + +/** Test implementation of [ProjectApplicationIdsProvider] */ +internal class FakeProjectApplicationIdsProvider( + private val project: Project, + vararg initialValue: String, +) : ProjectApplicationIdsProvider { + private var applicationIds = initialValue.toSet() + + @UiThread + fun setApplicationIds(vararg value: String) { + val newIds = value.toSet() + if (applicationIds != newIds) { + project.messageBus.syncPublisher(PROJECT_APPLICATION_IDS_CHANGED_TOPIC).applicationIdsChanged(newIds) + applicationIds = newIds + } + } + + override fun getPackageNames() = applicationIds +} diff --git a/logcat/testSrc/com/android/tools/idea/logcat/LogcatMainPanelTest.kt b/logcat/testSrc/com/android/tools/idea/logcat/LogcatMainPanelTest.kt index 672f6399015..767e8e135ff 100644 --- a/logcat/testSrc/com/android/tools/idea/logcat/LogcatMainPanelTest.kt +++ b/logcat/testSrc/com/android/tools/idea/logcat/LogcatMainPanelTest.kt @@ -134,13 +134,14 @@ class LogcatMainPanelTest { private val mockFoldingDetector = mock<FoldingDetector>() private val fakeAdbSession = FakeAdbSession() private val androidLogcatFormattingOptions = AndroidLogcatFormattingOptions() + private val project get() = projectRule.project @Before fun setUp() { ApplicationManager.getApplication().replaceService( AndroidLogcatFormattingOptions::class.java, androidLogcatFormattingOptions, - projectRule.project) + project) } @RunsInEdt @@ -375,7 +376,7 @@ class LogcatMainPanelTest { } } - projectRule.project.messageBus.syncPublisher(ClearLogcatListener.TOPIC).clearLogcat("device1") + project.messageBus.syncPublisher(ClearLogcatListener.TOPIC).clearLogcat("device1") ConcurrencyUtil.awaitQuiescence(AndroidExecutors.getInstance().workerThreadExecutor as ThreadPoolExecutor, TIMEOUT_SEC, SECONDS) runInEdtAndWait { } @@ -397,7 +398,7 @@ class LogcatMainPanelTest { } } - projectRule.project.messageBus.syncPublisher(ClearLogcatListener.TOPIC).clearLogcat("device2") + project.messageBus.syncPublisher(ClearLogcatListener.TOPIC).clearLogcat("device2") ConcurrencyUtil.awaitQuiescence(AndroidExecutors.getInstance().workerThreadExecutor as ThreadPoolExecutor, TIMEOUT_SEC, SECONDS) runInEdtAndWait { } @@ -994,9 +995,9 @@ class LogcatMainPanelTest { val testDevice = TestDevice("device1", DeviceState.ONLINE, 11, 30, "Google", "Pixel", "") fakeAdbSession.deviceServices.setupCommandsForDevice(testDevice) fakeAdbSession.hostServices.setDevices(testDevice) - val fakePackageNamesProvider = FakePackageNamesProvider("myapp") + val fakePackageNamesProvider = FakeProjectApplicationIdsProvider(project, "myapp") val logcatMainPanel = runInEdtAndGet { - logcatMainPanel(adbSession = fakeAdbSession, packageNamesProvider = fakePackageNamesProvider).also { + logcatMainPanel(adbSession = fakeAdbSession, projectApplicationIdsProvider = fakePackageNamesProvider).also { waitForCondition { it.getConnectedDevice() != null } } } @@ -1026,6 +1027,38 @@ class LogcatMainPanelTest { assertThat(AndroidDebugBridge.getDeviceChangeListenerCount() == 0) } + @Test + fun projectApplicationIdsChange_withPackageMine_reloadsMessages() = runBlocking { + val fakeProjectApplicationIdsProvider = FakeProjectApplicationIdsProvider(project) + val logcatMainPanel = runInEdtAndGet { + logcatMainPanel(projectApplicationIdsProvider = fakeProjectApplicationIdsProvider) + } + logcatMainPanel.processMessages(listOf( + LogcatMessage(LogcatHeader(WARN, 1, 2, "app1", "", "tag1", Instant.ofEpochMilli(1000)), "message1"), + LogcatMessage(LogcatHeader(WARN, 1, 2, "app2", "", "tag2", Instant.ofEpochMilli(1000)), "message2"), + )) + runInEdtAndWait { + logcatMainPanel.setFilter("package:mine | tag:tag2") + } + waitForCondition { + logcatMainPanel.editor.document.text.trim() == """ + 1970-01-01 04:00:01.000 1-2 tag2 app2 W message2 + """.trimIndent() + } + + runInEdtAndWait { + fakeProjectApplicationIdsProvider.setApplicationIds("app1") + } + + ConcurrencyUtil.awaitQuiescence(AndroidExecutors.getInstance().workerThreadExecutor as ThreadPoolExecutor, TIMEOUT_SEC, SECONDS) + logcatMainPanel.messageProcessor.onIdle { + assertThat(logcatMainPanel.editor.document.text.trim()).isEqualTo(""" + 1970-01-01 04:00:01.000 1-2 tag1 app1 W message1 + 1970-01-01 04:00:01.000 1-2 tag2 app2 W message2 + """.trimIndent()) + } + } + private fun logcatMainPanel( splitterPopupActionGroup: ActionGroup = EMPTY_GROUP, logcatColors: LogcatColors = LogcatColors(), @@ -1034,13 +1067,14 @@ class LogcatMainPanelTest { androidProjectDetector: AndroidProjectDetector = FakeAndroidProjectDetector(true), hyperlinkDetector: HyperlinkDetector? = null, foldingDetector: FoldingDetector? = null, - packageNamesProvider: PackageNamesProvider = FakePackageNamesProvider(), + projectApplicationIdsProvider: ProjectApplicationIdsProvider = FakeProjectApplicationIdsProvider(project), adbSession: AdbSession = FakeAdbSession(), logcatService: LogcatService = FakeLogcatService(), zoneId: ZoneId = ZoneId.of("Asia/Yerevan"), - ) = - LogcatMainPanel( - projectRule.project, + ): LogcatMainPanel { + project.replaceService(ProjectApplicationIdsProvider::class.java, projectApplicationIdsProvider, project) + return LogcatMainPanel( + project, splitterPopupActionGroup, logcatColors, state, @@ -1048,13 +1082,13 @@ class LogcatMainPanelTest { androidProjectDetector, hyperlinkDetector, foldingDetector, - packageNamesProvider, adbSession, logcatService, zoneId, ).also { - Disposer.register(projectRule.project, it) + Disposer.register(project, it) } + } } private fun LogcatMessage.length() = FormattingOptions().getHeaderWidth() + message.length diff --git a/logcat/testSrc/com/android/tools/idea/logcat/ProjectApplicationIdsProviderImplTest.kt b/logcat/testSrc/com/android/tools/idea/logcat/ProjectApplicationIdsProviderImplTest.kt new file mode 100644 index 00000000000..f2b378a0666 --- /dev/null +++ b/logcat/testSrc/com/android/tools/idea/logcat/ProjectApplicationIdsProviderImplTest.kt @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.tools.idea.logcat + +import com.android.testutils.MockitoKt.mock +import com.android.testutils.MockitoKt.whenever +import com.android.tools.idea.logcat.ProjectApplicationIdsProvider.Companion.PROJECT_APPLICATION_IDS_CHANGED_TOPIC +import com.android.tools.idea.logcat.ProjectApplicationIdsProvider.ProjectApplicationIdsListener +import com.android.tools.idea.model.AndroidModel +import com.android.tools.idea.model.TestAndroidModel +import com.android.tools.idea.projectsystem.PROJECT_SYSTEM_SYNC_TOPIC +import com.android.tools.idea.projectsystem.ProjectSystemSyncManager.SyncResult.SUCCESS +import com.android.tools.idea.testing.registerServiceInstance +import com.google.common.truth.Truth.assertThat +import com.intellij.facet.ProjectFacetManager +import com.intellij.mock.MockModule +import com.intellij.openapi.util.Disposer +import com.intellij.testFramework.ProjectRule +import com.intellij.testFramework.RuleChain +import org.jetbrains.android.facet.AndroidFacet +import org.jetbrains.android.facet.AndroidFacetConfiguration +import org.junit.Before +import org.junit.Rule +import org.junit.Test + +/** + * Tests for [ProjectApplicationIdsProviderImpl] + */ +class ProjectApplicationIdsProviderImplTest { + private val projectRule = ProjectRule() + + @get:Rule + val rule = RuleChain(projectRule) + + private val project get() = projectRule.project + private val mockProjectFacetManager = mock<ProjectFacetManager>() + + @Before + fun setUp() { + project.registerServiceInstance(ProjectFacetManager::class.java, mockProjectFacetManager, project) + } + + @Test + fun initialize_loadsApplicationIds() { + val facet1 = mockFacet("app1") + val facet2 = mockFacet("app2", "app3") + whenever(mockProjectFacetManager.getFacets(AndroidFacet.ID)).thenReturn(listOf(facet1, facet2)) + + val projectApplicationIdsProviderImpl = ProjectApplicationIdsProviderImpl(project) + + assertThat(projectApplicationIdsProviderImpl.getPackageNames()).containsExactly( + "app1", + "app2", + "app3", + ) + } + + @Test + fun syncEnds_reloadsApplicationIds() { + val facet1 = mockFacet("app1") + whenever(mockProjectFacetManager.getFacets(AndroidFacet.ID)).thenReturn(listOf(facet1)) + val projectApplicationIdsProviderImpl = ProjectApplicationIdsProviderImpl(project) + + val facet2 = mockFacet("app2", "app3") + whenever(mockProjectFacetManager.getFacets(AndroidFacet.ID)).thenReturn(listOf(facet1, facet2)) + project.messageBus.syncPublisher(PROJECT_SYSTEM_SYNC_TOPIC).syncEnded(SUCCESS) + + assertThat(projectApplicationIdsProviderImpl.getPackageNames()).containsExactly( + "app1", + "app2", + "app3", + ) + } + + @Test + fun syncEnds_applicationIdsChange_notifies() { + val facet1 = mockFacet("app1") + whenever(mockProjectFacetManager.getFacets(AndroidFacet.ID)).thenReturn(listOf(facet1)) + ProjectApplicationIdsProviderImpl(project) + var notified = false + project.messageBus.connect(project).subscribe(PROJECT_APPLICATION_IDS_CHANGED_TOPIC, ProjectApplicationIdsListener { + notified = true + }) + + val facet2 = mockFacet("app2") + whenever(mockProjectFacetManager.getFacets(AndroidFacet.ID)).thenReturn(listOf(facet2)) + project.messageBus.syncPublisher(PROJECT_SYSTEM_SYNC_TOPIC).syncEnded(SUCCESS) + + assertThat(notified).isTrue() + } + + @Test + fun syncEnds_applicationIdsDoNotChange_doesNotNotifies() { + val facet1 = mockFacet("app1") + whenever(mockProjectFacetManager.getFacets(AndroidFacet.ID)).thenReturn(listOf(facet1)) + ProjectApplicationIdsProviderImpl(project) + var notified = false + project.messageBus.connect(project).subscribe(PROJECT_APPLICATION_IDS_CHANGED_TOPIC, ProjectApplicationIdsListener { + notified = true + }) + + project.messageBus.syncPublisher(PROJECT_SYSTEM_SYNC_TOPIC).syncEnded(SUCCESS) + + assertThat(notified).isFalse() + } + + private fun mockFacet(vararg applicationIds: String): AndroidFacet { + val facet = AndroidFacet(MockModule(project), "ProjectApplicationIdsProviderImplTest:Facet", AndroidFacetConfiguration()) + Disposer.register(project, facet) + AndroidModel.set(facet, TestAndroidModel(allApplicationIds = applicationIds.toSet())) + return facet + } +}
\ No newline at end of file |