| /* |
| * Copyright (C) 2017 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. |
| */ |
| |
| import com.android.ide.common.rendering.api.Bridge; |
| import com.android.ide.common.rendering.api.Result; |
| import com.android.ide.common.rendering.api.SessionParams; |
| import com.android.layoutlib.bridge.intensive.RenderResult; |
| import com.android.layoutlib.bridge.intensive.RenderTestBase; |
| import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator; |
| import com.android.layoutlib.bridge.intensive.setup.LayoutLibTestCallback; |
| import com.android.layoutlib.bridge.intensive.setup.LayoutPullParser; |
| import com.android.layoutlib.bridge.intensive.util.ImageUtils; |
| import com.android.layoutlib.bridge.remote.client.RemoteBridgeClient; |
| import com.android.layoutlib.bridge.remote.server.ServerMain; |
| |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.rmi.NotBoundException; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.fail; |
| |
| |
| public class RemoteBridgeTest extends RenderTestBase { |
| private ServerMain mServerMain; |
| private RemoteBridgeClient mClient; |
| |
| /** |
| * Copy of RenderTestBase.renderAndVerify that allows using a different Bridge. TODO: Merge back |
| * into RenderTestBase |
| */ |
| protected static RenderResult renderAndVerify(Bridge bridge, SessionParams params, |
| String goldenFileName, long frameTimeNanos) throws ClassNotFoundException { |
| RenderResult result = RenderTestBase.render(bridge, params, frameTimeNanos); |
| try { |
| String goldenImagePath = APP_TEST_DIR + "/golden/" + goldenFileName; |
| assertNotNull(result.getImage()); |
| ImageUtils.requireSimilar(goldenImagePath, result.getImage()); |
| } catch (IOException e) { |
| getLogger().error(e, e.getMessage()); |
| } |
| |
| return result; |
| } |
| |
| @Before |
| public void setupServer() throws IOException, NotBoundException, InterruptedException { |
| long startTime = System.currentTimeMillis(); |
| mServerMain = ServerMain.forkAndStartServer(ServerMain.REGISTRY_BASE_PORT, 10); |
| mClient = RemoteBridgeClient.getRemoteBridge(mServerMain.getPort()); |
| System.out.printf("Server started in %dms\n", System.currentTimeMillis() - startTime); |
| startTime = System.currentTimeMillis(); |
| |
| File data_dir = new File(PLATFORM_DIR, "data"); |
| File res = new File(data_dir, "res"); |
| File fontLocation = new File(data_dir, "fonts"); |
| File buildProp = new File(PLATFORM_DIR, "build.prop"); |
| File attrs = new File(res, "values" + File.separator + "attrs.xml"); |
| |
| mClient.init(ConfigGenerator.loadProperties(buildProp), fontLocation, null, null, |
| ConfigGenerator.getEnumMap(attrs), getLayoutLog()); |
| System.out.printf("Remote client init took %dms\n", |
| System.currentTimeMillis() - startTime); |
| } |
| |
| @After |
| public void stopServer() { |
| mClient.dispose(); |
| mServerMain.stop(); |
| } |
| |
| /** |
| * Same test as RenderTest#testActivity but using the remote bridge |
| */ |
| @Test |
| public void testActivity() throws IOException, ClassNotFoundException { |
| SessionParams params = createSessionParams("activity.xml", ConfigGenerator.NEXUS_5); |
| RenderResult result = renderAndVerify(mClient, params, "activity.png", 250); |
| assertEquals(Result.Status.SUCCESS, result.getResult().getStatus()); |
| if (result.getResult().getException() != null) { |
| result.getResult().getException().printStackTrace(); |
| fail("Unexpected exception"); |
| } |
| } |
| |
| /** |
| * Same test as RenderTest#testActivity but using the remote bridge |
| */ |
| @Test |
| public void testCustomClassLoading() throws ClassNotFoundException { |
| LayoutLibTestCallback layoutLibCallback = |
| new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); |
| layoutLibCallback.initResources(); |
| |
| LayoutPullParser parser = LayoutPullParser.createFromString( |
| "<CustomComponent xmlns:android=\"http://schemas" + |
| ".android.com/apk/res/android\"\n" + |
| " android:layout_width=\"match_parent\"\n" + |
| " android:layout_height=\"match_parent\"\n>" + |
| "</CustomComponent>"); |
| SessionParams params = |
| getSessionParamsBuilder().setParser(parser).setCallback(layoutLibCallback).setTheme( |
| "Theme.NoTitleBar", false).build(); |
| |
| RenderResult result = renderAndVerify(mClient, params, "remote_component_load.png", 250); |
| assertEquals(Result.Status.SUCCESS, result.getResult().getStatus()); |
| if (result.getResult().getException() != null) { |
| result.getResult().getException().printStackTrace(); |
| fail("Unexpected exception"); |
| } |
| |
| parser = LayoutPullParser.createFromString( |
| "<MissingCustomComponent xmlns:android=\"http://schemas" + |
| ".android.com/apk/res/android\"\n" + |
| " android:layout_width=\"match_parent\"\n" + |
| " android:layout_height=\"match_parent\"\n>" + |
| "</MissingCustomComponent>"); |
| params = |
| getSessionParamsBuilder().setParser(parser).setCallback(layoutLibCallback).setTheme( |
| "Theme.NoTitleBar", false).build(); |
| result = renderAndVerify(mClient, params, "remote_component_load_fail.png", 250); |
| assertEquals(Result.Status.SUCCESS, result.getResult().getStatus()); |
| if (result.getResult().getException() != null) { |
| result.getResult().getException().printStackTrace(); |
| fail("Unexpected exception"); |
| } |
| } |
| } |