From d5d0b358066e0eb386110ee24dbea6db4a391828 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sun, 28 Nov 2021 17:56:11 +0000 Subject: [PATCH] Add `DeviceInfo.random(Random)` and implement `equals` and `hashCode` for `DeviceInfo` --- ...binary-compatibility-validator-android.api | 6 + .../api/binary-compatibility-validator.api | 6 + .../src/commonMain/kotlin/utils/DeviceInfo.kt | 126 ++++++++++++++++-- .../commonTest/kotlin/utils/DeviceInfoTest.kt | 22 +++ .../src/commonMain/kotlin/RandomUtils.kt | 19 +-- 5 files changed, 161 insertions(+), 18 deletions(-) create mode 100644 mirai-core-api/src/commonTest/kotlin/utils/DeviceInfoTest.kt diff --git a/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api b/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api index 0d0bedbbb..c4c1fddca 100644 --- a/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api +++ b/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api @@ -5755,6 +5755,7 @@ public final class net/mamoe/mirai/utils/DeviceInfo { public static final field Companion Lnet/mamoe/mirai/utils/DeviceInfo$Companion; public synthetic fun (I[B[B[B[B[B[B[B[B[B[B[BLnet/mamoe/mirai/utils/DeviceInfo$Version;[B[B[B[B[B[BLjava/lang/String;[BLkotlinx/serialization/internal/SerializationConstructorMarker;)V public fun ([B[B[B[B[B[B[B[B[B[B[BLnet/mamoe/mirai/utils/DeviceInfo$Version;[B[B[B[B[B[BLjava/lang/String;[B)V + public fun equals (Ljava/lang/Object;)Z public static final fun from (Ljava/io/File;)Lnet/mamoe/mirai/utils/DeviceInfo; public static final fun from (Ljava/io/File;Lkotlinx/serialization/json/Json;)Lnet/mamoe/mirai/utils/DeviceInfo; public final fun getAndroidId ()[B @@ -5780,7 +5781,9 @@ public final class net/mamoe/mirai/utils/DeviceInfo { public final fun getVersion ()Lnet/mamoe/mirai/utils/DeviceInfo$Version; public final fun getWifiBSSID ()[B public final fun getWifiSSID ()[B + public fun hashCode ()I public static final fun random ()Lnet/mamoe/mirai/utils/DeviceInfo; + public static final fun random (Lkotlin/random/Random;)Lnet/mamoe/mirai/utils/DeviceInfo; public static final fun write$Self (Lnet/mamoe/mirai/utils/DeviceInfo;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V } @@ -5801,6 +5804,7 @@ public final class net/mamoe/mirai/utils/DeviceInfo$Companion { public final fun from (Ljava/io/File;Lkotlinx/serialization/json/Json;)Lnet/mamoe/mirai/utils/DeviceInfo; public static synthetic fun from$default (Lnet/mamoe/mirai/utils/DeviceInfo$Companion;Ljava/io/File;Lkotlinx/serialization/json/Json;ILjava/lang/Object;)Lnet/mamoe/mirai/utils/DeviceInfo; public final fun random ()Lnet/mamoe/mirai/utils/DeviceInfo; + public final fun random (Lkotlin/random/Random;)Lnet/mamoe/mirai/utils/DeviceInfo; public final fun serializer ()Lkotlinx/serialization/KSerializer; } @@ -5810,10 +5814,12 @@ public final class net/mamoe/mirai/utils/DeviceInfo$Version { public synthetic fun (I[B[B[BILkotlinx/serialization/internal/SerializationConstructorMarker;)V public fun ([B[B[BI)V public synthetic fun ([B[B[BIILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun equals (Ljava/lang/Object;)Z public final fun getCodename ()[B public final fun getIncremental ()[B public final fun getRelease ()[B public final fun getSdk ()I + public fun hashCode ()I public static final fun write$Self (Lnet/mamoe/mirai/utils/DeviceInfo$Version;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V } diff --git a/binary-compatibility-validator/api/binary-compatibility-validator.api b/binary-compatibility-validator/api/binary-compatibility-validator.api index 24c03d981..ed35cde73 100644 --- a/binary-compatibility-validator/api/binary-compatibility-validator.api +++ b/binary-compatibility-validator/api/binary-compatibility-validator.api @@ -5755,6 +5755,7 @@ public final class net/mamoe/mirai/utils/DeviceInfo { public static final field Companion Lnet/mamoe/mirai/utils/DeviceInfo$Companion; public synthetic fun (I[B[B[B[B[B[B[B[B[B[B[BLnet/mamoe/mirai/utils/DeviceInfo$Version;[B[B[B[B[B[BLjava/lang/String;[BLkotlinx/serialization/internal/SerializationConstructorMarker;)V public fun ([B[B[B[B[B[B[B[B[B[B[BLnet/mamoe/mirai/utils/DeviceInfo$Version;[B[B[B[B[B[BLjava/lang/String;[B)V + public fun equals (Ljava/lang/Object;)Z public static final fun from (Ljava/io/File;)Lnet/mamoe/mirai/utils/DeviceInfo; public static final fun from (Ljava/io/File;Lkotlinx/serialization/json/Json;)Lnet/mamoe/mirai/utils/DeviceInfo; public final fun getAndroidId ()[B @@ -5780,7 +5781,9 @@ public final class net/mamoe/mirai/utils/DeviceInfo { public final fun getVersion ()Lnet/mamoe/mirai/utils/DeviceInfo$Version; public final fun getWifiBSSID ()[B public final fun getWifiSSID ()[B + public fun hashCode ()I public static final fun random ()Lnet/mamoe/mirai/utils/DeviceInfo; + public static final fun random (Lkotlin/random/Random;)Lnet/mamoe/mirai/utils/DeviceInfo; public static final fun write$Self (Lnet/mamoe/mirai/utils/DeviceInfo;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V } @@ -5801,6 +5804,7 @@ public final class net/mamoe/mirai/utils/DeviceInfo$Companion { public final fun from (Ljava/io/File;Lkotlinx/serialization/json/Json;)Lnet/mamoe/mirai/utils/DeviceInfo; public static synthetic fun from$default (Lnet/mamoe/mirai/utils/DeviceInfo$Companion;Ljava/io/File;Lkotlinx/serialization/json/Json;ILjava/lang/Object;)Lnet/mamoe/mirai/utils/DeviceInfo; public final fun random ()Lnet/mamoe/mirai/utils/DeviceInfo; + public final fun random (Lkotlin/random/Random;)Lnet/mamoe/mirai/utils/DeviceInfo; public final fun serializer ()Lkotlinx/serialization/KSerializer; } @@ -5810,10 +5814,12 @@ public final class net/mamoe/mirai/utils/DeviceInfo$Version { public synthetic fun (I[B[B[BILkotlinx/serialization/internal/SerializationConstructorMarker;)V public fun ([B[B[BI)V public synthetic fun ([B[B[BIILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun equals (Ljava/lang/Object;)Z public final fun getCodename ()[B public final fun getIncremental ()[B public final fun getRelease ()[B public final fun getSdk ()I + public fun hashCode ()I public static final fun write$Self (Lnet/mamoe/mirai/utils/DeviceInfo$Version;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V } diff --git a/mirai-core-api/src/commonMain/kotlin/utils/DeviceInfo.kt b/mirai-core-api/src/commonMain/kotlin/utils/DeviceInfo.kt index 41dc6d4f2..0db3bef60 100644 --- a/mirai-core-api/src/commonMain/kotlin/utils/DeviceInfo.kt +++ b/mirai-core-api/src/commonMain/kotlin/utils/DeviceInfo.kt @@ -16,6 +16,7 @@ import kotlinx.serialization.json.Json import kotlinx.serialization.protobuf.ProtoBuf import kotlinx.serialization.protobuf.ProtoNumber import java.io.File +import kotlin.random.Random @Serializable public class DeviceInfo( @@ -57,7 +58,35 @@ public class DeviceInfo( public val release: ByteArray = "10".toByteArray(), public val codename: ByteArray = "REL".toByteArray(), public val sdk: Int = 29 - ) + ) { + /** + * @since 2.9 + */ + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as Version + + if (!incremental.contentEquals(other.incremental)) return false + if (!release.contentEquals(other.release)) return false + if (!codename.contentEquals(other.codename)) return false + if (sdk != other.sdk) return false + + return true + } + + /** + * @since 2.9 + */ + override fun hashCode(): Int { + var result = incremental.contentHashCode() + result = 31 * result + release.contentHashCode() + result = 31 * result + codename.contentHashCode() + result = 31 * result + sdk + return result + } + } public companion object { internal val logger = MiraiLogger.Factory.create(DeviceInfo::class, "DeviceInfo") @@ -79,20 +108,36 @@ public class DeviceInfo( return json.decodeFromString(serializer(), this.readText()) } - + /** + * 生成随机 [DeviceInfo] + * + * @since 2.0 + */ @JvmStatic - public fun random(): DeviceInfo { + public fun random(): DeviceInfo = random(Random.Default) + + /** + * 使用特定随机数生成器生成 [DeviceInfo] + * + * @since 2.9 + */ + @JvmStatic + public fun random(random: Random): DeviceInfo { return DeviceInfo( - display = "MIRAI.${getRandomString(6, '0'..'9')}.001".toByteArray(), + display = "MIRAI.${getRandomString(6, '0'..'9', random)}.001".toByteArray(), product = "mirai".toByteArray(), device = "mirai".toByteArray(), board = "mirai".toByteArray(), brand = "mamoe".toByteArray(), model = "mirai".toByteArray(), bootloader = "unknown".toByteArray(), - fingerprint = "mamoe/mirai/mirai:10/MIRAI.200122.001/${getRandomIntString(7)}:user/release-keys".toByteArray(), - bootId = generateUUID(getRandomByteArray(16).md5()).toByteArray(), - procVersion = "Linux version 3.0.31-${getRandomString(8)} (android-build@xxx.xxx.xxx.xxx.com)".toByteArray(), + fingerprint = "mamoe/mirai/mirai:10/MIRAI.200122.001/${ + getRandomIntString(7, random) + }:user/release-keys".toByteArray(), + bootId = generateUUID(getRandomByteArray(16, random).md5()).toByteArray(), + procVersion = "Linux version 3.0.31-${ + getRandomString(8, random) + } (android-build@xxx.xxx.xxx.xxx.com)".toByteArray(), baseBand = byteArrayOf(), version = Version(), simInfo = "T-Mobile".toByteArray(), @@ -100,12 +145,75 @@ public class DeviceInfo( macAddress = "02:00:00:00:00:00".toByteArray(), wifiBSSID = "02:00:00:00:00:00".toByteArray(), wifiSSID = "".toByteArray(), - imsiMd5 = getRandomByteArray(16).md5(), - imei = getRandomIntString(15), + imsiMd5 = getRandomByteArray(16, random).md5(), + imei = getRandomIntString(15, random), apn = "wifi".toByteArray() ) } } + + /** + * @since 2.9 + */ + @Suppress("DuplicatedCode") + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as DeviceInfo + + if (!display.contentEquals(other.display)) return false + if (!product.contentEquals(other.product)) return false + if (!device.contentEquals(other.device)) return false + if (!board.contentEquals(other.board)) return false + if (!brand.contentEquals(other.brand)) return false + if (!model.contentEquals(other.model)) return false + if (!bootloader.contentEquals(other.bootloader)) return false + if (!fingerprint.contentEquals(other.fingerprint)) return false + if (!bootId.contentEquals(other.bootId)) return false + if (!procVersion.contentEquals(other.procVersion)) return false + if (!baseBand.contentEquals(other.baseBand)) return false + if (version != other.version) return false + if (!simInfo.contentEquals(other.simInfo)) return false + if (!osType.contentEquals(other.osType)) return false + if (!macAddress.contentEquals(other.macAddress)) return false + if (!wifiBSSID.contentEquals(other.wifiBSSID)) return false + if (!wifiSSID.contentEquals(other.wifiSSID)) return false + if (!imsiMd5.contentEquals(other.imsiMd5)) return false + if (imei != other.imei) return false + if (!apn.contentEquals(other.apn)) return false + if (!guid.contentEquals(other.guid)) return false + + return true + } + + /** + * @since 2.9 + */ + override fun hashCode(): Int { + var result = display.contentHashCode() + result = 31 * result + product.contentHashCode() + result = 31 * result + device.contentHashCode() + result = 31 * result + board.contentHashCode() + result = 31 * result + brand.contentHashCode() + result = 31 * result + model.contentHashCode() + result = 31 * result + bootloader.contentHashCode() + result = 31 * result + fingerprint.contentHashCode() + result = 31 * result + bootId.contentHashCode() + result = 31 * result + procVersion.contentHashCode() + result = 31 * result + baseBand.contentHashCode() + result = 31 * result + version.hashCode() + result = 31 * result + simInfo.contentHashCode() + result = 31 * result + osType.contentHashCode() + result = 31 * result + macAddress.contentHashCode() + result = 31 * result + wifiBSSID.contentHashCode() + result = 31 * result + wifiSSID.contentHashCode() + result = 31 * result + imsiMd5.contentHashCode() + result = 31 * result + imei.hashCode() + result = 31 * result + apn.contentHashCode() + result = 31 * result + guid.contentHashCode() + return result + } } @Serializable diff --git a/mirai-core-api/src/commonTest/kotlin/utils/DeviceInfoTest.kt b/mirai-core-api/src/commonTest/kotlin/utils/DeviceInfoTest.kt new file mode 100644 index 000000000..048d062f6 --- /dev/null +++ b/mirai-core-api/src/commonTest/kotlin/utils/DeviceInfoTest.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2019-2021 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/dev/LICENSE + */ + +package net.mamoe.mirai.utils + +import kotlin.random.Random +import kotlin.test.Test +import kotlin.test.assertEquals + +class DeviceInfoTest { + @Test + fun `DeviceInfo_random with custom Random is stable`() { + val time = System.currentTimeMillis() + assertEquals(DeviceInfo.random(Random(time)), DeviceInfo.random(Random(time))) + } +} \ No newline at end of file diff --git a/mirai-core-utils/src/commonMain/kotlin/RandomUtils.kt b/mirai-core-utils/src/commonMain/kotlin/RandomUtils.kt index 0c4642472..3754d9e7a 100644 --- a/mirai-core-utils/src/commonMain/kotlin/RandomUtils.kt +++ b/mirai-core-utils/src/commonMain/kotlin/RandomUtils.kt @@ -22,7 +22,8 @@ import kotlin.random.nextInt /** * 生成长度为 [length], 元素为随机 `0..255` 的 [ByteArray] */ -public fun getRandomByteArray(length: Int): ByteArray = ByteArray(length) { Random.nextInt(0..255).toByte() } +public fun getRandomByteArray(length: Int, random: Random = Random): ByteArray = + ByteArray(length) { random.nextInt(0..255).toByte() } /** * 随机生成一个正整数 @@ -32,8 +33,8 @@ public fun getRandomUnsignedInt(): Int = Random.nextInt().absoluteValue /** * 随机生成长度为 [length] 的 [String]. */ -public fun getRandomString(length: Int): String = - getRandomString(length, *defaultRanges) +public fun getRandomString(length: Int, random: Random = Random): String = + getRandomString(length, *defaultRanges, random = random) private val defaultRanges: Array = arrayOf('a'..'z', 'A'..'Z', '0'..'9') private val intCharRanges: Array = arrayOf('0'..'9') @@ -41,15 +42,15 @@ private val intCharRanges: Array = arrayOf('0'..'9') /** * 根据所给 [charRange] 随机生成长度为 [length] 的 [String]. */ -public fun getRandomString(length: Int, charRange: CharRange): String = - CharArray(length) { charRange.random() }.concatToString() +public fun getRandomString(length: Int, charRange: CharRange, random: Random = Random): String = + CharArray(length) { charRange.random(random) }.concatToString() /** * 根据所给 [charRanges] 随机生成长度为 [length] 的 [String]. */ -public fun getRandomString(length: Int, vararg charRanges: CharRange): String = - CharArray(length) { charRanges[Random.Default.nextInt(0..charRanges.lastIndex)].random() }.concatToString() +public fun getRandomString(length: Int, vararg charRanges: CharRange, random: Random = Random): String = + CharArray(length) { charRanges[random.nextInt(0..charRanges.lastIndex)].random(random) }.concatToString() -public fun getRandomIntString(length: Int): String = - getRandomString(length, *intCharRanges) \ No newline at end of file +public fun getRandomIntString(length: Int, random: Random = Random): String = + getRandomString(length, *intCharRanges, random = random) \ No newline at end of file