Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.text.method.cts;
     18 
     19 import static org.junit.Assert.assertEquals;
     20 import static org.junit.Assert.assertNotNull;
     21 import static org.junit.Assert.assertSame;
     22 import static org.junit.Assert.assertTrue;
     23 import static org.junit.Assert.fail;
     24 import static org.mockito.Mockito.any;
     25 import static org.mockito.Mockito.anyInt;
     26 import static org.mockito.Mockito.atLeastOnce;
     27 import static org.mockito.Mockito.reset;
     28 import static org.mockito.Mockito.spy;
     29 import static org.mockito.Mockito.verify;
     30 
     31 import android.app.Instrumentation;
     32 import android.app.UiAutomation;
     33 import android.os.ParcelFileDescriptor;
     34 import android.provider.Settings.SettingNotFoundException;
     35 import android.provider.Settings.System;
     36 import android.support.test.InstrumentationRegistry;
     37 import android.support.test.filters.MediumTest;
     38 import android.support.test.rule.ActivityTestRule;
     39 import android.support.test.runner.AndroidJUnit4;
     40 import android.text.method.PasswordTransformationMethod;
     41 import android.util.TypedValue;
     42 import android.view.KeyCharacterMap;
     43 import android.widget.Button;
     44 import android.widget.EditText;
     45 import android.widget.LinearLayout;
     46 import android.widget.LinearLayout.LayoutParams;
     47 
     48 import com.android.compatibility.common.util.CtsKeyEventUtil;
     49 import com.android.compatibility.common.util.PollingCheck;
     50 
     51 import org.junit.After;
     52 import org.junit.Before;
     53 import org.junit.Rule;
     54 import org.junit.Test;
     55 import org.junit.runner.RunWith;
     56 
     57 import java.io.FileInputStream;
     58 import java.io.InputStream;
     59 import java.util.Scanner;
     60 
     61 /**
     62  * Test {@link PasswordTransformationMethod}.
     63  */
     64 @MediumTest
     65 @RunWith(AndroidJUnit4.class)
     66 public class PasswordTransformationMethodTest {
     67     private static final int EDIT_TXT_ID = 1;
     68 
     69     /** original text */
     70     private static final String TEST_CONTENT = "test content";
     71 
     72     /** text after transformation: ************(12 dots) */
     73     private static final String TEST_CONTENT_TRANSFORMED =
     74         "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
     75 
     76     private Instrumentation mInstrumentation;
     77     private CtsActivity mActivity;
     78     private int mPasswordPrefBackUp;
     79     private boolean isPasswordPrefSaved;
     80     private PasswordTransformationMethod mMethod;
     81     private EditText mEditText;
     82     private CharSequence mTransformedText;
     83 
     84     @Rule
     85     public ActivityTestRule<CtsActivity> mActivityRule = new ActivityTestRule<>(CtsActivity.class);
     86 
     87     @Before
     88     public void setup() throws Throwable {
     89         mActivity = mActivityRule.getActivity();
     90         PollingCheck.waitFor(1000, mActivity::hasWindowFocus);
     91         mInstrumentation = InstrumentationRegistry.getInstrumentation();
     92         mMethod = spy(new PasswordTransformationMethod());
     93 
     94         mActivityRule.runOnUiThread(() -> {
     95             EditText editText = new EditTextNoIme(mActivity);
     96             editText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
     97             editText.setId(EDIT_TXT_ID);
     98             editText.setTransformationMethod(mMethod);
     99             Button button = new Button(mActivity);
    100             LinearLayout layout = new LinearLayout(mActivity);
    101             layout.setOrientation(LinearLayout.VERTICAL);
    102             layout.addView(editText, new LayoutParams(LayoutParams.MATCH_PARENT,
    103                     LayoutParams.WRAP_CONTENT));
    104             layout.addView(button, new LayoutParams(LayoutParams.MATCH_PARENT,
    105                     LayoutParams.WRAP_CONTENT));
    106             mActivity.setContentView(layout);
    107             editText.requestFocus();
    108         });
    109         mInstrumentation.waitForIdleSync();
    110 
    111         mEditText = (EditText) mActivity.findViewById(EDIT_TXT_ID);
    112         assertTrue(mEditText.isFocused());
    113 
    114         enableAppOps();
    115         savePasswordPref();
    116         switchShowPassword(true);
    117     }
    118 
    119     @After
    120     public void teardown() {
    121         resumePasswordPref();
    122     }
    123 
    124     private void enableAppOps() {
    125         UiAutomation uiAutomation = mInstrumentation.getUiAutomation();
    126 
    127         StringBuilder cmd = new StringBuilder();
    128         cmd.append("appops set ");
    129         cmd.append(mActivity.getPackageName());
    130         cmd.append(" android:write_settings allow");
    131         uiAutomation.executeShellCommand(cmd.toString());
    132 
    133         StringBuilder query = new StringBuilder();
    134         query.append("appops get ");
    135         query.append(mActivity.getPackageName());
    136         query.append(" android:write_settings");
    137         String queryStr = query.toString();
    138 
    139         String result = "No operations.";
    140         while (result.contains("No operations")) {
    141             ParcelFileDescriptor pfd = uiAutomation.executeShellCommand(queryStr);
    142             InputStream inputStream = new FileInputStream(pfd.getFileDescriptor());
    143             result = convertStreamToString(inputStream);
    144         }
    145     }
    146 
    147     private String convertStreamToString(InputStream is) {
    148         try (Scanner scanner = new Scanner(is).useDelimiter("\\A")) {
    149             return scanner.hasNext() ? scanner.next() : "";
    150         }
    151     }
    152 
    153     @Test
    154     public void testConstructor() {
    155         new PasswordTransformationMethod();
    156     }
    157 
    158     @Test
    159     public void testTextChangedCallBacks() throws Throwable {
    160         mActivityRule.runOnUiThread(() ->
    161             mTransformedText = mMethod.getTransformation(mEditText.getText(), mEditText));
    162 
    163         reset(mMethod);
    164         // 12-key support
    165         KeyCharacterMap keymap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
    166         if (keymap.getKeyboardType() == KeyCharacterMap.NUMERIC) {
    167             // "HELLO" in case of 12-key(NUMERIC) keyboard
    168             CtsKeyEventUtil.sendKeys(mInstrumentation, mEditText,
    169                     "6*4 6*3 7*5 DPAD_RIGHT 7*5 7*6 DPAD_RIGHT");
    170         }
    171         else {
    172             CtsKeyEventUtil.sendKeys(mInstrumentation, mEditText, "H E 2*L O");
    173         }
    174         verify(mMethod, atLeastOnce()).beforeTextChanged(any(), anyInt(), anyInt(), anyInt());
    175         verify(mMethod, atLeastOnce()).onTextChanged(any(), anyInt(), anyInt(), anyInt());
    176         verify(mMethod, atLeastOnce()).afterTextChanged(any());
    177 
    178         reset(mMethod);
    179 
    180         mActivityRule.runOnUiThread(() -> mEditText.append(" "));
    181 
    182         // the appended string will not get transformed immediately
    183         // "***** "
    184         assertEquals("\u2022\u2022\u2022\u2022\u2022 ", mTransformedText.toString());
    185         verify(mMethod, atLeastOnce()).beforeTextChanged(any(), anyInt(), anyInt(), anyInt());
    186         verify(mMethod, atLeastOnce()).onTextChanged(any(), anyInt(), anyInt(), anyInt());
    187         verify(mMethod, atLeastOnce()).afterTextChanged(any());
    188 
    189         // it will get transformed after a while
    190         // "******"
    191         PollingCheck.waitFor(() -> mTransformedText.toString()
    192                 .equals("\u2022\u2022\u2022\u2022\u2022\u2022"));
    193     }
    194 
    195     @Test
    196     public void testGetTransformation() {
    197         PasswordTransformationMethod method = new PasswordTransformationMethod();
    198 
    199         assertEquals(TEST_CONTENT_TRANSFORMED,
    200                 method.getTransformation(TEST_CONTENT, null).toString());
    201 
    202         CharSequence transformed = method.getTransformation(null, mEditText);
    203         assertNotNull(transformed);
    204         try {
    205             transformed.toString();
    206             fail("Should throw NullPointerException if the source is null.");
    207         } catch (NullPointerException e) {
    208             // expected
    209         }
    210     }
    211 
    212     @Test
    213     public void testGetInstance() {
    214         PasswordTransformationMethod method0 = PasswordTransformationMethod.getInstance();
    215         assertNotNull(method0);
    216 
    217         PasswordTransformationMethod method1 = PasswordTransformationMethod.getInstance();
    218         assertNotNull(method1);
    219         assertSame(method0, method1);
    220     }
    221 
    222     private void savePasswordPref() {
    223         try {
    224             mPasswordPrefBackUp = System.getInt(mActivity.getContentResolver(),
    225                     System.TEXT_SHOW_PASSWORD);
    226             isPasswordPrefSaved = true;
    227         } catch (SettingNotFoundException e) {
    228             isPasswordPrefSaved = false;
    229         }
    230     }
    231 
    232     private void resumePasswordPref() {
    233         if (isPasswordPrefSaved) {
    234             System.putInt(mActivity.getContentResolver(), System.TEXT_SHOW_PASSWORD,
    235                     mPasswordPrefBackUp);
    236         }
    237     }
    238 
    239     private void switchShowPassword(boolean on) {
    240         System.putInt(mActivity.getContentResolver(), System.TEXT_SHOW_PASSWORD,
    241                 on ? 1 : 0);
    242     }
    243 }
    244