1// Copyright 2017 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package jar 16 17import ( 18 "bytes" 19 "io" 20 "testing" 21) 22 23func TestGetJavaPackage(t *testing.T) { 24 type args struct { 25 r io.Reader 26 src string 27 } 28 tests := []struct { 29 name string 30 in string 31 want string 32 wantErr bool 33 }{ 34 { 35 name: "simple", 36 in: "package foo.bar;", 37 want: "foo.bar", 38 }, 39 { 40 name: "comment", 41 in: "/* test */\npackage foo.bar;", 42 want: "foo.bar", 43 }, 44 { 45 name: "no package", 46 in: "import foo.bar;", 47 want: "", 48 }, 49 { 50 name: "missing semicolon error", 51 in: "package foo.bar", 52 wantErr: true, 53 }, 54 { 55 name: "parser error", 56 in: "/*", 57 wantErr: true, 58 }, 59 { 60 name: "parser ident error", 61 in: "package 0foo.bar;", 62 wantErr: true, 63 }, 64 { 65 name: "annotations", 66 in: "@NonNullApi\n@X\npackage foo.bar;", 67 want: "foo.bar", 68 }, 69 { 70 name: "complex annotation", 71 in: "@Foo(x=y)\n@package foo.bar;", 72 wantErr: true, // Complex annotation not supported yet. 73 }, 74 } 75 for _, tt := range tests { 76 t.Run(tt.name, func(t *testing.T) { 77 buf := bytes.NewBufferString(tt.in) 78 got, err := JavaPackage(buf, "<test>") 79 if (err != nil) != tt.wantErr { 80 t.Errorf("JavaPackage() error = %v, wantErr %v", err, tt.wantErr) 81 return 82 } 83 if got != tt.want { 84 t.Errorf("JavaPackage() = %v, want %v", got, tt.want) 85 } 86 }) 87 } 88} 89 90func Test_javaIdentRune(t *testing.T) { 91 // runes that should be valid anywhere in an identifier 92 validAnywhere := []rune{ 93 // letters, $, _ 94 'a', 95 'A', 96 '$', 97 '_', 98 99 // assorted unicode 100 '', 101 '', 102 'Dž', 103 'ῼ', 104 'ʰ', 105 '゚', 106 'ƻ', 107 '', 108 '₩', 109 '_', 110 'Ⅰ', 111 '', 112 } 113 114 // runes that should be invalid as the first rune in an identifier, but valid anywhere else 115 validAfterFirst := []rune{ 116 // digits 117 '0', 118 119 // assorted unicode 120 '᥍', 121 '', 122 'ྂ', 123 '', 124 125 // control characters 126 '\x00', 127 '\b', 128 '\u000e', 129 '\u001b', 130 '\u007f', 131 '\u009f', 132 '\u00ad', 133 0xE007F, 134 135 // zero width space 136 '\u200b', 137 } 138 139 // runes that should never be valid in an identifier 140 invalid := []rune{ 141 ';', 142 0x110000, 143 } 144 145 validFirst := validAnywhere 146 invalidFirst := append(validAfterFirst, invalid...) 147 validPart := append(validAnywhere, validAfterFirst...) 148 invalidPart := invalid 149 150 check := func(t *testing.T, ch rune, i int, want bool) { 151 t.Helper() 152 if got := javaIdentRune(ch, i); got != want { 153 t.Errorf("javaIdentRune() = %v, want %v", got, want) 154 } 155 } 156 157 t.Run("first", func(t *testing.T) { 158 t.Run("valid", func(t *testing.T) { 159 for _, ch := range validFirst { 160 t.Run(string(ch), func(t *testing.T) { 161 check(t, ch, 0, true) 162 }) 163 } 164 }) 165 166 t.Run("invalid", func(t *testing.T) { 167 for _, ch := range invalidFirst { 168 t.Run(string(ch), func(t *testing.T) { 169 check(t, ch, 0, false) 170 }) 171 } 172 }) 173 }) 174 175 t.Run("part", func(t *testing.T) { 176 t.Run("valid", func(t *testing.T) { 177 for _, ch := range validPart { 178 t.Run(string(ch), func(t *testing.T) { 179 check(t, ch, 1, true) 180 }) 181 } 182 }) 183 184 t.Run("invalid", func(t *testing.T) { 185 for _, ch := range invalidPart { 186 t.Run(string(ch), func(t *testing.T) { 187 check(t, ch, 1, false) 188 }) 189 } 190 }) 191 }) 192} 193