1 /* 2 * Copyright (C) 2019 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.protolog.tool 18 19 import org.junit.Assert 20 import org.junit.Assert.assertTrue 21 import org.junit.Test 22 import java.io.ByteArrayInputStream 23 import java.io.ByteArrayOutputStream 24 import java.io.File 25 import java.io.FileNotFoundException 26 import java.io.OutputStream 27 import java.util.jar.JarInputStream 28 29 class EndToEndTest { 30 31 @Test 32 fun e2e_transform() { 33 val output = run( 34 src = "frameworks/base/org/example/Example.java" to """ 35 package org.example; 36 import com.android.internal.protolog.common.ProtoLog; 37 import static com.android.internal.protolog.ProtoLogGroup.GROUP; 38 39 class Example { 40 void method() { 41 String argString = "hello"; 42 int argInt = 123; 43 ProtoLog.d(GROUP, "Example: %s %d", argString, argInt); 44 } 45 } 46 """.trimIndent(), 47 logGroup = LogGroup("GROUP", true, false, "TAG_GROUP"), 48 commandOptions = CommandOptions(arrayOf("transform-protolog-calls", 49 "--protolog-class", "com.android.internal.protolog.common.ProtoLog", 50 "--protolog-impl-class", "com.android.internal.protolog.ProtoLogImpl", 51 "--protolog-cache-class", 52 "com.android.server.wm.ProtoLogCache", 53 "--loggroups-class", "com.android.internal.protolog.ProtoLogGroup", 54 "--loggroups-jar", "not_required.jar", 55 "--output-srcjar", "out.srcjar", 56 "frameworks/base/org/example/Example.java")) 57 ) 58 val outSrcJar = assertLoadSrcJar(output, "out.srcjar") 59 assertTrue(" 2066303299," in outSrcJar["frameworks/base/org/example/Example.java"]!!) 60 } 61 62 @Test 63 fun e2e_viewerConfig() { 64 val output = run( 65 src = "frameworks/base/org/example/Example.java" to """ 66 package org.example; 67 import com.android.internal.protolog.common.ProtoLog; 68 import static com.android.internal.protolog.ProtoLogGroup.GROUP; 69 70 class Example { 71 void method() { 72 String argString = "hello"; 73 int argInt = 123; 74 ProtoLog.d(GROUP, "Example: %s %d", argString, argInt); 75 } 76 } 77 """.trimIndent(), 78 logGroup = LogGroup("GROUP", true, false, "TAG_GROUP"), 79 commandOptions = CommandOptions(arrayOf("generate-viewer-config", 80 "--protolog-class", "com.android.internal.protolog.common.ProtoLog", 81 "--loggroups-class", "com.android.internal.protolog.ProtoLogGroup", 82 "--loggroups-jar", "not_required.jar", 83 "--viewer-conf", "out.json", 84 "frameworks/base/org/example/Example.java")) 85 ) 86 val viewerConfigJson = assertLoadText(output, "out.json") 87 assertTrue("\"2066303299\"" in viewerConfigJson) 88 } 89 90 private fun assertLoadSrcJar( 91 outputs: Map<String, ByteArray>, 92 path: String 93 ): Map<String, String> { 94 val out = outputs[path] ?: fail("$path not in outputs (${outputs.keys})") 95 96 val sources = mutableMapOf<String, String>() 97 JarInputStream(ByteArrayInputStream(out)).use { jarStream -> 98 var entry = jarStream.nextJarEntry 99 while (entry != null) { 100 if (entry.name.endsWith(".java")) { 101 sources[entry.name] = jarStream.reader().readText() 102 } 103 entry = jarStream.nextJarEntry 104 } 105 } 106 return sources 107 } 108 109 private fun assertLoadText(outputs: Map<String, ByteArray>, path: String): String { 110 val out = outputs[path] ?: fail("$path not in outputs (${outputs.keys})") 111 return out.toString(Charsets.UTF_8) 112 } 113 114 fun run( 115 src: Pair<String, String>, 116 logGroup: LogGroup, 117 commandOptions: CommandOptions 118 ): Map<String, ByteArray> { 119 val outputs = mutableMapOf<String, ByteArrayOutputStream>() 120 121 ProtoLogTool.injector = object : ProtoLogTool.Injector { 122 override fun fileOutputStream(file: String): OutputStream = 123 ByteArrayOutputStream().also { outputs[file] = it } 124 125 override fun readText(file: File): String { 126 if (file.path == src.first) { 127 return src.second 128 } 129 throw FileNotFoundException("expected: ${src.first}, but was $file") 130 } 131 132 override fun readLogGroups(jarPath: String, className: String) = mapOf( 133 logGroup.name to logGroup) 134 135 override fun reportParseError(ex: ParsingException) = throw AssertionError(ex) 136 } 137 138 ProtoLogTool.invoke(commandOptions) 139 140 return outputs.mapValues { it.value.toByteArray() } 141 } 142 143 fun fail(message: String): Nothing = Assert.fail(message) as Nothing 144 } 145