blob: ab13f32aaef15f0b469320855ea8efb08dc4caab [file] [log] [blame]
/*
* Copyright (C) 2022 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 android.nfc.tech.cts;
import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertThrows;
import android.nfc.ErrorCodes;
import android.nfc.INfcTag;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.nfc.tech.TagTechnology;
import android.os.Bundle;
import android.os.RemoteException;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.IOException;
public class NdefTest {
private static final int NDEF_MAX_LENGTH = 128;
@Mock
private INfcTag mNfcTagMock;
@Captor
private ArgumentCaptor<NdefMessage> mNdefMessageCaptor;
private NdefMessage mNdefMessage;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
NdefRecord ndefRecord = NdefRecord.createTextRecord("en", "text");
mNdefMessage = new NdefMessage(ndefRecord);
}
@Test
public void testGet_isNdef() {
Ndef ndef = createNdef(1);
assertTrue("Expected to not be <null>", ndef != null);
}
@Test
public void testGet_notNdef() {
Tag tag = new Tag(new byte[]{}, new int[]{TagTechnology.NFC_A}, new Bundle[]{}, 0, 0L,
null);
Ndef ndef = Ndef.get(tag);
assertTrue("Expected: <null> ", ndef == null);
}
@Test
public void testGetCachedNdefMessage() {
Ndef ndef = createNdef(1);
assertEquals(mNdefMessage, ndef.getCachedNdefMessage());
}
@Test
public void testGetType_type1() {
Ndef ndef = createNdef(1);
assertEquals(Ndef.NFC_FORUM_TYPE_1, ndef.getType());
}
@Test
public void testGetType_type2() {
Ndef ndef = createNdef(2);
assertEquals(Ndef.NFC_FORUM_TYPE_2, ndef.getType());
}
@Test
public void testGetType_type3() {
Ndef ndef = createNdef(3);
assertEquals(Ndef.NFC_FORUM_TYPE_3, ndef.getType());
}
@Test
public void testGetType_type4() {
Ndef ndef = createNdef(4);
assertEquals(Ndef.NFC_FORUM_TYPE_4, ndef.getType());
}
@Test
public void testGetType_mifareClassic() {
Ndef ndef = createNdef(101);
assertEquals(Ndef.MIFARE_CLASSIC, ndef.getType());
}
@Test
public void testGetType_iCodeSLI() {
Ndef ndef = createNdef(102);
assertEquals(Ndef.ICODE_SLI, ndef.getType());
}
@Test
public void testGetType_unknown() {
Ndef ndef = createNdef(-1);
assertEquals(Ndef.UNKNOWN, ndef.getType());
}
@Test
public void testGetMaxLength() {
Ndef ndef = createNdef(1);
assertEquals(NDEF_MAX_LENGTH, ndef.getMaxSize());
}
@Test
public void testIsWritable() {
Ndef ndef = createNdef(1);
assertEquals(true, ndef.isWritable());
}
@Test
public void testGetNdefMessage() throws Exception {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.isNdef(anyInt())).thenReturn(true);
when(mNfcTagMock.ndefRead(anyInt())).thenReturn(mNdefMessage);
when(mNfcTagMock.isPresent(anyInt())).thenReturn(true);
assertEquals(mNdefMessage, ndef.getNdefMessage());
}
@Test
public void testGetNdefMessage_noTagService() throws Exception {
Ndef ndef = createNdefNoTagService();
assertThrows(() -> ndef.getNdefMessage());
}
@Test
public void testGetNdefMessage_notNdef() throws Exception {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.isNdef(anyInt())).thenReturn(true);
when(mNfcTagMock.isPresent(anyInt())).thenReturn(true);
assertEquals(null, ndef.getNdefMessage());
}
@Test
public void testGetNdefMessage_notNdefNotPresent() throws Exception {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.isNdef(anyInt())).thenReturn(true);
when(mNfcTagMock.isPresent(anyInt())).thenReturn(false);
assertThrows(() -> ndef.getNdefMessage());
}
@Test
public void testGetNdefMessage_noTagOnRead() throws Exception {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.isNdef(anyInt())).thenReturn(true);
when(mNfcTagMock.ndefRead(anyInt())).thenReturn(null);
when(mNfcTagMock.isPresent(anyInt())).thenReturn(false);
assertThrows(() -> ndef.getNdefMessage());
}
@Test
public void testWriteNdefMessage() throws Exception {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.isNdef(anyInt())).thenReturn(true);
when(mNfcTagMock.ndefWrite(anyInt(), any())).thenReturn(ErrorCodes.SUCCESS);
ndef.writeNdefMessage(mNdefMessage);
verify(mNfcTagMock, times(1)).ndefWrite(anyInt(), mNdefMessageCaptor.capture());
assertEquals(mNdefMessage, mNdefMessageCaptor.getValue());
}
@Test
public void testWriteNdefMessage_noTagService() throws Exception {
Ndef ndef = createNdefNoTagService();
assertThrows(() -> ndef.writeNdefMessage(mNdefMessage));
}
@Test
public void testWriteNdefMessage_notNdef() throws Exception {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.isNdef(anyInt())).thenReturn(false);
assertThrows(() -> ndef.writeNdefMessage(mNdefMessage));
}
@Test
public void testWriteNdefMessage_ioError() throws Exception {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.isNdef(anyInt())).thenReturn(true);
when(mNfcTagMock.ndefWrite(anyInt(), any())).thenReturn(ErrorCodes.ERROR_IO);
assertThrows(() -> ndef.writeNdefMessage(mNdefMessage));
}
@Test
public void testWriteNdefMessage_formatError() throws Exception {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.isNdef(anyInt())).thenReturn(true);
when(mNfcTagMock.ndefWrite(anyInt(), any())).thenReturn(ErrorCodes.ERROR_INVALID_PARAM);
assertThrows(() -> ndef.writeNdefMessage(mNdefMessage));
}
@Test
public void testWriteNdefMessage_unknownError() throws Exception {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.isNdef(anyInt())).thenReturn(true);
when(mNfcTagMock.ndefWrite(anyInt(), any())).thenReturn(1);
assertThrows(() -> ndef.writeNdefMessage(mNdefMessage));
}
@Test
public void testCanMakeReadOnly() throws RemoteException, IOException {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.canMakeReadOnly(anyInt())).thenReturn(true);
assertEquals(true, ndef.canMakeReadOnly());
}
@Test
public void testCanMakeReadOnly_noTagService() throws RemoteException, IOException {
Ndef ndef = createNdefNoTagService();
assertEquals(false, ndef.canMakeReadOnly());
}
@Test
public void testCanMakeReadOnly_serviceDead() throws RemoteException, IOException {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.canMakeReadOnly(anyInt())).thenThrow(new RemoteException());
assertEquals(false, ndef.canMakeReadOnly());
}
@Test
public void testMakeReadOnly() throws RemoteException, IOException {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.isNdef(anyInt())).thenReturn(true);
when(mNfcTagMock.ndefMakeReadOnly(anyInt())).thenReturn(ErrorCodes.SUCCESS);
assertEquals(true, ndef.makeReadOnly());
}
@Test
public void testMakeReadOnly_noTagService() throws RemoteException, IOException {
Ndef ndef = createNdefNoTagService();
assertEquals(false, ndef.makeReadOnly());
}
@Test
public void testMakeReadOnly_notNdef() throws RemoteException, IOException {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.isNdef(anyInt())).thenReturn(false);
assertThrows(() -> ndef.makeReadOnly());
}
@Test
public void testMakeReadOnly_serviceDead() throws RemoteException, IOException {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.isNdef(anyInt())).thenReturn(true);
when(mNfcTagMock.ndefMakeReadOnly(anyInt())).thenThrow(new RemoteException());
assertEquals(false, ndef.makeReadOnly());
}
@Test
public void testMakeReadOnly_ioError() throws RemoteException, IOException {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.isNdef(anyInt())).thenReturn(true);
when(mNfcTagMock.ndefMakeReadOnly(anyInt())).thenReturn(ErrorCodes.ERROR_IO);
assertThrows(() -> ndef.makeReadOnly());
}
@Test
public void testMakeReadOnly_formatError() throws RemoteException, IOException {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.isNdef(anyInt())).thenReturn(true);
when(mNfcTagMock.ndefMakeReadOnly(anyInt())).thenReturn(ErrorCodes.ERROR_INVALID_PARAM);
assertEquals(false, ndef.makeReadOnly());
}
@Test
public void testMakeReadOnly_unknownError() throws RemoteException, IOException {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.isNdef(anyInt())).thenReturn(true);
when(mNfcTagMock.ndefMakeReadOnly(anyInt())).thenReturn(1);
assertThrows(() -> ndef.makeReadOnly());
}
@Test
public void testGetTag() {
Bundle extras = new Bundle();
extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, NDEF_MAX_LENGTH);
extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, 2);
extras.putParcelable(Ndef.EXTRA_NDEF_MSG, mNdefMessage);
extras.putInt(Ndef.EXTRA_NDEF_TYPE, 1);
Tag tag = new Tag(new byte[]{0x01, 0x02, 0x03, 0x04}, new int[]{TagTechnology.NDEF},
new Bundle[]{extras}, 0, 0L, mNfcTagMock);
Ndef ndef = Ndef.get(tag);
assertEquals(tag, ndef.getTag());
}
@Test
public void testIsConnected_isConnected() throws RemoteException, IOException {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.isPresent(anyInt())).thenReturn(true);
assertEquals(true, ndef.isConnected());
}
@Test
public void testIsConnected_notConnected() throws RemoteException, IOException {
Ndef ndef = createNdef(1);
when(mNfcTagMock.isPresent(anyInt())).thenReturn(false);
assertEquals(false, ndef.isConnected());
}
@Test
public void testIsConnected_serviceDead() throws RemoteException, IOException {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.isPresent(anyInt())).thenThrow(new RemoteException());
assertEquals(false, ndef.isConnected());
}
@Test
public void testReconnect() throws RemoteException, IOException {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.reconnect(anyInt())).thenReturn(ErrorCodes.SUCCESS);
ndef.reconnect();
verify(mNfcTagMock, times(1)).reconnect(anyInt());
}
@Test
public void testReconnect_notConnected() throws RemoteException, IOException {
Ndef ndef = createNdef(1);
assertThrows(() -> ndef.reconnect());
}
@Test
public void testReconnect_failReconnect() throws RemoteException, IOException {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.reconnect(anyInt())).thenReturn(ErrorCodes.ERROR_CONNECT);
assertThrows(() -> ndef.reconnect());
}
@Test
public void testReconnect_remoteException() throws RemoteException, IOException {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.reconnect(anyInt())).thenThrow(new RemoteException());
assertThrows(() -> ndef.reconnect());
}
@Test
public void testClose() throws RemoteException, IOException {
Ndef ndef = createConnectedNdef();
when(mNfcTagMock.reconnect(anyInt())).thenReturn(ErrorCodes.SUCCESS);
when(mNfcTagMock.isPresent(anyInt())).thenReturn(true);
ndef.close();
assertEquals(false, ndef.isConnected());
}
private Ndef createConnectedNdef() throws RemoteException, IOException {
Ndef ndef = createNdef(1);
when(mNfcTagMock.isTagUpToDate(anyLong())).thenReturn(true);
when(mNfcTagMock.connect(anyInt(), anyInt())).thenReturn(ErrorCodes.SUCCESS);
ndef.connect();
return ndef;
}
private Ndef createNdef(int type) {
Bundle extras = new Bundle();
extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, NDEF_MAX_LENGTH);
extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, 2);
extras.putParcelable(Ndef.EXTRA_NDEF_MSG, mNdefMessage);
extras.putInt(Ndef.EXTRA_NDEF_TYPE, type);
Tag tag = new Tag(new byte[]{0x01, 0x02, 0x03, 0x04}, new int[]{TagTechnology.NDEF},
new Bundle[]{extras}, 0, 0L, mNfcTagMock);
return Ndef.get(tag);
}
private Ndef createNdefNoTagService() {
Bundle extras = new Bundle();
extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, NDEF_MAX_LENGTH);
extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, 2);
extras.putParcelable(Ndef.EXTRA_NDEF_MSG, mNdefMessage);
extras.putInt(Ndef.EXTRA_NDEF_TYPE, 1);
Tag tag = new Tag(new byte[]{0x01, 0x02, 0x03, 0x04}, new int[]{TagTechnology.NDEF},
new Bundle[]{extras}, 0, 0L, null);
tag.setConnectedTechnology(TagTechnology.NDEF);
return Ndef.get(tag);
}
}