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