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

Commit 0eafdad0 authored by Sebastián Franco's avatar Sebastián Franco Committed by Android (Google) Code Review
Browse files

Merge "Adding testin for Utilities.java" into main

parents 51c8ae66 3780e096
Loading
Loading
Loading
Loading
+53 −9
Original line number Diff line number Diff line
@@ -106,8 +106,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Various utilities shared amongst the Launcher's classes.
@@ -116,8 +114,7 @@ public final class Utilities {

    private static final String TAG = "Launcher.Utilities";

    private static final Pattern sTrimPattern =
            Pattern.compile("^[\\s|\\p{javaSpaceChar}]*(.*)[\\s|\\p{javaSpaceChar}]*$");
    private static final String TRIM_PATTERN = "(^\\h+|\\h+$)";

    private static final Matrix sMatrix = new Matrix();
    private static final Matrix sInverseMatrix = new Matrix();
@@ -445,10 +442,7 @@ public final class Utilities {
        if (s == null) {
            return "";
        }

        // Just strip any sequence of whitespace or java space characters from the beginning and end
        Matcher m = sTrimPattern.matcher(s);
        return m.replaceAll("$1");
        return s.toString().replaceAll(TRIM_PATTERN, "").trim();
    }

    /**
@@ -722,14 +716,59 @@ public final class Utilities {
    }

    /**
     * Rotates `inOutBounds` by `delta` 90-degree increments. Rotation is visually CCW. Parent
     * Rotates `inOutBounds` by `delta` 90-degree increments. Rotation is visually CW. Parent
     * sizes represent the "space" that will rotate carrying inOutBounds along with it to determine
     * the final bounds.
     *
     * As an example if this is the input:
     * +-------------+
     * |   +-----+   |
     * |   |     |   |
     * |   +-----+   |
     * |             |
     * |             |
     * |             |
     * +-------------+
     * This would be case delta % 4 == 0:
     * +-------------+
     * |   +-----+   |
     * |   |     |   |
     * |   +-----+   |
     * |             |
     * |             |
     * |             |
     * +-------------+
     * This would be case delta % 4 == 1:
     * +----------------+
     * |          +--+  |
     * |          |  |  |
     * |          |  |  |
     * |          +--+  |
     * |                |
     * +----------------+
     * This would be case delta % 4 == 2:
     * +-------------+
     * |             |
     * |             |
     * |             |
     * |   +-----+   |
     * |   |     |   |
     * |   +-----+   |
     * +-------------+
     * This would be case delta % 4 == 3:
     * +----------------+
     * |  +--+          |
     * |  |  |          |
     * |  |  |          |
     * |  +--+          |
     * |                |
     * +----------------+
     */
    public static void rotateBounds(Rect inOutBounds, int parentWidth, int parentHeight,
            int delta) {
        int rdelta = ((delta % 4) + 4) % 4;
        int origLeft = inOutBounds.left;
        int origTop = inOutBounds.top;
        switch (rdelta) {
            case 0:
                return;
@@ -741,6 +780,8 @@ public final class Utilities {
                return;
            case 2:
                inOutBounds.left = parentWidth - inOutBounds.right;
                inOutBounds.top = parentHeight - inOutBounds.bottom;
                inOutBounds.bottom = parentHeight - origTop;
                inOutBounds.right = parentWidth - origLeft;
                return;
            case 3:
@@ -830,6 +871,9 @@ public final class Utilities {
            @NonNull Rect inclusionBounds,
            @NonNull Rect exclusionBounds,
            @AdjustmentDirection int adjustmentDirection) {
        if (!Rect.intersects(targetViewBounds, exclusionBounds)) {
            return;
        }
        switch (adjustmentDirection) {
            case TRANSLATE_RIGHT:
                targetView.setTranslationX(Math.min(
+291 −1
Original line number Diff line number Diff line
@@ -17,12 +17,19 @@
package com.android.launcher3

import android.content.Context
import android.content.ContextWrapper
import android.graphics.Rect
import android.graphics.RectF
import android.view.View
import android.view.ViewGroup
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.launcher3.util.ActivityContextWrapper
import org.junit.Assert.*
import kotlin.random.Random
import org.junit.Assert.assertArrayEquals
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -30,6 +37,10 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class UtilitiesTest {

    companion object {
        const val SEED = 827
    }

    private lateinit var mContext: Context

    @Before
@@ -94,4 +105,283 @@ class UtilitiesTest {
        assertTrue(Utilities.pointInView(view, -5f, -5f, 10f)) // Inside slop
        assertFalse(Utilities.pointInView(view, 115f, 115f, 10f)) // Outside slop
    }

    @Test
    fun testNumberBounding() {
        assertEquals(887.99f, Utilities.boundToRange(887.99f, 0f, 1000f))
        assertEquals(2.777f, Utilities.boundToRange(887.99f, 0f, 2.777f))
        assertEquals(900f, Utilities.boundToRange(887.99f, 900f, 1000f))

        assertEquals(9383667L, Utilities.boundToRange(9383667L, -999L, 9999999L))
        assertEquals(9383668L, Utilities.boundToRange(9383667L, 9383668L, 9999999L))
        assertEquals(42L, Utilities.boundToRange(9383667L, -999L, 42L))

        assertEquals(345, Utilities.boundToRange(345, 2, 500))
        assertEquals(400, Utilities.boundToRange(345, 400, 500))
        assertEquals(300, Utilities.boundToRange(345, 2, 300))

        val random = Random(SEED)
        for (i in 1..300) {
            val value = random.nextFloat()
            val lowerBound = random.nextFloat()
            val higherBound = lowerBound + random.nextFloat()

            assertEquals(
                "Utilities.boundToRange doesn't match Kotlin coerceIn",
                value.coerceIn(lowerBound, higherBound),
                Utilities.boundToRange(value, lowerBound, higherBound)
            )
            assertEquals(
                "Utilities.boundToRange doesn't match Kotlin coerceIn",
                value.toInt().coerceIn(lowerBound.toInt(), higherBound.toInt()),
                Utilities.boundToRange(value.toInt(), lowerBound.toInt(), higherBound.toInt())
            )
            assertEquals(
                "Utilities.boundToRange doesn't match Kotlin coerceIn",
                value.toLong().coerceIn(lowerBound.toLong(), higherBound.toLong()),
                Utilities.boundToRange(value.toLong(), lowerBound.toLong(), higherBound.toLong())
            )
            assertEquals(
                "If the lower bound is higher than lower bound, it should return the lower bound",
                higherBound,
                Utilities.boundToRange(value, higherBound, lowerBound)
            )
        }
    }

    @Test
    fun testTranslateOverlappingView() {
        testConcentricOverlap()
        leftDownCornerOverlap()
        noOverlap()
    }

    /*
        Test Case: Rectangle Contained Within Another Rectangle

           +-------------+  <-- exclusionBounds
           |             |
           |   +-----+   |
           |   |     |   |  <-- targetViewBounds
           |   |     |   |
           |   +-----+   |
           |             |
           +-------------+
    */
    private fun testConcentricOverlap() {
        val targetView = View(ContextWrapper(getApplicationContext()))
        val targetViewBounds = Rect(40, 40, 60, 60)
        val inclusionBounds = Rect(0, 0, 100, 100)
        val exclusionBounds = Rect(30, 30, 70, 70)

        Utilities.translateOverlappingView(
            targetView,
            targetViewBounds,
            inclusionBounds,
            exclusionBounds,
            Utilities.TRANSLATE_RIGHT
        )
        assertEquals(30f, targetView.translationX)
        Utilities.translateOverlappingView(
            targetView,
            targetViewBounds,
            inclusionBounds,
            exclusionBounds,
            Utilities.TRANSLATE_LEFT
        )
        assertEquals(-30f, targetView.translationX)
        Utilities.translateOverlappingView(
            targetView,
            targetViewBounds,
            inclusionBounds,
            exclusionBounds,
            Utilities.TRANSLATE_DOWN
        )
        assertEquals(30f, targetView.translationY)
        Utilities.translateOverlappingView(
            targetView,
            targetViewBounds,
            inclusionBounds,
            exclusionBounds,
            Utilities.TRANSLATE_UP
        )
        assertEquals(-30f, targetView.translationY)
    }

    /*
    Test Case: Non-Overlapping Rectangles

        +-----------------+      <-- targetViewBounds
        |                 |
        |                 |
        +-----------------+

                 +-----------+     <-- exclusionBounds
                 |           |
                 |           |
                 +-----------+
    */
    private fun noOverlap() {
        val targetView = View(ContextWrapper(getApplicationContext()))
        val targetViewBounds = Rect(10, 10, 20, 20)

        val inclusionBounds = Rect(0, 0, 100, 100)
        val exclusionBounds = Rect(30, 30, 40, 40)

        Utilities.translateOverlappingView(
            targetView,
            targetViewBounds,
            inclusionBounds,
            exclusionBounds,
            Utilities.TRANSLATE_RIGHT
        )
        assertEquals(0f, targetView.translationX)
        Utilities.translateOverlappingView(
            targetView,
            targetViewBounds,
            inclusionBounds,
            exclusionBounds,
            Utilities.TRANSLATE_LEFT
        )
        assertEquals(0f, targetView.translationX)
        Utilities.translateOverlappingView(
            targetView,
            targetViewBounds,
            inclusionBounds,
            exclusionBounds,
            Utilities.TRANSLATE_DOWN
        )
        assertEquals(0f, targetView.translationY)
        Utilities.translateOverlappingView(
            targetView,
            targetViewBounds,
            inclusionBounds,
            exclusionBounds,
            Utilities.TRANSLATE_UP
        )
        assertEquals(0f, targetView.translationY)
    }

    /*
    Test Case: Rectangles Overlapping at Corners

       +------------+         <-- exclusionBounds
       |            |
    +-------+       |
    |  |    |       |          <-- targetViewBounds
    |  +------------+
    |       |
    +-------+
    */
    private fun leftDownCornerOverlap() {
        val targetView = View(ContextWrapper(getApplicationContext()))
        val targetViewBounds = Rect(20, 20, 30, 30)

        val inclusionBounds = Rect(0, 0, 100, 100)
        val exclusionBounds = Rect(25, 25, 35, 35)

        Utilities.translateOverlappingView(
            targetView,
            targetViewBounds,
            inclusionBounds,
            exclusionBounds,
            Utilities.TRANSLATE_RIGHT
        )
        assertEquals(15f, targetView.translationX)
        Utilities.translateOverlappingView(
            targetView,
            targetViewBounds,
            inclusionBounds,
            exclusionBounds,
            Utilities.TRANSLATE_LEFT
        )
        assertEquals(-5f, targetView.translationX)
        Utilities.translateOverlappingView(
            targetView,
            targetViewBounds,
            inclusionBounds,
            exclusionBounds,
            Utilities.TRANSLATE_DOWN
        )
        assertEquals(15f, targetView.translationY)
        Utilities.translateOverlappingView(
            targetView,
            targetViewBounds,
            inclusionBounds,
            exclusionBounds,
            Utilities.TRANSLATE_UP
        )
        assertEquals(-5f, targetView.translationY)
    }

    @Test
    fun trim() {
        val expectedString = "Hello World"
        assertEquals(expectedString, Utilities.trim("Hello World   "))
        // Basic trimming
        assertEquals(expectedString, Utilities.trim("   Hello World  "))
        assertEquals(expectedString, Utilities.trim("   Hello World"))

        // Non-breaking whitespace
        assertEquals("Hello World", Utilities.trim("\u00A0\u00A0Hello World\u00A0\u00A0"))

        // Whitespace combinations
        assertEquals(expectedString, Utilities.trim("\t \r\n Hello World \n\r"))
        assertEquals(expectedString, Utilities.trim("\nHello World   "))

        // Null input
        assertEquals("", Utilities.trim(null))

        // Empty String
        assertEquals("", Utilities.trim(""))
    }

    @Test
    fun getProgress() {
        // Basic test
        assertEquals(0.5f, Utilities.getProgress(50f, 0f, 100f), 0.001f)

        // Negative values
        assertEquals(0.5f, Utilities.getProgress(-20f, -50f, 10f), 0.001f)

        // Outside of range
        assertEquals(1.2f, Utilities.getProgress(120f, 0f, 100f), 0.001f)
    }

    @Test
    fun scaleRectFAboutPivot() {
        // Enlarge
        var rectF = RectF(10f, 20f, 50f, 80f)
        Utilities.scaleRectFAboutPivot(rectF, 30f, 50f, 1.5f)
        assertEquals(RectF(0f, 5f, 60f, 95f), rectF)

        // Shrink
        rectF = RectF(10f, 20f, 50f, 80f)
        Utilities.scaleRectFAboutPivot(rectF, 30f, 50f, 0.5f)
        assertEquals(RectF(20f, 35f, 40f, 65f), rectF)

        // No scale
        rectF = RectF(10f, 20f, 50f, 80f)
        Utilities.scaleRectFAboutPivot(rectF, 30f, 50f, 1.0f)
        assertEquals(RectF(10f, 20f, 50f, 80f), rectF)
    }

    @Test
    fun rotateBounds() {
        var rect = Rect(20, 70, 60, 80)
        Utilities.rotateBounds(rect, 100, 100, 0)
        assertEquals(Rect(20, 70, 60, 80), rect)

        rect = Rect(20, 70, 60, 80)
        Utilities.rotateBounds(rect, 100, 100, 1)
        assertEquals(Rect(70, 40, 80, 80), rect)

        rect = Rect(20, 70, 60, 80)
        Utilities.rotateBounds(rect, 100, 100, 2)
        assertEquals(Rect(40, 20, 80, 30), rect)

        rect = Rect(20, 70, 60, 80)
        Utilities.rotateBounds(rect, 100, 100, 3)
        assertEquals(Rect(20, 20, 30, 60), rect)
    }
}