15c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez/* 25c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez * Copyright (C) 2017 The Android Open Source Project 35c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez * 45c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez * Licensed under the Apache License, Version 2.0 (the "License"); 55c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez * you may not use this file except in compliance with the License. 65c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez * You may obtain a copy of the License at 75c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez * 85c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez * http://www.apache.org/licenses/LICENSE-2.0 95c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez * 105c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez * Unless required by applicable law or agreed to in writing, software 115c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez * distributed under the License is distributed on an "AS IS" BASIS, 125c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez * See the License for the specific language governing permissions and 145c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez * limitations under the License. 155c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez */ 165c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez 175c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perezimport com.android.ide.common.rendering.api.Bridge; 185c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perezimport com.android.ide.common.rendering.api.Result; 195c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perezimport com.android.ide.common.rendering.api.SessionParams; 205c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perezimport com.android.layoutlib.bridge.intensive.RenderResult; 215c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perezimport com.android.layoutlib.bridge.intensive.RenderTestBase; 225c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perezimport com.android.layoutlib.bridge.intensive.setup.ConfigGenerator; 2362413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perezimport com.android.layoutlib.bridge.intensive.setup.LayoutLibTestCallback; 2462413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perezimport com.android.layoutlib.bridge.intensive.setup.LayoutPullParser; 255c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perezimport com.android.layoutlib.bridge.intensive.util.ImageUtils; 265c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perezimport com.android.layoutlib.bridge.remote.client.RemoteBridgeClient; 275c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perezimport com.android.layoutlib.bridge.remote.server.ServerMain; 285c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez 295c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perezimport org.junit.After; 305c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perezimport org.junit.Before; 315c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perezimport org.junit.Test; 325c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez 335c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perezimport java.io.File; 345c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perezimport java.io.IOException; 355c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perezimport java.rmi.NotBoundException; 365c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez 375c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perezimport static org.junit.Assert.assertEquals; 385c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perezimport static org.junit.Assert.assertNotNull; 395c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perezimport static org.junit.Assert.fail; 405c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez 415c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez 425c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perezpublic class RemoteBridgeTest extends RenderTestBase { 435c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez private ServerMain mServerMain; 445c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez private RemoteBridgeClient mClient; 455c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez 465c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez /** 475c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez * Copy of RenderTestBase.renderAndVerify that allows using a different Bridge. TODO: Merge back 485c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez * into RenderTestBase 495c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez */ 505c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez protected static RenderResult renderAndVerify(Bridge bridge, SessionParams params, 515c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez String goldenFileName, long frameTimeNanos) throws ClassNotFoundException { 525c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez RenderResult result = RenderTestBase.render(bridge, params, frameTimeNanos); 535c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez try { 545c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez String goldenImagePath = APP_TEST_DIR + "/golden/" + goldenFileName; 555c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez assertNotNull(result.getImage()); 565c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez ImageUtils.requireSimilar(goldenImagePath, result.getImage()); 575c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez } catch (IOException e) { 585c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez getLogger().error(e, e.getMessage()); 595c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez } 605c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez 615c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez return result; 625c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez } 635c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez 645c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez @Before 6562413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez public void setupServer() throws IOException, NotBoundException, InterruptedException { 66ce1a4634e3b96e7e4d043afa4d5cc8ab23ce92dbDiego Perez mServerMain = ServerMain.forkAndStartServer(ServerMain.REGISTRY_BASE_PORT, 10); 675c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez mClient = RemoteBridgeClient.getRemoteBridge(mServerMain.getPort()); 685c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez 695c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez File data_dir = new File(PLATFORM_DIR, "data"); 705c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez File res = new File(data_dir, "res"); 715c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez File fontLocation = new File(data_dir, "fonts"); 725c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez File buildProp = new File(PLATFORM_DIR, "build.prop"); 735c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez File attrs = new File(res, "values" + File.separator + "attrs.xml"); 745c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez 755c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez mClient.init(ConfigGenerator.loadProperties(buildProp), fontLocation, 765c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez ConfigGenerator.getEnumMap(attrs), getLayoutLog()); 775c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez } 785c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez 795c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez @After 805c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez public void stopServer() { 815c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez mClient.dispose(); 825c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez mServerMain.stop(); 835c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez } 845c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez 855c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez /** 865c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez * Same test as RenderTest#testActivity but using the remote bridge 875c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez */ 885c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez @Test 8962413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez public void testActivity() throws IOException, ClassNotFoundException { 905c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez SessionParams params = createSessionParams("activity.xml", ConfigGenerator.NEXUS_5); 915c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez RenderResult result = renderAndVerify(mClient, params, "activity.png", 250); 925c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez assertEquals(Result.Status.SUCCESS, result.getResult().getStatus()); 935c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez if (result.getResult().getException() != null) { 945c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez result.getResult().getException().printStackTrace(); 955c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez fail("Unexpected exception"); 965c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez } 975c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez } 9862413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez 9962413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez /** 10062413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez * Same test as RenderTest#testActivity but using the remote bridge 10162413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez */ 10262413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez @Test 10362413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez public void testCustomClassLoading() throws ClassNotFoundException { 10462413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez LayoutLibTestCallback layoutLibCallback = 10562413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); 10662413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez layoutLibCallback.initResources(); 10762413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez 10862413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez LayoutPullParser parser = LayoutPullParser.createFromString( 10962413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez "<CustomComponent xmlns:android=\"http://schemas" + 11062413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez ".android.com/apk/res/android\"\n" + 11162413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez " android:layout_width=\"match_parent\"\n" + 11262413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez " android:layout_height=\"match_parent\"\n>" + 11362413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez "</CustomComponent>"); 11462413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez SessionParams params = 11562413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez getSessionParamsBuilder().setParser(parser).setCallback(layoutLibCallback).setTheme( 11662413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez "Theme.NoTitleBar", false).build(); 11762413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez 11862413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez RenderResult result = renderAndVerify(mClient, params, "remote_component_load.png", 250); 11962413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez assertEquals(Result.Status.SUCCESS, result.getResult().getStatus()); 12062413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez if (result.getResult().getException() != null) { 12162413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez result.getResult().getException().printStackTrace(); 12262413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez fail("Unexpected exception"); 12362413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez } 12462413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez 12562413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez parser = LayoutPullParser.createFromString( 12662413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez "<MissingCustomComponent xmlns:android=\"http://schemas" + 12762413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez ".android.com/apk/res/android\"\n" + 12862413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez " android:layout_width=\"match_parent\"\n" + 12962413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez " android:layout_height=\"match_parent\"\n>" + 13062413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez "</MissingCustomComponent>"); 13162413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez params = 13262413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez getSessionParamsBuilder().setParser(parser).setCallback(layoutLibCallback).setTheme( 13362413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez "Theme.NoTitleBar", false).build(); 13462413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez result = renderAndVerify(mClient, params, "remote_component_load_fail.png", 250); 13562413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez assertEquals(Result.Status.SUCCESS, result.getResult().getStatus()); 13662413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez if (result.getResult().getException() != null) { 13762413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez result.getResult().getException().printStackTrace(); 13862413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez fail("Unexpected exception"); 13962413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez } 14062413126b979e60482d6dd7d4ec8ce1412c61da5Diego Perez } 1415c5efc433eb4cc81f59bcfaf28f5e72b38f7a829Diego Perez}