Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit be8a78c1 authored by Steve Elliott's avatar Steve Elliott Committed by Android (Google) Code Review
Browse files

Merge "Move Kosmos to its own build module" into main

parents 721fcd47 b42fe7c3
Loading
Loading
Loading
Loading
+21 −1
Original line number Diff line number Diff line
@@ -196,13 +196,30 @@ filegroup {
    path: "tests/src",
}

filegroup {
    name: "kosmos-src",
    srcs: ["tests/utils/kosmos/src/**/*.kt"],
    path: "tests/utils/kosmos",
}

java_library {
    name: "kosmos",
    host_supported: true,
    srcs: [":kosmos-src"],
    static_libs: [
        "kotlin-reflect",
        "kotlin-stdlib",
    ],
}

filegroup {
    name: "SystemUI-tests-utils",
    srcs: [
        "tests/utils/src/**/*.java",
        "tests/utils/src/**/*.kt",
        ":kosmos-src",
    ],
    path: "tests/utils/src",
    path: "tests/utils",
}

filegroup {
@@ -334,6 +351,7 @@ android_library {
        "kotlin-test",
        "SystemUICustomizationTestUtils",
        "androidx.compose.runtime_runtime",
        "kosmos",
    ],
    libs: [
        "android.test.runner",
@@ -416,6 +434,7 @@ android_robolectric_test {
        "inline-mockito-robolectric-prebuilt",
        "platform-parametric-runner-lib",
        "SystemUICustomizationTestUtils",
        "kosmos",
    ],
    libs: [
        "android.test.runner",
@@ -449,6 +468,7 @@ android_ravenwood_test {
        "androidx.test.uiautomator_uiautomator",
        "androidx.core_core-animation-testing",
        "androidx.test.ext.junit",
        "kosmos",
    ],
    libs: [
        "android.test.runner",
+97 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.systemui.kosmos

import kotlin.reflect.KProperty
@@ -5,6 +21,7 @@ import kotlin.reflect.KProperty
// (Historical note: The name Kosmos is meant to invoke "Kotlin", the "Object Mother" pattern
//   (https://martinfowler.com/bliki/ObjectMother.html), and of course the Greek word "kosmos" for
//   the "order of the world" (https://en.wiktionary.org/wiki/%CE%BA%CF%8C%CF%83%CE%BC%CE%BF%CF%82)

/**
 * Each Kosmos is its own self-contained set of fixtures, which may reference each other. Fixtures
 * can be defined through extension properties in any file:
@@ -29,9 +46,15 @@ import kotlin.reflect.KProperty
 * )
 * ```
 */
class Kosmos {
    private val map: MutableMap<String, Any?> = mutableMapOf()
    private val gotten: MutableSet<String> = mutableSetOf()
interface Kosmos {
    /**
     * Lookup a fixture in the Kosmos by [name], using [creator] to instantiate and store one if
     * there is none present.
     */
    fun <T> get(name: String, creator: (Kosmos.() -> T)?): T

    /** Sets the [value] of a fixture with the given [name]. */
    fun set(name: String, value: Any?)

    /**
     * A value in the kosmos that has a single value once it's read. It can be overridden before
@@ -42,28 +65,33 @@ class Kosmos {
     * If no [creator] parameter is provided, the fixture must be set before use.
     */
    class Fixture<T>(private val creator: (Kosmos.() -> T)? = null) {
        operator fun getValue(thisRef: Kosmos, property: KProperty<*>): T {
            thisRef.gotten.add(property.name)
            @Suppress("UNCHECKED_CAST")
            if (!thisRef.map.contains(property.name)) {
                if (creator == null) {
                    throw IllegalStateException(
                        "Fixture ${property.name} has no default, and is read before set."
                    )
                } else {
                    val nonNullCreator = creator
                    // The Kotlin compiler seems to need this odd workaround
                    thisRef.map[property.name] = thisRef.nonNullCreator()
        operator fun getValue(thisRef: Kosmos, property: KProperty<*>): T =
            thisRef.get(property.name, creator)

        operator fun setValue(thisRef: Kosmos, property: KProperty<*>, value: T) {
            thisRef.set(property.name, value)
        }
    }
            return thisRef.map[property.name] as T
}

        operator fun setValue(thisRef: Kosmos, property: KProperty<*>, value: T) {
            check(!thisRef.gotten.contains(property.name)) {
                "Tried to set fixture '${property.name}' after it's already been read."
/** Constructs a fresh Kosmos. */
fun Kosmos(): Kosmos = KosmosRegistry()

private class KosmosRegistry : Kosmos {
    val map: MutableMap<String, Any?> = mutableMapOf()
    val gotten: MutableSet<String> = mutableSetOf()

    override fun <T> get(name: String, creator: (Kosmos.() -> T)?): T {
        gotten.add(name)
        if (name !in map) {
            checkNotNull(creator) { "Fixture $name has no default, and is read before set." }
            map[name] = creator()
        }
            thisRef.map[property.name] = value
        @Suppress("UNCHECKED_CAST") return map[name] as T
    }

    override fun set(name: String, value: Any?) {
        check(name !in gotten) { "Tried to set fixture '$name' after it's already been read." }
        map[name] = value
    }
}