1#!/usr/bin/ruby 2# encoding: utf-8 3 4require 'antlr3' 5require 'antlr3/tree/wizard' 6require 'test/unit' 7require 'spec' 8 9include ANTLR3 10include ANTLR3::AST 11 12class TestPatternLexer < Test::Unit::TestCase 13 14 # vvvvvvvv tests vvvvvvvvv 15 16 def test_open 17 lexer = Wizard::PatternLexer.new( '(' ) 18 type = lexer.next_token 19 assert_equal( type, :open ) 20 assert_equal( lexer.text, '' ) 21 assert_equal( lexer.error, false ) 22 end 23 24 def test_close 25 lexer = Wizard::PatternLexer.new(')') 26 type = lexer.next_token 27 assert_equal(type, :close) 28 assert_equal(lexer.text, '') 29 assert_equal(lexer.error, false) 30 end 31 32 def test_percent 33 lexer = Wizard::PatternLexer.new('%') 34 type = lexer.next_token 35 assert_equal(type, :percent) 36 assert_equal(lexer.text, '') 37 assert_equal(lexer.error, false) 38 end 39 40 def test_dot 41 lexer = Wizard::PatternLexer.new('.') 42 type = lexer.next_token 43 assert_equal(type, :dot) 44 assert_equal(lexer.text, '') 45 assert_equal(lexer.error, false) 46 end 47 48 def test_eof 49 lexer = Wizard::PatternLexer.new(" \n \r \t ") 50 type = lexer.next_token 51 assert_equal(type, EOF) 52 assert_equal(lexer.text, '') 53 assert_equal(lexer.error, false) 54 end 55 56 def test_id 57 lexer = Wizard::PatternLexer.new('__whatever_1__') 58 type = lexer.next_token 59 assert_equal(:identifier, type) 60 assert_equal('__whatever_1__', lexer.text) 61 assert( !(lexer.error) ) 62 end 63 64 def test_arg 65 lexer = Wizard::PatternLexer.new('[ \]bla\n]') 66 type = lexer.next_token 67 assert_equal(type, :argument) 68 assert_equal(' ]bla\n', lexer.text) 69 assert( !(lexer.error) ) 70 end 71 72 def test_error 73 lexer = Wizard::PatternLexer.new("1") 74 type = lexer.next_token 75 assert_equal(type, EOF) 76 assert_equal(lexer.text, '') 77 assert_equal(lexer.error, true) 78 end 79 80end 81 82 83class TestPatternParser < Test::Unit::TestCase 84 Tokens = TokenScheme.build %w(A B C D E ID VAR) 85 include Tokens 86 87 def setup 88 @adaptor = CommonTreeAdaptor.new( Tokens.token_class ) 89 @pattern_adaptor = Wizard::PatternAdaptor.new( Tokens.token_class ) 90 @wizard = Wizard.new( :adaptor => @adaptor, :token_scheme => Tokens ) 91 end 92 93 # vvvvvvvv tests vvvvvvvvv 94 def test_single_node 95 tree = Wizard::PatternParser.parse( 'ID', Tokens, @adaptor ) 96 97 assert_instance_of(CommonTree, tree) 98 assert_equal( ID, tree.type ) 99 assert_equal( 'ID', tree.text ) 100 end 101 102 def test_single_node_with_arg 103 tree = Wizard::PatternParser.parse( 'ID[foo]', Tokens, @adaptor ) 104 105 assert_instance_of( CommonTree, tree ) 106 assert_equal( ID, tree.type ) 107 assert_equal( 'foo', tree.text ) 108 end 109 110 def test_single_level_tree 111 tree = Wizard::PatternParser.parse( '(A B)', Tokens, @adaptor ) 112 113 assert_instance_of( CommonTree, tree ) 114 assert_equal(A, tree.type) 115 assert_equal('A', tree.text) 116 assert_equal(tree.child_count, 1) 117 assert_equal(tree.child(0).type, B) 118 assert_equal(tree.child(0).text, 'B') 119 end 120 121 def test_nil 122 tree = Wizard::PatternParser.parse( 'nil', Tokens, @adaptor ) 123 124 assert_instance_of(CommonTree, tree) 125 assert_equal(0, tree.type) 126 assert_nil tree.text 127 end 128 129 def test_wildcard 130 tree = Wizard::PatternParser.parse( '(.)', Tokens, @adaptor ) 131 assert_instance_of( Wizard::WildcardPattern, tree ) 132 end 133 134 def test_label 135 tree = Wizard::PatternParser.parse( '(%a:A)', Tokens, @pattern_adaptor ) 136 assert_instance_of(Wizard::Pattern, tree) 137 assert_equal('a', tree.label) 138 end 139 140 def test_error_1 141 tree = Wizard::PatternParser.parse( ')', Tokens, @adaptor ) 142 assert_nil tree 143 end 144 145 def test_error_2 146 tree = Wizard::PatternParser.parse( '()', Tokens, @adaptor ) 147 assert_nil tree 148 end 149 150 def test_error_3 151 tree = Wizard::PatternParser.parse( '(A ])', Tokens, @adaptor ) 152 assert_nil tree 153 end 154 155end 156 157 158class TestTreeWizard < Test::Unit::TestCase 159 Tokens = TokenScheme.build %w(A B C D E ID VAR) 160 include Tokens 161 162 def setup 163 @adaptor = CommonTreeAdaptor.new( Tokens.token_class ) 164 @wizard = Wizard.new( :adaptor => @adaptor, :token_scheme => Tokens ) 165 end 166 167 def create_wizard( tokens ) 168 Wizard.new( :tokens => tokens ) 169 end 170 171 # vvvvvvvv tests vvvvvvvvv 172 def test_init 173 @wizard = Wizard.new( :tokens => %w(A B), :adaptor => @adaptor ) 174 175 assert_equal( @wizard.adaptor, @adaptor ) 176 assert_kind_of( ANTLR3::TokenScheme, @wizard.token_scheme ) 177 end 178 179 def test_single_node 180 t = @wizard.create("ID") 181 assert_equal(t.inspect, 'ID') 182 end 183 184 def test_single_node_with_arg 185 t = @wizard.create("ID[foo]") 186 187 assert_equal(t.inspect, 'foo') 188 end 189 190 def test_single_node_tree 191 t = @wizard.create("(A)") 192 assert_equal(t.inspect, 'A') 193 end 194 195 def test_single_level_tree 196 t = @wizard.create("(A B C D)") 197 assert_equal(t.inspect, '(A B C D)') 198 end 199 200 def test_list_tree 201 t = @wizard.create("(nil A B C)") 202 assert_equal(t.inspect, 'A B C') 203 end 204 205 def test_invalid_list_tree 206 t = @wizard.create("A B C") 207 assert_nil t 208 end 209 210 def test_double_level_tree 211 t = @wizard.create("(A (B C) (B D) E)") 212 assert_equal(t.inspect, "(A (B C) (B D) E)") 213 end 214 215 SIMPLIFY_MAP = lambda do |imap| 216 Hash[ 217 imap.map { |type, nodes| [type, nodes.map { |n| n.to_s }] } 218 ] 219 end 220 221 def test_single_node_index 222 tree = @wizard.create("ID") 223 index_map = SIMPLIFY_MAP[@wizard.index(tree)] 224 225 assert_equal(index_map, ID => %w(ID)) 226 end 227 228 229 def test_no_repeats_index 230 tree = @wizard.create("(A B C D)") 231 index_map = SIMPLIFY_MAP[@wizard.index(tree)] 232 233 assert_equal(index_map, 234 D => %w(D), B => %w(B), 235 C => %w(C), A => %w(A) 236 ) 237 end 238 239 def test_repeats_index 240 tree = @wizard.create("(A B (A C B) B D D)") 241 index_map = SIMPLIFY_MAP[@wizard.index(tree)] 242 243 assert_equal(index_map, 244 D => %w(D D), B => %w(B B B), 245 C => %w(C), A => %w(A A) 246 ) 247 end 248 249 250 def test_no_repeats_visit 251 tree = @wizard.create("(A B C D)") 252 253 elements = [] 254 @wizard.visit( tree, B ) do |node, parent, child_index, labels| 255 elements << node.to_s 256 end 257 258 assert_equal( %w(B), elements ) 259 end 260 261 262 def test_no_repeats_visit2 263 tree = @wizard.create("(A B (A C B) B D D)") 264 265 elements = [] 266 @wizard.visit( tree, C ) do |node, parent, child_index, labels| 267 elements << node.to_s 268 end 269 270 assert_equal(%w(C), elements) 271 end 272 273 274 def test_repeats_visit 275 tree = @wizard.create("(A B (A C B) B D D)") 276 277 elements = [] 278 @wizard.visit( tree, B ) do |node, parent, child_index, labels| 279 elements << node.to_s 280 end 281 282 assert_equal(%w(B B B), elements) 283 end 284 285 286 def test_repeats_visit2 287 tree = @wizard.create("(A B (A C B) B D D)") 288 289 elements = [] 290 @wizard.visit( tree, A ) do |node, parent, child_index, labels| 291 elements << node.to_s 292 end 293 294 assert_equal(%w(A A), elements) 295 end 296 297 def context(node, parent, index) 298 '%s@%s[%d]' % [node.to_s, (parent || 'nil').to_s, index] 299 end 300 301 def test_repeats_visit_with_context 302 tree = @wizard.create("(A B (A C B) B D D)") 303 304 elements = [] 305 @wizard.visit( tree, B ) do |node, parent, child_index, labels| 306 elements << context(node, parent, child_index) 307 end 308 309 assert_equal(['B@A[0]', 'B@A[1]', 'B@A[2]'], elements) 310 end 311 312 313 def test_repeats_visit_with_null_parent_and_context 314 tree = @wizard.create("(A B (A C B) B D D)") 315 316 elements = [] 317 @wizard.visit( tree, A ) do |node, parent, child_index, labels| 318 elements << context(node, parent, child_index) 319 end 320 321 assert_equal(['A@nil[-1]', 'A@A[1]'], elements) 322 end 323 324 def test_visit_pattern 325 tree = @wizard.create("(A B C (A B) D)") 326 327 elements = [] 328 @wizard.visit(tree, '(A B)') do |node, parent, child_index, labels| 329 elements << node.to_s 330 end 331 332 assert_equal(%w(A), elements) 333 end 334 335 336 def test_visit_pattern_multiple 337 tree = @wizard.create("(A B C (A B) (D (A B)))") 338 339 elements = [] 340 @wizard.visit(tree, '(A B)') do |node, parent, child_index, labels| 341 elements << context(node, parent, child_index) 342 end 343 344 assert_equal( %w(A@A[2] A@D[0]) , elements ) 345 end 346 347 def labeled_context(node, parent, index, labels, *names) 348 suffix = names.map { |n| labels[n].to_s }.join('&') 349 '%s@%s[%d]%s' % [node.to_s, (parent || 'nil').to_s, index, suffix] 350 end 351 352 def test_visit_pattern_multiple_with_labels 353 tree = @wizard.create("(A B C (A[foo] B[bar]) (D (A[big] B[dog])))") 354 355 elements = [] 356 @wizard.visit(tree, '(%a:A %b:B)') do |node, parent, child_index, labels| 357 elements << labeled_context(node, parent, child_index, labels, 'a', 'b') 358 end 359 360 assert_equal( ['foo@A[2]foo&bar', 'big@D[0]big&dog'] , elements ) 361 end 362 363 364 def test_match 365 tree = @wizard.create("(A B C)") 366 assert @wizard.match(tree, "(A B C)") 367 end 368 369 def test_match_single_node 370 tree = @wizard.create('A') 371 assert @wizard.match(tree, 'A') 372 end 373 374 def test_match_single_node_fails 375 tree = @wizard.create('A') 376 assert( !(@wizard.match(tree, 'B')) ) 377 end 378 379 380 def test_match_flat_tree 381 tree = @wizard.create('(nil A B C)') 382 assert @wizard.match(tree, '(nil A B C)') 383 end 384 385 def test_match_flat_tree_fails 386 tree = @wizard.create('(nil A B C)') 387 assert( !(@wizard.match(tree, '(nil A B)')) ) 388 end 389 390 def test_match_flat_tree_fails2 391 tree = @wizard.create('(nil A B C)') 392 assert( !(@wizard.match(tree, '(nil A B A)')) ) 393 end 394 395 def test_wildcard 396 tree = @wizard.create('(A B C)') 397 assert @wizard.match(tree, '(A . .)') 398 end 399 400 def test_match_with_text 401 tree = @wizard.create('(A B[foo] C[bar])') 402 assert @wizard.match(tree, '(A B[foo] C)') 403 end 404 405 def test_match_with_text_fails 406 tree = @wizard.create('(A B C)') 407 assert( !(@wizard.match(tree, '(A[foo] B C)')) ) 408 end 409 410 def test_match_labels 411 tree = @wizard.create('(A B C)') 412 labels = @wizard.match( tree, '(%a:A %b:B %c:C)' ) 413 414 assert_equal('A', labels['a'].to_s) 415 assert_equal('B', labels['b'].to_s) 416 assert_equal('C', labels['c'].to_s) 417 end 418 419 def test_match_with_wildcard_labels 420 tree = @wizard.create('(A B C)') 421 labels = @wizard.match(tree, '(A %b:. %c:.)') 422 assert_kind_of( Hash, labels ) 423 assert_equal('B', labels['b'].to_s) 424 assert_equal('C', labels['c'].to_s) 425 end 426 427 428 def test_match_labels_and_test_text 429 tree = @wizard.create('(A B[foo] C)') 430 labels = @wizard.match( tree, '(%a:A %b:B[foo] %c:C)' ) 431 assert_kind_of( Hash, labels ) 432 assert_equal('A', labels['a'].to_s) 433 assert_equal('foo', labels['b'].to_s) 434 assert_equal('C', labels['c'].to_s) 435 end 436 437 def test_match_labels_in_nested_tree 438 tree = @wizard.create('(A (B C) (D E))') 439 labels = @wizard.match( tree, '(%a:A (%b:B %c:C) (%d:D %e:E))' ) 440 assert_kind_of( Hash, labels ) 441 assert_equal('A', labels['a'].to_s) 442 assert_equal('B', labels['b'].to_s) 443 assert_equal('C', labels['c'].to_s) 444 assert_equal('D', labels['d'].to_s) 445 assert_equal('E', labels['e'].to_s) 446 end 447 448 449 def test_equals 450 tree1 = @wizard.create("(A B C)") 451 tree2 = @wizard.create("(A B C)") 452 assert @wizard.equals(tree1, tree2) 453 end 454 455 456 def test_equals_with_text 457 tree1 = @wizard.create("(A B[foo] C)") 458 tree2 = @wizard.create("(A B[foo] C)") 459 assert @wizard.equals(tree1, tree2) 460 end 461 462 463 def test_equals_with_mismatched_text 464 tree1 = @wizard.create("(A B[foo] C)") 465 tree2 = @wizard.create("(A B C)") 466 assert( !(@wizard.equals(tree1, tree2)) ) 467 end 468 469 470 def test_equals_with_mismatched_list 471 tree1 = @wizard.create("(A B C)") 472 tree2 = @wizard.create("(A B A)") 473 assert( !(@wizard.equals(tree1, tree2)) ) 474 end 475 476 def test_equals_with_mismatched_list_length 477 tree1 = @wizard.create("(A B C)") 478 tree2 = @wizard.create("(A B)") 479 assert( !(@wizard.equals(tree1, tree2)) ) 480 end 481 482 def test_find_pattern 483 tree = @wizard.create("(A B C (A[foo] B[bar]) (D (A[big] B[dog])))") 484 subtrees = @wizard.find(tree, "(A B)").map { |t| t.to_s } 485 assert_equal(%w(foo big), subtrees) 486 end 487 488 def test_find_token_type 489 tree = @wizard.create("(A B C (A[foo] B[bar]) (D (A[big] B[dog])))") 490 subtrees = @wizard.find( tree, A ).map { |t| t.to_s } 491 assert_equal(%w(A foo big), subtrees) 492 end 493end 494 495