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 com.android.json.stream.JsonReader 20 import com.android.internal.protolog.ProtoLogMessage 21 import com.android.internal.protolog.ProtoLogFileProto 22 import org.junit.Assert.assertEquals 23 import org.junit.Before 24 import org.junit.Test 25 import org.mockito.Mockito 26 import org.mockito.Mockito.mock 27 import java.io.ByteArrayOutputStream 28 import java.io.InputStream 29 import java.io.OutputStream 30 import java.io.PrintStream 31 import java.text.SimpleDateFormat 32 import java.util.Date 33 import java.util.Locale 34 35 class LogParserTest { 36 private val configParser: ViewerConfigParser = mock(ViewerConfigParser::class.java) 37 private val parser = LogParser(configParser) 38 private var config: MutableMap<Long, ViewerConfigParser.ConfigEntry> = mutableMapOf() 39 private var outStream: OutputStream = ByteArrayOutputStream() 40 private var printStream: PrintStream = PrintStream(outStream) 41 private val dateFormat = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US) 42 43 @Before initnull44 fun init() { 45 Mockito.`when`(configParser.parseConfig(any(JsonReader::class.java))).thenReturn(config) 46 } 47 anynull48 private fun <T> any(type: Class<T>): T = Mockito.any<T>(type) 49 50 private fun getConfigDummyStream(): InputStream { 51 return "".byteInputStream() 52 } 53 buildProtoInputnull54 private fun buildProtoInput(logBuilder: ProtoLogFileProto.Builder): InputStream { 55 logBuilder.setVersion(Constants.VERSION) 56 logBuilder.magicNumber = 57 ProtoLogFileProto.MagicNumber.MAGIC_NUMBER_H.number.toLong() shl 32 or 58 ProtoLogFileProto.MagicNumber.MAGIC_NUMBER_L.number.toLong() 59 return logBuilder.build().toByteArray().inputStream() 60 } 61 testDatenull62 private fun testDate(timeMS: Long): String { 63 return dateFormat.format(Date(timeMS)) 64 } 65 66 @Test parsenull67 fun parse() { 68 config[70933285] = ViewerConfigParser.ConfigEntry("Test completed successfully: %b", 69 "ERROR", "WindowManager") 70 71 val logBuilder = ProtoLogFileProto.newBuilder() 72 val logMessageBuilder = ProtoLogMessage.newBuilder() 73 logMessageBuilder 74 .setMessageHash(70933285) 75 .setElapsedRealtimeNanos(0) 76 .addBooleanParams(true) 77 logBuilder.addLog(logMessageBuilder.build()) 78 79 parser.parse(buildProtoInput(logBuilder), getConfigDummyStream(), printStream) 80 81 assertEquals("${testDate(0)} ERROR WindowManager: Test completed successfully: true\n", 82 outStream.toString()) 83 } 84 85 @Test parse_formattingnull86 fun parse_formatting() { 87 config[123] = ViewerConfigParser.ConfigEntry("Test completed successfully: %b %d %%" + 88 " %x %s %f", "ERROR", "WindowManager") 89 90 val logBuilder = ProtoLogFileProto.newBuilder() 91 val logMessageBuilder = ProtoLogMessage.newBuilder() 92 logMessageBuilder 93 .setMessageHash(123) 94 .setElapsedRealtimeNanos(0) 95 .addBooleanParams(true) 96 .addAllSint64Params(listOf(1000, 20000)) 97 .addDoubleParams(1000.1) 98 .addStrParams("test") 99 logBuilder.addLog(logMessageBuilder.build()) 100 101 parser.parse(buildProtoInput(logBuilder), getConfigDummyStream(), printStream) 102 103 assertEquals("${testDate(0)} ERROR WindowManager: Test completed successfully: " + 104 "true 1000 % 4e20 test 1000.100000\n", 105 outStream.toString()) 106 } 107 108 @Test parse_invalidParamsTooManynull109 fun parse_invalidParamsTooMany() { 110 config[123] = ViewerConfigParser.ConfigEntry("Test completed successfully: %b %d %%", 111 "ERROR", "WindowManager") 112 113 val logBuilder = ProtoLogFileProto.newBuilder() 114 val logMessageBuilder = ProtoLogMessage.newBuilder() 115 logMessageBuilder 116 .setMessageHash(123) 117 .setElapsedRealtimeNanos(0) 118 .addBooleanParams(true) 119 .addAllSint64Params(listOf(1000, 20000, 300000)) 120 .addAllDoubleParams(listOf(0.1, 0.00001, 1000.1)) 121 .addStrParams("test") 122 logBuilder.addLog(logMessageBuilder.build()) 123 124 parser.parse(buildProtoInput(logBuilder), getConfigDummyStream(), printStream) 125 126 assertEquals("${testDate(0)} INVALID: 123 - [test] [1000, 20000, 300000] " + 127 "[0.1, 1.0E-5, 1000.1] [true]\n", outStream.toString()) 128 } 129 130 @Test parse_invalidParamsNotEnoughnull131 fun parse_invalidParamsNotEnough() { 132 config[123] = ViewerConfigParser.ConfigEntry("Test completed successfully: %b %d %%" + 133 " %x %s %f", "ERROR", "WindowManager") 134 135 val logBuilder = ProtoLogFileProto.newBuilder() 136 val logMessageBuilder = ProtoLogMessage.newBuilder() 137 logMessageBuilder 138 .setMessageHash(123) 139 .setElapsedRealtimeNanos(0) 140 .addBooleanParams(true) 141 .addStrParams("test") 142 logBuilder.addLog(logMessageBuilder.build()) 143 144 parser.parse(buildProtoInput(logBuilder), getConfigDummyStream(), printStream) 145 146 assertEquals("${testDate(0)} INVALID: 123 - [test] [] [] [true]\n", 147 outStream.toString()) 148 } 149 150 @Test(expected = InvalidInputException::class) parse_invalidMagicNumbernull151 fun parse_invalidMagicNumber() { 152 val logBuilder = ProtoLogFileProto.newBuilder() 153 logBuilder.setVersion(Constants.VERSION) 154 logBuilder.magicNumber = 0 155 val stream = logBuilder.build().toByteArray().inputStream() 156 157 parser.parse(stream, getConfigDummyStream(), printStream) 158 } 159 160 @Test(expected = InvalidInputException::class) parse_invalidVersionnull161 fun parse_invalidVersion() { 162 val logBuilder = ProtoLogFileProto.newBuilder() 163 logBuilder.setVersion("invalid") 164 logBuilder.magicNumber = 165 ProtoLogFileProto.MagicNumber.MAGIC_NUMBER_H.number.toLong() shl 32 or 166 ProtoLogFileProto.MagicNumber.MAGIC_NUMBER_L.number.toLong() 167 val stream = logBuilder.build().toByteArray().inputStream() 168 169 parser.parse(stream, getConfigDummyStream(), printStream) 170 } 171 172 @Test parse_noConfignull173 fun parse_noConfig() { 174 val logBuilder = ProtoLogFileProto.newBuilder() 175 val logMessageBuilder = ProtoLogMessage.newBuilder() 176 logMessageBuilder 177 .setMessageHash(70933285) 178 .setElapsedRealtimeNanos(0) 179 .addBooleanParams(true) 180 logBuilder.addLog(logMessageBuilder.build()) 181 182 parser.parse(buildProtoInput(logBuilder), getConfigDummyStream(), printStream) 183 184 assertEquals("${testDate(0)} UNKNOWN: 70933285 - [] [] [] [true]\n", 185 outStream.toString()) 186 } 187 } 188