1 /*
2  * Copyright (C) 2024 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.nfc;
18 
19 import static org.mockito.Mockito.mock;
20 import static org.mockito.Mockito.when;
21 
22 import android.content.Context;
23 import android.content.ContextWrapper;
24 import android.content.pm.PackageManager;
25 
26 import androidx.test.ext.junit.runners.AndroidJUnit4;
27 import androidx.test.platform.app.InstrumentationRegistry;
28 
29 import com.android.dx.mockito.inline.extended.ExtendedMockito;
30 import com.android.nfc.cardemulation.AidRoutingManager;
31 import com.android.nfc.cardemulation.RoutingOptionManager;
32 
33 import org.junit.After;
34 import org.junit.Assert;
35 import org.junit.Before;
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 import org.mockito.MockitoSession;
39 import org.mockito.quality.Strictness;
40 
41 import java.util.HashMap;
42 import java.util.Map;
43 
44 @RunWith(AndroidJUnit4.class)
45 public class AidRoutingManagerTest {
46 
47     private static final String TAG = AidRoutingManagerTest.class.getSimpleName();
48     private boolean mNfcSupported;
49     private MockitoSession mStaticMockSession;
50     private AidRoutingManager mAidRoutingManager;
51 
52     @Before
setUp()53     public void setUp() throws Exception {
54         mStaticMockSession = ExtendedMockito.mockitoSession()
55                 .mockStatic(RoutingOptionManager.class)
56                 .mockStatic(NfcService.class)
57                 .mockStatic(NfcStatsLog.class)
58                 .strictness(Strictness.LENIENT)
59                 .startMocking();
60 
61         Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
62         PackageManager pm = context.getPackageManager();
63         if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_ANY)) {
64             mNfcSupported = false;
65             return;
66         }
67         mNfcSupported = true;
68 
69         RoutingOptionManager routingOptionManager = mock(RoutingOptionManager.class);
70         when(RoutingOptionManager.getInstance()).thenReturn(routingOptionManager);
71         InstrumentationRegistry.getInstrumentation().runOnMainSync(
72                 () -> mAidRoutingManager = new AidRoutingManager());
73         Assert.assertNotNull(mAidRoutingManager);
74     }
75 
76     @After
tearDown()77     public void tearDown() throws Exception {
78         mStaticMockSession.finishMocking();
79     }
80 
81     @Test
testCalculateAidRouteSize()82     public void testCalculateAidRouteSize() {
83         if (!mNfcSupported) return;
84 
85         HashMap<String, AidRoutingManager.AidEntry> aidEntryMap = new HashMap<>();
86         int size = mAidRoutingManager.calculateAidRouteSize(aidEntryMap);
87         Assert.assertEquals(0, size);
88         AidRoutingManager.AidEntry aidEntry = mAidRoutingManager.new AidEntry();
89         aidEntryMap.put("test*", aidEntry);
90         size = mAidRoutingManager.calculateAidRouteSize(aidEntryMap);
91         Assert.assertEquals(6, size);
92     }
93 
94     @Test
testOnNfccRoutingTableCleared()95     public void testOnNfccRoutingTableCleared() {
96         if (!mNfcSupported) return;
97 
98         mAidRoutingManager.onNfccRoutingTableCleared();
99         boolean isTableCleared = mAidRoutingManager.isRoutingTableCleared();
100         Assert.assertTrue(isTableCleared);
101     }
102 
103     @Test
testSupportsAidPrefixRouting()104     public void testSupportsAidPrefixRouting() {
105         if (!mNfcSupported) return;
106 
107         boolean isSupportPrefixRouting = mAidRoutingManager.supportsAidPrefixRouting();
108         Assert.assertFalse(isSupportPrefixRouting);
109     }
110 
111     @Test
testSupportsAidSubsetRouting()112     public void testSupportsAidSubsetRouting() {
113         if (!mNfcSupported) return;
114 
115         boolean isSupportSubsetRouting = mAidRoutingManager.supportsAidSubsetRouting();
116         Assert.assertFalse(isSupportSubsetRouting);
117     }
118 
119     @Test
testConfigureRoutingErrorOccurred()120     public void testConfigureRoutingErrorOccurred() {
121         if (!mNfcSupported) return;
122 
123         NfcService nfcService = mock(NfcService.class);
124         when(NfcService.getInstance()).thenReturn(nfcService);
125         when(nfcService.getNciVersion()).thenReturn(NfcService.NCI_VERSION_2_0);
126         HashMap<String, AidRoutingManager.AidEntry> aidEntryMap = new HashMap<>();
127         boolean isConfigureRouting = mAidRoutingManager.configureRouting(aidEntryMap, true);
128         Assert.assertTrue(isConfigureRouting);
129         ExtendedMockito.verify(() -> NfcStatsLog.write(
130                 NfcStatsLog.NFC_ERROR_OCCURRED,
131                 NfcStatsLog.NFC_ERROR_OCCURRED__TYPE__AID_OVERFLOW,
132                 0,
133                 0));
134     }
135 
136     @Test
testConfigureRouting()137     public void testConfigureRouting() {
138         if (!mNfcSupported) return;
139 
140         NfcService nfcService = mock(NfcService.class);
141         when(NfcService.getInstance()).thenReturn(nfcService);
142         when(nfcService.getNciVersion()).thenReturn(NfcService.NCI_VERSION_2_0);
143         HashMap<String, AidRoutingManager.AidEntry> aidEntryMap = new HashMap<>();
144         aidEntryMap.put("aidEntry", mock(AidRoutingManager.AidEntry.class));
145         boolean isConfigureRouting = mAidRoutingManager.configureRouting(aidEntryMap, true);
146         Assert.assertTrue(isConfigureRouting);
147         ExtendedMockito.verify(() -> NfcStatsLog.write(
148                 NfcStatsLog.NFC_ERROR_OCCURRED,
149                 NfcStatsLog.NFC_ERROR_OCCURRED__TYPE__AID_OVERFLOW,
150                 0,
151                 0));
152     }
153 }