• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * [The "BSD licence"]
3  * Copyright (c) 2010 Ben Gruver
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 import org.antlr.runtime.ANTLRInputStream;
30 import org.antlr.runtime.CommonToken;
31 import org.antlr.runtime.CommonTokenStream;
32 import org.antlr.runtime.RecognitionException;
33 import org.jf.smali.expectedTokensTestGrammarLexer;
34 import org.jf.smali.expectedTokensTestGrammarParser;
35 import org.jf.smali.smaliFlexLexer;
36 import org.jf.smali.smaliParser;
37 import org.junit.Assert;
38 import org.junit.Test;
39 
40 import java.io.File;
41 import java.io.IOException;
42 import java.io.InputStream;
43 import java.io.InputStreamReader;
44 import java.util.HashMap;
45 import java.util.List;
46 
47 import static org.jf.smali.expectedTokensTestGrammarParser.ExpectedToken;
48 
49 public class LexerTest {
50     private static final HashMap<String, Integer> tokenTypesByName;
51 
52     static {
53         tokenTypesByName = new HashMap<String, Integer>();
54 
55         for (int i=0; i<smaliParser.tokenNames.length; i++) {
tokenTypesByName.put(smaliParser.tokenNames[i], i)56             tokenTypesByName.put(smaliParser.tokenNames[i], i);
57         }
58     }
59 
60     @Test
DirectiveTest()61     public void DirectiveTest() {
62         runTest("DirectiveTest");
63     }
64 
65     @Test
ByteLiteralTest()66     public void ByteLiteralTest() {
67         runTest("ByteLiteralTest");
68     }
69 
70     @Test
ShortLiteralTest()71     public void ShortLiteralTest() {
72         runTest("ShortLiteralTest");
73     }
74 
75     @Test
IntegerLiteralTest()76     public void IntegerLiteralTest() {
77         runTest("IntegerLiteralTest");
78     }
79 
80     @Test
LongLiteralTest()81     public void LongLiteralTest() {
82         runTest("LongLiteralTest");
83     }
84 
85     @Test
FloatLiteralTest()86     public void FloatLiteralTest() {
87         runTest("FloatLiteralTest");
88     }
89 
90     @Test
CharLiteralTest()91     public void CharLiteralTest() {
92         runTest("CharLiteralTest");
93     }
94 
95     @Test
StringLiteralTest()96     public void StringLiteralTest() {
97         runTest("StringLiteralTest");
98     }
99 
100     @Test
MiscTest()101     public void MiscTest() {
102         runTest("MiscTest");
103     }
104 
105     @Test
CommentTest()106     public void CommentTest() {
107         runTest("CommentTest", false);
108     }
109 
110     @Test
InstructionTest()111     public void InstructionTest() {
112         runTest("InstructionTest", true);
113     }
114 
115     @Test
TypeAndIdentifierTest()116     public void TypeAndIdentifierTest() {
117         runTest("TypeAndIdentifierTest");
118     }
119 
120     @Test
SymbolTest()121     public void SymbolTest() {
122         runTest("SymbolTest", false);
123     }
124 
125     @Test
RealSmaliFileTest()126     public void RealSmaliFileTest() {
127         runTest("RealSmaliFileTest", true);
128     }
129 
runTest(String test)130     public void runTest(String test) {
131         runTest(test, true);
132     }
133 
runTest(String test, boolean discardHiddenTokens)134     public void runTest(String test, boolean discardHiddenTokens) {
135         String smaliFile = String.format("LexerTest%s%s.smali", File.separatorChar, test);
136         String tokensFile = String.format("LexerTest%s%s.tokens", File.separatorChar, test);
137 
138         expectedTokensTestGrammarLexer expectedTokensLexer = null;
139         try {
140             expectedTokensLexer = new expectedTokensTestGrammarLexer(new ANTLRInputStream(
141                     LexerTest.class.getClassLoader().getResourceAsStream(tokensFile)));
142         } catch (IOException ex) {
143             throw new RuntimeException(ex);
144         }
145 
146         CommonTokenStream expectedTokensStream = new CommonTokenStream(expectedTokensLexer);
147 
148         expectedTokensTestGrammarParser expectedTokensParser =
149                 new expectedTokensTestGrammarParser(expectedTokensStream);
150         try {
151             expectedTokensParser.top();
152         } catch (RecognitionException ex) {
153             throw new RuntimeException(ex);
154         }
155 
156         List<ExpectedToken> expectedTokens = expectedTokensParser.getExpectedTokens();
157 
158         InputStream smaliStream = LexerTest.class.getClassLoader().getResourceAsStream(smaliFile);
159         if (smaliStream == null) {
160             Assert.fail("Could not load " + smaliFile);
161         }
162         smaliFlexLexer lexer = new smaliFlexLexer(new InputStreamReader(smaliStream));
163         lexer.setSourceFile(new File(test + ".smali"));
164         lexer.setSuppressErrors(true);
165 
166         CommonTokenStream tokenStream = new CommonTokenStream(lexer);
167         tokenStream.fill();
168         List tokens = tokenStream.getTokens();
169 
170         int expectedTokenIndex = 0;
171         CommonToken token;
172         for (int i=0; i<tokens.size()-1; i++) {
173             token = (CommonToken)tokens.get(i);
174 
175             if (discardHiddenTokens && token.getChannel() == smaliParser.HIDDEN) {
176                 continue;
177             }
178 
179             if (expectedTokenIndex >= expectedTokens.size()) {
180                 Assert.fail("Too many tokens");
181             }
182 
183             if (token.getType() == smaliParser.INVALID_TOKEN) {
184                 Assert.assertTrue("Encountered an INVALID_TOKEN not on the error channel",
185                         token.getChannel() == smaliParser.ERROR_CHANNEL);
186             }
187 
188             ExpectedToken expectedToken = expectedTokens.get(expectedTokenIndex++);
189             if (!tokenTypesByName.containsKey(expectedToken.tokenName)) {
190                 Assert.fail("Unknown token: " + expectedToken.tokenName);
191             }
192             int expectedTokenType = tokenTypesByName.get(expectedToken.tokenName);
193 
194             if (token.getType() != expectedTokenType) {
195                 Assert.fail(String.format("Invalid token at index %d. Expecting %s, got %s(%s)",
196                         expectedTokenIndex-1, expectedToken.tokenName, getTokenName(token.getType()), token.getText()));
197             }
198 
199             if (expectedToken.tokenText != null) {
200                 if (!expectedToken.tokenText.equals(token.getText())) {
201                     Assert.fail(
202                             String.format("Invalid token text at index %d. Expecting text \"%s\", got \"%s\"",
203                                     expectedTokenIndex - 1, expectedToken.tokenText, token.getText()));
204                 }
205             }
206         }
207 
208         if (expectedTokenIndex < expectedTokens.size()) {
209             Assert.fail(String.format("Not enough tokens. Expecting %d tokens, but got %d", expectedTokens.size(),
210                     expectedTokenIndex));
211         }
212     }
213 
214 
215 
getTokenName(int tokenType)216     private static String getTokenName(int tokenType) {
217         return smaliParser.tokenNames[tokenType];
218     }
219 }
220