mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[ab] IJPL-186222 support product-specific experiments
GitOrigin-RevId: 3482ab936f56ad856f91924754125fa221c90154
This commit is contained in:
committed by
intellij-monorepo-bot
parent
15ca1be9f9
commit
d6e4c47453
@@ -6,9 +6,10 @@ import com.intellij.openapi.application.ApplicationInfo
|
||||
import com.intellij.openapi.diagnostic.debug
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.diagnostic.runAndLogException
|
||||
import com.intellij.platform.experiment.ab.impl.ABExperimentOption.*
|
||||
import com.intellij.platform.experiment.ab.impl.ABExperimentOption.UNASSIGNED
|
||||
import com.intellij.platform.experiment.ab.impl.statistic.ABExperimentCountCollector
|
||||
import org.jetbrains.annotations.VisibleForTesting
|
||||
import java.util.*
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
/**
|
||||
@@ -77,18 +78,22 @@ internal fun ABExperimentOption.reportableName(): String {
|
||||
private val thisUserDecision: ABExperimentDecision by lazy {
|
||||
val currentBucket = getUserBucketNumber()
|
||||
val currentVersion = ApplicationInfo.getInstance().fullVersion
|
||||
val currentProduct = IntelliJPlatformProduct.get()
|
||||
val option = experimentsPartition.find {
|
||||
(it.majorVersion == null || currentVersion.startsWith(it.majorVersion)) &&
|
||||
(it.experimentBuckets.contains(currentBucket) || it.controlBuckets.contains(currentBucket))
|
||||
(it.experimentBuckets.contains(currentBucket) || it.controlBuckets.contains(currentBucket)) &&
|
||||
it.products.contains(currentProduct)
|
||||
} ?: return@lazy ABExperimentDecision(option = UNASSIGNED, isControlGroup = true, bucketNumber = currentBucket)
|
||||
ABExperimentDecision(option = option.experiment, isControlGroup = option.controlBuckets.contains(currentBucket), bucketNumber = currentBucket)
|
||||
}
|
||||
|
||||
data class ExperimentAssignment(
|
||||
internal data class ExperimentAssignment(
|
||||
val experiment: ABExperimentOption,
|
||||
val experimentBuckets: Set<Int>,
|
||||
val controlBuckets: Set<Int>,
|
||||
val majorVersion: String? = null)
|
||||
val majorVersion: String? = null,
|
||||
val products: Set<IntelliJPlatformProduct> = EnumSet.allOf(IntelliJPlatformProduct::class.java)
|
||||
)
|
||||
|
||||
internal fun getUserBucketNumber(): Int {
|
||||
val overridingBucket = Integer.getInteger("ide.ab.test.overriding.bucket")
|
||||
@@ -109,4 +114,17 @@ private fun getDeviceIdPurpose(): String {
|
||||
return "A/B Experiment" + ApplicationInfo.getInstance().shortVersion
|
||||
}
|
||||
|
||||
private val LOG = logger<ABExperimentOption>()
|
||||
private val LOG = logger<ABExperimentOption>()
|
||||
|
||||
/**
|
||||
* There is no need to list all available products. Add if a product-specific experiment is needed.
|
||||
*/
|
||||
internal enum class IntelliJPlatformProduct {
|
||||
OTHER,
|
||||
;
|
||||
|
||||
companion object {
|
||||
fun get(): IntelliJPlatformProduct =
|
||||
OTHER
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.platform.experiment.ab
|
||||
|
||||
import com.intellij.platform.experiment.ab.impl.IntelliJPlatformProduct
|
||||
import com.intellij.platform.experiment.ab.impl.NUMBER_OF_BUCKETS
|
||||
import com.intellij.platform.experiment.ab.impl.experimentsPartition
|
||||
import org.junit.jupiter.api.Assertions
|
||||
@@ -12,14 +13,17 @@ class ABExperimentSanityTest {
|
||||
fun `no intersections in experiment partitions`() {
|
||||
for (experiment1 in experimentsPartition) {
|
||||
for (experiment2 in experimentsPartition) {
|
||||
if (experiment1.experiment == experiment2.experiment) {
|
||||
assertEmptyIntersection(experiment1.controlBuckets, experiment2.experimentBuckets)
|
||||
}
|
||||
else {
|
||||
assertEmptyIntersection(experiment1.experimentBuckets, experiment2.controlBuckets)
|
||||
assertEmptyIntersection(experiment1.controlBuckets, experiment2.controlBuckets)
|
||||
assertEmptyIntersection(experiment1.experimentBuckets, experiment2.experimentBuckets)
|
||||
assertEmptyIntersection(experiment1.controlBuckets, experiment2.experimentBuckets)
|
||||
for (product in IntelliJPlatformProduct.entries) {
|
||||
if (!experiment1.products.contains(product) || !experiment2.products.contains(product)) continue
|
||||
if (experiment1.experiment == experiment2.experiment) {
|
||||
assertEmptyIntersection(experiment1.controlBuckets, experiment2.experimentBuckets)
|
||||
}
|
||||
else {
|
||||
assertEmptyIntersection(experiment1.experimentBuckets, experiment2.controlBuckets)
|
||||
assertEmptyIntersection(experiment1.controlBuckets, experiment2.controlBuckets)
|
||||
assertEmptyIntersection(experiment1.experimentBuckets, experiment2.experimentBuckets)
|
||||
assertEmptyIntersection(experiment1.controlBuckets, experiment2.experimentBuckets)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,6 +37,13 @@ class ABExperimentSanityTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `no experiment without associated products`() {
|
||||
for (experiment in experimentsPartition) {
|
||||
Assertions.assertTrue(experiment.products.isNotEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
fun assertEmptyIntersection(range1: Set<*>, range2: Set<*>) {
|
||||
Assertions.assertTrue(range1.intersect(range2).isEmpty())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user