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

Commit 29f023c2 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Introducing NamedLock." into main

parents 612a7b78 88d36827
Loading
Loading
Loading
Loading
+55 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.internal.util;

import java.util.Objects;

/**
 * A lock with a name!
 *
 * <p>This class should be used as a synchronization lock (i.e., instead of
 * {@code mLock = new Object()}, so stack traces show exactly what the lock's for (other than just
 * it's internal address). In other words, it solves the "A Lock has no Name!" issue).
 *
 * @hide
 */
public final class NamedLock {

    private final String mName;

    private NamedLock(String name) {
        mName = Objects.requireNonNull(name, "name cannot be null");
        String stripped = name.strip();
        Preconditions.checkArgument(name.equals(stripped),
                "name (%s) cannot start or end with blank characters", name);
        Preconditions.checkArgument(!name.isEmpty(), "name cannot be empty");
    }

    /**
     * Creates a lock with the given name.
     *
     * @throws IllegalArgumentException if the name is empty, starts with a blank character, or ends
     *             with a blank character.
     */
    public static Object create(String name) {
        return new NamedLock(name);
    }

    @Override
    public String toString() {
        return mName;
    }
}
+93 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.internal.util;

import static com.android.internal.util.NamedLock.create;

import static com.google.common.truth.Truth.assertWithMessage;

import static org.junit.Assert.assertThrows;

import org.junit.Test;

public final class NamedLockTest {

    @Test
    public void testFactoryMethod_null() {
        assertThrows(NullPointerException.class, () -> create(null));
    }

    @Test
    public void testFactoryMethod_empty() {
        assertThrows(IllegalArgumentException.class, () -> create(""));
        assertThrows(IllegalArgumentException.class, () -> create(" "));
        assertThrows(IllegalArgumentException.class, () -> create("\t"));
    }

    @Test
    public void testFactoryMethod_startsWithSpace() {
        assertThrows(IllegalArgumentException.class,
                () -> create(" NAME, Y U START WITH SPACE?"));
    }

    @Test
    public void testFactoryMethod_startsWithTab() {
        assertThrows(IllegalArgumentException.class,
                () -> create("\tNAME, Y U START WITH TAB?"));
    }

    @Test
    public void testFactoryMethod_endsWithSpace() {
        assertThrows(IllegalArgumentException.class,
                () -> create("NAME, Y U END WITH SPACE? "));
    }

    @Test
    public void testFactoryMethod_endsWithTab() {
        assertThrows(IllegalArgumentException.class,
                () -> create("NAME, Y U END WITH TAB?\t"));
    }

    @Test
    public void testOneInstance() {
        var namedLock = create("Bond, James Bond");

        assertWithMessage("create()").that(namedLock).isNotNull();

        assertWithMessage("toString()").that(namedLock.toString()).isEqualTo("Bond, James Bond");
    }

    @Test
    public void testMultipleInstances_sameName() {
        String commonName = "Bond, James Bond";
        var namedLock1 = create(commonName);
        var namedLock2 = create(commonName);

        assertWithMessage("namedLock1").that(namedLock1).isNotSameInstanceAs(namedLock2);
        assertWithMessage("namedLock1").that(namedLock1).isNotEqualTo(namedLock2);
        assertWithMessage("namedLock2").that(namedLock2).isNotEqualTo(namedLock1);
    }

    @Test
    public void testMultipleInstances_differentNames() {
        var namedLock1 = create("Bond, James Bond");
        var namedLock2 = create("A Lock has a Name");

        assertWithMessage("namedLock1").that(namedLock1).isNotSameInstanceAs(namedLock2);
        assertWithMessage("namedLock1").that(namedLock1).isNotEqualTo(namedLock2);
        assertWithMessage("namedLock2").that(namedLock2).isNotEqualTo(namedLock1);
    }
}