1 /* 2 * Copyright 2022 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 com.android.server.bluetooth; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assert.assertThrows; 22 import static org.mockito.ArgumentMatchers.anyBoolean; 23 import static org.mockito.Mockito.any; 24 import static org.mockito.Mockito.doReturn; 25 import static org.mockito.Mockito.eq; 26 import static org.mockito.Mockito.mock; 27 import static org.mockito.Mockito.spy; 28 import static org.mockito.Mockito.verify; 29 import static org.mockito.Mockito.verifyNoMoreInteractions; 30 import static org.mockito.Mockito.when; 31 32 import android.bluetooth.BluetoothAdapter; 33 import android.os.Binder; 34 import android.os.RemoteException; 35 36 import androidx.test.filters.SmallTest; 37 import androidx.test.runner.AndroidJUnit4; 38 39 import com.android.server.bluetooth.BluetoothShellCommand.BluetoothCommand; 40 41 import com.google.common.truth.Expect; 42 43 import org.junit.After; 44 import org.junit.Before; 45 import org.junit.Rule; 46 import org.junit.Test; 47 import org.junit.runner.RunWith; 48 import org.mockito.Mock; 49 import org.mockito.MockitoAnnotations; 50 51 import java.io.FileDescriptor; 52 import java.io.PrintWriter; 53 54 @SmallTest 55 @RunWith(AndroidJUnit4.class) 56 public class BluetoothShellCommandTest { 57 @Rule public final Expect expect = Expect.create(); 58 59 @Mock BluetoothManagerService mManagerService; 60 61 @Mock BluetoothServiceBinder mBinder; 62 63 BluetoothShellCommand mShellCommand; 64 65 @Before setUp()66 public void setUp() throws Exception { 67 MockitoAnnotations.initMocks(this); 68 doReturn(mBinder).when(mManagerService).getBinder(); 69 70 mShellCommand = new BluetoothShellCommand(mManagerService); 71 mShellCommand.init( 72 mock(Binder.class), 73 mock(FileDescriptor.class), 74 mock(FileDescriptor.class), 75 mock(FileDescriptor.class), 76 new String[0], 77 -1); 78 } 79 80 @After tearDown()81 public void tearDown() { 82 verifyNoMoreInteractions(mBinder); 83 // verifyNoMoreInteractions(mManagerService); // TODO(b/280518177): Apply after cleanup 84 } 85 86 @Test enableCommand()87 public void enableCommand() throws Exception { 88 BluetoothCommand enableCmd = mShellCommand.new Enable(); 89 String cmdName = "enable"; 90 91 assertThat(enableCmd.getName()).isEqualTo(cmdName); 92 assertThat(enableCmd.isMatch(cmdName)).isTrue(); 93 assertThat(enableCmd.isPrivileged()).isFalse(); 94 when(mBinder.enable(any())).thenReturn(true); 95 assertThat(enableCmd.exec(cmdName)).isEqualTo(0); 96 verify(mBinder).enable(any()); 97 } 98 99 @Test disableCommand()100 public void disableCommand() throws Exception { 101 BluetoothCommand disableCmd = mShellCommand.new Disable(); 102 String cmdName = "disable"; 103 104 assertThat(disableCmd.getName()).isEqualTo(cmdName); 105 assertThat(disableCmd.isMatch(cmdName)).isTrue(); 106 assertThat(disableCmd.isPrivileged()).isFalse(); 107 when(mBinder.disable(any(), anyBoolean())).thenReturn(true); 108 assertThat(disableCmd.exec(cmdName)).isEqualTo(0); 109 verify(mBinder).disable(any(), anyBoolean()); 110 } 111 112 @Test waitForStateCommand()113 public void waitForStateCommand() throws Exception { 114 BluetoothCommand waitCmd = mShellCommand.new WaitForAdapterState(); 115 116 expect.that(waitCmd.getName()).isEqualTo("wait-for-state"); 117 String[] validCmd = { 118 "wait-for-state:STATE_OFF", "wait-for-state:STATE_ON", 119 }; 120 for (String m : validCmd) { 121 expect.that(waitCmd.isMatch(m)).isTrue(); 122 } 123 String[] falseCmd = { 124 "wait-for-stateSTATE_ON", "wait-for-foo:STATE_ON", 125 }; 126 for (String m : falseCmd) { 127 expect.that(waitCmd.isMatch(m)).isFalse(); 128 } 129 String[] throwCmd = { 130 "wait-for-state:STATE_BLE_TURNING_ON", 131 "wait-for-state:STATE_ON:STATE_OFF", 132 "wait-for-state::STATE_ON", 133 "wait-for-state:STATE_ON:", 134 }; 135 for (String m : throwCmd) { 136 assertThrows(m, IllegalArgumentException.class, () -> waitCmd.isMatch(m)); 137 } 138 139 expect.that(waitCmd.isPrivileged()).isFalse(); 140 when(mManagerService.waitForManagerState(eq(BluetoothAdapter.STATE_OFF))).thenReturn(true); 141 142 expect.that(waitCmd.exec(validCmd[0])).isEqualTo(0); 143 } 144 145 @Test onCommand_withNullString_callsOnHelp()146 public void onCommand_withNullString_callsOnHelp() { 147 BluetoothShellCommand command = spy(mShellCommand); 148 149 command.onCommand(null); 150 151 verify(command).onHelp(); 152 } 153 154 @Test onCommand_withEnableString_callsEnableCommand()155 public void onCommand_withEnableString_callsEnableCommand() throws Exception { 156 BluetoothCommand enableCmd = spy(mShellCommand.new Enable()); 157 mShellCommand.mBluetoothCommands[0] = enableCmd; 158 159 mShellCommand.onCommand("enable"); 160 161 verify(enableCmd).exec(eq("enable")); 162 verify(mBinder).enable(any()); 163 } 164 165 static class TestPrivilegedCmd extends BluetoothCommand { TestPrivilegedCmd()166 TestPrivilegedCmd() { 167 super(true, TestPrivilegedCmd.class.getSimpleName()); 168 } 169 170 @Override exec(String cmd)171 int exec(String cmd) throws RemoteException { 172 return 0; 173 } 174 175 @Override onHelp(PrintWriter pw)176 public void onHelp(PrintWriter pw) {} 177 } 178 179 @Test onCommand_withPrivilegedCommandName_throwsSecurityException()180 public void onCommand_withPrivilegedCommandName_throwsSecurityException() { 181 mShellCommand.mBluetoothCommands[0] = new TestPrivilegedCmd(); 182 183 assertThrows( 184 SecurityException.class, 185 () -> mShellCommand.onCommand(TestPrivilegedCmd.class.getSimpleName())); 186 } 187 } 188