• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.backup.testing;
18 
19 import static com.android.server.backup.testing.TestUtils.uncheck;
20 
21 import static org.junit.Assert.fail;
22 import static org.mockito.ArgumentMatchers.any;
23 import static org.mockito.ArgumentMatchers.eq;
24 import static org.mockito.Mockito.mock;
25 import static org.mockito.Mockito.when;
26 
27 import static java.util.stream.Collectors.toList;
28 
29 import android.annotation.IntDef;
30 import android.annotation.Nullable;
31 import android.content.ComponentName;
32 import android.content.Intent;
33 import android.content.pm.ResolveInfo;
34 import android.content.pm.ServiceInfo;
35 import android.os.RemoteException;
36 
37 import com.android.server.backup.TransportManager;
38 import com.android.server.backup.transport.BackupTransportClient;
39 import com.android.server.backup.transport.TransportConnection;
40 import com.android.server.backup.transport.TransportNotAvailableException;
41 import com.android.server.backup.transport.TransportNotRegisteredException;
42 
43 import org.robolectric.shadows.ShadowPackageManager;
44 
45 import java.lang.annotation.Retention;
46 import java.lang.annotation.RetentionPolicy;
47 import java.util.List;
48 import java.util.stream.Stream;
49 
50 public class TransportTestUtils {
51     /**
52      * Differently from {@link #setUpTransports(TransportManager, TransportData...)}, which
53      * configures {@link TransportManager}, this is meant to mock the environment for a real
54      * TransportManager.
55      */
setUpTransportsForTransportManager( ShadowPackageManager shadowPackageManager, TransportData... transports)56     public static void setUpTransportsForTransportManager(
57             ShadowPackageManager shadowPackageManager, TransportData... transports)
58             throws Exception {
59         for (TransportData transport : transports) {
60             if (transport.transportStatus == TransportStatus.UNREGISTERED) {
61                 continue;
62             }
63             ComponentName transportComponent = transport.getTransportComponent();
64             String packageName = transportComponent.getPackageName();
65             ResolveInfo resolveInfo = resolveInfo(transportComponent);
66             shadowPackageManager.addResolveInfoForIntent(transportIntent(), resolveInfo);
67             shadowPackageManager.addResolveInfoForIntent(
68                     transportIntent().setPackage(packageName), resolveInfo);
69         }
70     }
71 
transportIntent()72     private static Intent transportIntent() {
73         return new Intent(TransportManager.SERVICE_ACTION_TRANSPORT_HOST);
74     }
75 
resolveInfo(ComponentName transportComponent)76     private static ResolveInfo resolveInfo(ComponentName transportComponent) {
77         ResolveInfo resolveInfo = new ResolveInfo();
78         resolveInfo.serviceInfo = new ServiceInfo();
79         resolveInfo.serviceInfo.packageName = transportComponent.getPackageName();
80         resolveInfo.serviceInfo.name = transportComponent.getClassName();
81         return resolveInfo;
82     }
83 
84     /** {@code transportName} has to be in the {@link ComponentName} format (with '/') */
setUpCurrentTransport( TransportManager transportManager, TransportData transport)85     public static TransportMock setUpCurrentTransport(
86             TransportManager transportManager, TransportData transport) throws Exception {
87         TransportMock transportMock = setUpTransport(transportManager, transport);
88         int status = transport.transportStatus;
89         when(transportManager.getCurrentTransportName()).thenReturn(transport.transportName);
90         if (status == TransportStatus.REGISTERED_AVAILABLE
91                 || status == TransportStatus.REGISTERED_UNAVAILABLE) {
92             // Transport registered
93             when(transportManager.getCurrentTransportClient(any()))
94                     .thenReturn(transportMock.mTransportConnection);
95             when(transportManager.getCurrentTransportClientOrThrow(any()))
96                     .thenReturn(transportMock.mTransportConnection);
97         } else {
98             // Transport not registered
99             when(transportManager.getCurrentTransportClient(any())).thenReturn(null);
100             when(transportManager.getCurrentTransportClientOrThrow(any()))
101                     .thenThrow(TransportNotRegisteredException.class);
102         }
103         return transportMock;
104     }
105 
106     /** @see #setUpTransport(TransportManager, TransportData) */
setUpTransports( TransportManager transportManager, TransportData... transports)107     public static List<TransportMock> setUpTransports(
108             TransportManager transportManager, TransportData... transports) throws Exception {
109         return Stream.of(transports)
110                 .map(transport -> uncheck(() -> setUpTransport(transportManager, transport)))
111                 .collect(toList());
112     }
113 
setUpTransport( TransportManager transportManager, TransportData transport)114     public static TransportMock setUpTransport(
115             TransportManager transportManager, TransportData transport) throws Exception {
116         int status = transport.transportStatus;
117         String transportName = transport.transportName;
118         ComponentName transportComponent = transport.getTransportComponent();
119         String transportDirName = transport.transportDirName;
120 
121         TransportMock transportMock = mockTransport(transport);
122         if (status == TransportStatus.REGISTERED_AVAILABLE
123                 || status == TransportStatus.REGISTERED_UNAVAILABLE) {
124             // Transport registered
125             when(transportManager.getTransportClient(eq(transportName), any()))
126                     .thenReturn(transportMock.mTransportConnection);
127             when(transportManager.getTransportClientOrThrow(eq(transportName), any()))
128                     .thenReturn(transportMock.mTransportConnection);
129             when(transportManager.getTransportName(transportComponent)).thenReturn(transportName);
130             when(transportManager.getTransportDirName(eq(transportName)))
131                     .thenReturn(transportDirName);
132             when(transportManager.getTransportDirName(eq(transportComponent)))
133                     .thenReturn(transportDirName);
134             when(transportManager.isTransportRegistered(eq(transportName))).thenReturn(true);
135             // TODO: Mock rest of description methods
136         } else {
137             // Transport not registered
138             when(transportManager.getTransportClient(eq(transportName), any())).thenReturn(null);
139             when(transportManager.getTransportClientOrThrow(eq(transportName), any()))
140                     .thenThrow(TransportNotRegisteredException.class);
141             when(transportManager.getTransportName(transportComponent))
142                     .thenThrow(TransportNotRegisteredException.class);
143             when(transportManager.getTransportDirName(eq(transportName)))
144                     .thenThrow(TransportNotRegisteredException.class);
145             when(transportManager.getTransportDirName(eq(transportComponent)))
146                     .thenThrow(TransportNotRegisteredException.class);
147             when(transportManager.isTransportRegistered(eq(transportName))).thenReturn(false);
148         }
149         return transportMock;
150     }
151 
mockTransport(TransportData transport)152     public static TransportMock mockTransport(TransportData transport) throws Exception {
153         final TransportConnection transportConnectionMock;
154         int status = transport.transportStatus;
155         ComponentName transportComponent = transport.getTransportComponent();
156         if (status == TransportStatus.REGISTERED_AVAILABLE
157                 || status == TransportStatus.REGISTERED_UNAVAILABLE) {
158             // Transport registered
159             transportConnectionMock = mock(TransportConnection.class);
160             when(transportConnectionMock.getTransportComponent()).thenReturn(transportComponent);
161             if (status == TransportStatus.REGISTERED_AVAILABLE) {
162                 // Transport registered and available
163                 BackupTransportClient transportMock = mockTransportBinder(transport);
164                 when(transportConnectionMock.connectOrThrow(any())).thenReturn(transportMock);
165                 when(transportConnectionMock.connect(any())).thenReturn(transportMock);
166 
167                 return new TransportMock(transport, transportConnectionMock, transportMock);
168             } else {
169                 // Transport registered but unavailable
170                 when(transportConnectionMock.connectOrThrow(any()))
171                         .thenThrow(TransportNotAvailableException.class);
172                 when(transportConnectionMock.connect(any())).thenReturn(null);
173 
174                 return new TransportMock(transport, transportConnectionMock, null);
175             }
176         } else {
177             // Transport not registered
178             return new TransportMock(transport, null, null);
179         }
180     }
181 
mockTransportBinder(TransportData transport)182     private static BackupTransportClient mockTransportBinder(TransportData transport)
183             throws Exception {
184         BackupTransportClient transportBinder = mock(BackupTransportClient.class);
185         try {
186             when(transportBinder.name()).thenReturn(transport.transportName);
187             when(transportBinder.transportDirName()).thenReturn(transport.transportDirName);
188             when(transportBinder.configurationIntent()).thenReturn(transport.configurationIntent);
189             when(transportBinder.currentDestinationString())
190                     .thenReturn(transport.currentDestinationString);
191             when(transportBinder.dataManagementIntent()).thenReturn(transport.dataManagementIntent);
192             when(transportBinder.dataManagementIntentLabel())
193                     .thenReturn(transport.dataManagementLabel);
194         } catch (RemoteException e) {
195             fail("RemoteException?");
196         }
197         return transportBinder;
198     }
199 
200     public static class TransportMock {
201         public final TransportData transportData;
202         @Nullable public final TransportConnection mTransportConnection;
203         @Nullable public final BackupTransportClient transport;
204 
TransportMock( TransportData transportData, @Nullable TransportConnection transportConnection, @Nullable BackupTransportClient transport)205         private TransportMock(
206                 TransportData transportData,
207                 @Nullable TransportConnection transportConnection,
208                 @Nullable BackupTransportClient transport) {
209             this.transportData = transportData;
210             this.mTransportConnection = transportConnection;
211             this.transport = transport;
212         }
213     }
214 
215     @IntDef({
216         TransportStatus.REGISTERED_AVAILABLE,
217         TransportStatus.REGISTERED_UNAVAILABLE,
218         TransportStatus.UNREGISTERED
219     })
220     @Retention(RetentionPolicy.SOURCE)
221     public @interface TransportStatus {
222         int REGISTERED_AVAILABLE = 0;
223         int REGISTERED_UNAVAILABLE = 1;
224         int UNREGISTERED = 2;
225     }
226 
TransportTestUtils()227     private TransportTestUtils() {}
228 }
229