pione 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/.gitignore +2 -1
  2. data/History.txt +11 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +1 -1
  5. data/bin/pione-log +5 -0
  6. data/example/CountChar/CountChar.pione +1 -1
  7. data/example/SieveOfEratosthenes/SieveOfEratosthenes.pione +39 -38
  8. data/lib/pione.rb +14 -35
  9. data/lib/pione/agent/input-generator.rb +38 -40
  10. data/lib/pione/agent/logger.rb +52 -19
  11. data/lib/pione/agent/rule-provider.rb +5 -8
  12. data/lib/pione/agent/task-worker.rb +25 -32
  13. data/lib/pione/agent/tuple-space-client.rb +22 -14
  14. data/lib/pione/command.rb +21 -0
  15. data/lib/pione/command/basic-command.rb +267 -84
  16. data/lib/pione/command/child-process.rb +21 -18
  17. data/lib/pione/command/daemon-process.rb +9 -8
  18. data/lib/pione/command/front-owner-command.rb +8 -25
  19. data/lib/pione/command/pione-broker.rb +27 -24
  20. data/lib/pione/command/pione-clean.rb +6 -6
  21. data/lib/pione/command/pione-client.rb +143 -128
  22. data/lib/pione/command/pione-log.rb +61 -0
  23. data/lib/pione/command/pione-relay-account-db.rb +40 -38
  24. data/lib/pione/command/pione-relay-client-db.rb +38 -42
  25. data/lib/pione/command/pione-relay.rb +19 -20
  26. data/lib/pione/command/pione-syntax-checker.rb +70 -45
  27. data/lib/pione/command/pione-task-worker.rb +56 -66
  28. data/lib/pione/command/pione-tuple-space-provider.rb +36 -45
  29. data/lib/pione/command/pione-tuple-space-receiver.rb +34 -32
  30. data/lib/pione/command/pione-tuple-space-viewer.rb +63 -47
  31. data/lib/pione/location.rb +10 -0
  32. data/lib/pione/location/basic-location.rb +272 -0
  33. data/lib/pione/location/dropbox-location.rb +139 -0
  34. data/lib/pione/location/ftp-location.rb +156 -0
  35. data/lib/pione/location/local-location.rb +116 -0
  36. data/lib/pione/log.rb +10 -0
  37. data/lib/pione/log/domain-info.rb +72 -0
  38. data/lib/pione/log/process-log.rb +176 -0
  39. data/lib/pione/log/process-record.rb +189 -0
  40. data/lib/pione/log/xes-log.rb +105 -0
  41. data/lib/pione/model/assignment.rb +88 -80
  42. data/lib/pione/model/binary-operator.rb +74 -68
  43. data/lib/pione/model/block.rb +218 -207
  44. data/lib/pione/model/boolean.rb +123 -112
  45. data/lib/pione/model/call-rule.rb +72 -65
  46. data/lib/pione/model/data-expr.rb +596 -290
  47. data/lib/pione/model/float.rb +108 -103
  48. data/lib/pione/model/integer.rb +133 -129
  49. data/lib/pione/model/message.rb +79 -72
  50. data/lib/pione/model/package.rb +42 -38
  51. data/lib/pione/model/parameters.rb +265 -236
  52. data/lib/pione/model/rule-expr.rb +247 -242
  53. data/lib/pione/model/rule-io.rb +137 -133
  54. data/lib/pione/model/rule.rb +307 -292
  55. data/lib/pione/model/string.rb +110 -99
  56. data/lib/pione/model/variable-table.rb +300 -271
  57. data/lib/pione/model/variable.rb +88 -83
  58. data/lib/pione/option.rb +13 -0
  59. data/lib/pione/option/child-process-option.rb +19 -0
  60. data/lib/pione/{command-option → option}/common-option.rb +6 -5
  61. data/lib/pione/option/option-interface.rb +73 -0
  62. data/lib/pione/{command-option → option}/presence-notifier-option.rb +4 -3
  63. data/lib/pione/option/task-worker-owner-option.rb +24 -0
  64. data/lib/pione/{command-option → option}/tuple-space-provider-option.rb +6 -4
  65. data/lib/pione/option/tuple-space-provider-owner-option.rb +18 -0
  66. data/lib/pione/option/tuple-space-receiver-option.rb +8 -0
  67. data/lib/pione/parser/common-parser.rb +3 -2
  68. data/lib/pione/parser/expr-parser.rb +6 -1
  69. data/lib/pione/patch/em-ftpd-patch.rb +21 -0
  70. data/lib/pione/patch/rinda-patch.rb +31 -23
  71. data/lib/pione/rule-handler/action-handler.rb +35 -25
  72. data/lib/pione/rule-handler/basic-handler.rb +92 -18
  73. data/lib/pione/rule-handler/flow-handler.rb +104 -98
  74. data/lib/pione/rule-handler/root-handler.rb +11 -0
  75. data/lib/pione/system/common.rb +10 -0
  76. data/lib/pione/system/file-cache.rb +103 -84
  77. data/lib/pione/system/global.rb +67 -12
  78. data/lib/pione/system/init.rb +20 -0
  79. data/lib/pione/transformer/expr-transformer.rb +6 -1
  80. data/lib/pione/tuple-space/data-finder.rb +33 -6
  81. data/lib/pione/tuple-space/tuple-space-receiver.rb +4 -3
  82. data/lib/pione/tuple-space/tuple-space-server-interface.rb +58 -13
  83. data/lib/pione/tuple-space/tuple-space-server.rb +13 -11
  84. data/lib/pione/tuple-space/update-criteria.rb +8 -7
  85. data/lib/pione/tuple/base-location-tuple.rb +9 -0
  86. data/lib/pione/tuple/basic-tuple.rb +7 -7
  87. data/lib/pione/tuple/data-tuple.rb +5 -2
  88. data/lib/pione/tuple/lift-tuple.rb +14 -0
  89. data/lib/pione/tuple/rule-tuple.rb +1 -1
  90. data/lib/pione/tuple/task-tuple.rb +5 -1
  91. data/lib/pione/version.rb +1 -1
  92. data/pione.gemspec +5 -1
  93. data/test/location/spec_basic-location.rb +35 -0
  94. data/test/location/spec_ftp-location.rb +100 -0
  95. data/test/location/spec_local-location.rb +99 -0
  96. data/test/log/data/sample.log +1003 -0
  97. data/test/log/spec_xes-log.rb +11 -0
  98. data/test/model/spec_data-expr.rb +249 -6
  99. data/test/model/spec_data-expr.yml +45 -0
  100. data/test/parser/spec_expr-parser.yml +4 -0
  101. data/test/spec_data-finder.rb +13 -7
  102. data/test/spec_data-finder.yml +42 -13
  103. data/test/system/spec_file-cache.rb +39 -0
  104. data/test/test-util.rb +226 -1
  105. data/test/transformer/spec_expr-transformer.rb +12 -1
  106. metadata +107 -24
  107. data/bin/pione-search-log +0 -30
  108. data/lib/pione/command-option/basic-option.rb +0 -42
  109. data/lib/pione/command-option/child-process-option.rb +0 -17
  110. data/lib/pione/command-option/daemon-option.rb +0 -12
  111. data/lib/pione/command-option/task-worker-owner-option.rb +0 -17
  112. data/lib/pione/command-option/tuple-space-provider-owner-option.rb +0 -16
  113. data/lib/pione/command-option/tuple-space-receiver-option.rb +0 -12
  114. data/lib/pione/command/tuple-space-provider-owner.rb +0 -6
  115. data/lib/pione/resource/basic-resource.rb +0 -92
  116. data/lib/pione/resource/dropbox-resource.rb +0 -106
  117. data/lib/pione/resource/ftp.rb +0 -84
  118. data/lib/pione/resource/local.rb +0 -113
  119. data/lib/pione/tuple/base-uri-tuple.rb +0 -9
  120. data/lib/pione/tuple/shift-tuple.rb +0 -13
  121. data/lib/pione/util/log.rb +0 -79
  122. data/test/spec_resource.rb +0 -73
@@ -0,0 +1,11 @@
1
+ require_relative '../test-util'
2
+
3
+ location = Pione::Location[File.join(File.dirname(__FILE__), "data", "sample.log")]
4
+
5
+ describe 'Pione::XESLog' do
6
+ it 'should format XES log' do
7
+ result = Log::XESLog.read(location).format
8
+ result.should.kind_of String
9
+ result.size.should > 0
10
+ end
11
+ end
@@ -37,6 +37,18 @@ describe 'Model::DataExpr' do
37
37
  exp.should.be.stderr
38
38
  end
39
39
 
40
+ it 'should neglect update criteria' do
41
+ exp = DataExpr.new('test.a').neglect
42
+ exp.should.neglect
43
+ exp.should.not.care
44
+ end
45
+
46
+ it 'should care update criteria' do
47
+ exp = DataExpr.new('test.a').care
48
+ exp.should.not.neglect
49
+ exp.should.care
50
+ end
51
+
40
52
  it 'should match the same name' do
41
53
  exp = DataExpr.new('test.a')
42
54
  exp.should.match 'test.a'
@@ -50,9 +62,8 @@ describe 'Model::DataExpr' do
50
62
 
51
63
  it 'should handle multi characters matcher (Case 1)' do
52
64
  exp = DataExpr.new('test-*.a')
53
- exp.should.match 'test-.a'
54
- { 'test-.a' => '',
55
- 'test-1.a'=> '1',
65
+ exp.should.not.match 'test-.a'
66
+ { 'test-1.a'=> '1',
56
67
  'test-2.a' => '2',
57
68
  'test-3.a' => '3',
58
69
  'test-A.a' => 'A',
@@ -75,9 +86,7 @@ describe 'Model::DataExpr' do
75
86
  exp.should.match 'test-abc-xyz.a'
76
87
  exp.match('test-abc-xyz.a')[1].should == 'abc'
77
88
  exp.match('test-abc-xyz.a')[2].should == 'xyz'
78
- exp.should.match 'test--.a'
79
- exp.match('test--.a')[1].should == ''
80
- exp.match('test--.a')[2].should == ''
89
+ exp.should.not.match 'test--.a'
81
90
  exp.should.not.match('test-1.a')
82
91
  exp.should.not.match('test-1-2.b')
83
92
  exp.should.not.match('test-1-2')
@@ -309,4 +318,238 @@ describe 'Model::DataExpr' do
309
318
  DataExpr.new('test.a').stderr
310
319
  end
311
320
  end
321
+
322
+ describe 'pione method: or' do
323
+ it 'should get OR-relation data expression' do
324
+ a = DataExpr.new('test.a')
325
+ b = DataExpr.new('test.b')
326
+ a.call_pione_method('or', b).should == DataExprOr.new([a, b])
327
+ end
328
+ end
329
+
330
+ describe 'pione method: join' do
331
+ it 'should join with the connective' do
332
+ DataExpr.new('A:B').call_pione_method('join', PioneString.new(",")).should ==
333
+ PioneString.new("A,B")
334
+ end
335
+ end
336
+
337
+ describe "pione method: as_string" do
338
+ it "should convert to string" do
339
+ DataExpr.new('A').call_pione_method('as_string').should ==
340
+ PioneString.new("A")
341
+ DataExpr.new('A:B').call_pione_method('as_string').should ==
342
+ PioneString.new("A:B")
343
+ DataExprNull.instance.call_pione_method('as_string').should ==
344
+ PioneString.new("")
345
+ end
346
+ end
347
+ end
348
+
349
+ describe "Model::DataExprNull" do
350
+ before do
351
+ @null = Model::DataExprNull.instance
352
+ end
353
+
354
+ it "should not initialize" do
355
+ should.raise(NoMethodError) do
356
+ Model::DataExprNull.new
357
+ end
358
+ end
359
+
360
+ it "should not match any data" do
361
+ @null.should.not.match('test.a')
362
+ end
363
+
364
+ it "should return itselt" do
365
+ @null.all.should == @null
366
+ @null.each.should == @null
367
+ @null.stdout.should == @null
368
+ @null.stderr.should == @null
369
+ @null.neglect.should == @null
370
+ @null.care.should == @null
371
+ end
372
+
373
+ it "should accept nonexistance" do
374
+ @null.should.accept_nonexistence
375
+ end
376
+ end
377
+
378
+ describe "Model::DataExprOr" do
379
+ before do
380
+ @a_each = Model::DataExpr.new('A')
381
+ @a_all = Model::DataExpr.new('A').all
382
+ @a_stdout = Model::DataExpr.new('A').stdout
383
+ @a_stderr = Model::DataExpr.new('A').stderr
384
+ @a_neglect = Model::DataExpr.new('A').neglect
385
+ @a_care = Model::DataExpr.new('A').care
386
+ @a_aster = Model::DataExpr.new('A*')
387
+ @aa_each = Model::DataExpr.new('AA')
388
+ @b_each = Model::DataExpr.new('B')
389
+ @b_all = Model::DataExpr.new('B').all
390
+ @b_stdout = Model::DataExpr.new('B').stdout
391
+ @b_stderr = Model::DataExpr.new('B').stderr
392
+ @b_neglect = Model::DataExpr.new('B').neglect
393
+ @b_care = Model::DataExpr.new('B').care
394
+ @null = Model::DataExprNull.instance
395
+ end
396
+
397
+ it "should match" do
398
+ expr = Model::DataExprOr.new([@a_each, @b_each])
399
+ expr.should.match('A')
400
+ expr.should.match('B')
401
+ expr.should.not.match('C')
402
+ expr.modifier.should == :each
403
+ end
404
+
405
+ it 'should get/set modifier' do
406
+ [ [@a_each, @b_each, @null],
407
+ [@a_all, @b_all, @null] ].each do |vars|
408
+ vars.combination(2) do |left, right|
409
+ Model::DataExprOr.new([left, right]).all.modifier.should == :all
410
+ Model::DataExprOr.new([left, right]).each.modifier.should == :each
411
+ end
412
+ end
413
+ end
414
+
415
+ it 'should get/set the mode' do
416
+ [ [@a_each, @b_each, @null],
417
+ [@a_stdout, @b_stdout, @null],
418
+ [@a_stderr, @b_stderr, @null] ].each do |vars|
419
+ vars.combination(2) do |left, right|
420
+ Model::DataExprOr.new([left, right]).stdout.mode.should == :stdout
421
+ Model::DataExprOr.new([left, right]).stderr.mode.should == :stderr
422
+ end
423
+ end
424
+ end
425
+
426
+ it 'should get/set the update criteria' do
427
+ [ [@a_each, @b_each, @null],
428
+ [@a_neglect, @b_neglect, @null],
429
+ [@a_care, @b_care, @null] ].each do |vars|
430
+ vars.combination(2) do |left, right|
431
+ Model::DataExprOr.new([left, right]).neglect.update_criteria.should == :neglect
432
+ Model::DataExprOr.new([left, right]).care.update_criteria.should == :care
433
+ end
434
+ end
435
+ end
436
+
437
+ it "should have each modifier" do
438
+ Model::DataExprOr.new([@a_each, @b_each]).should.each
439
+ Model::DataExprOr.new([@a_each, @null]).should.each
440
+ Model::DataExprOr.new([@null, @a_each]).should.each
441
+ end
442
+
443
+ it "should not have all modifier" do
444
+ Model::DataExprOr.new([@a_all, @b_all]).should.not.each
445
+ Model::DataExprOr.new([@a_all, @null]).should.not.each
446
+ Model::DataExprOr.new([@null, @a_all]).should.not.each
447
+ end
448
+
449
+ it "should have all modifier" do
450
+ Model::DataExprOr.new([@a_all, @b_all]).should.all
451
+ Model::DataExprOr.new([@a_all, @null]).should.all
452
+ Model::DataExprOr.new([@null, @a_all]).should.all
453
+ end
454
+
455
+ it "should not have all modifier" do
456
+ Model::DataExprOr.new([@a_each, @b_each]).should.not.all
457
+ Model::DataExprOr.new([@a_each, @null]).should.not.all
458
+ Model::DataExprOr.new([@null, @a_each]).should.not.all
459
+ end
460
+
461
+ it "should be stdout mode" do
462
+ Model::DataExprOr.new([@a_stdout, @b_stdout]).should.stdout
463
+ Model::DataExprOr.new([@a_stdout, @null]).should.stdout
464
+ Model::DataExprOr.new([@null, @a_stdout]).should.stdout
465
+ end
466
+
467
+ it "should be not stdout mode" do
468
+ Model::DataExprOr.new([@a_stderr, @b_stderr]).should.not.stdout
469
+ Model::DataExprOr.new([@a_stderr, @null]).should.not.stdout
470
+ Model::DataExprOr.new([@null, @a_stderr]).should.not.stdout
471
+ end
472
+
473
+ it "should be stderr mode" do
474
+ Model::DataExprOr.new([@a_stderr, @b_stderr]).should.stderr
475
+ Model::DataExprOr.new([@a_stderr, @null]).should.stderr
476
+ Model::DataExprOr.new([@null, @a_stderr]).should.stderr
477
+ end
478
+
479
+ it "should be not stderr mode" do
480
+ Model::DataExprOr.new([@a_stdout, @b_stdout]).should.not.stderr
481
+ Model::DataExprOr.new([@a_stdout, @null]).should.not.stderr
482
+ Model::DataExprOr.new([@null, @a_stdout]).should.not.stderr
483
+ end
484
+
485
+ it "should neglect update criteria" do
486
+ Model::DataExprOr.new([@a_neglect, @b_neglect]).should.neglect
487
+ Model::DataExprOr.new([@a_neglect, @null]).should.neglect
488
+ Model::DataExprOr.new([@null, @a_neglect]).should.neglect
489
+ end
490
+
491
+ it "should not neglect update criteria" do
492
+ Model::DataExprOr.new([@a_care, @b_care]).should.not.neglect
493
+ Model::DataExprOr.new([@a_care, @null]).should.not.neglect
494
+ Model::DataExprOr.new([@null, @a_care]).should.not.neglect
495
+ end
496
+
497
+ it "should care update criteria" do
498
+ Model::DataExprOr.new([@a_care, @b_care]).should.care
499
+ Model::DataExprOr.new([@a_care, @null]).should.care
500
+ Model::DataExprOr.new([@null, @a_care]).should.care
501
+ end
502
+
503
+ it "should not care update criteria" do
504
+ Model::DataExprOr.new([@a_neglect, @b_neglect]).should.not.care
505
+ Model::DataExprOr.new([@a_neglect, @null]).should.not.care
506
+ Model::DataExprOr.new([@null, @a_neglect]).should.not.care
507
+ end
508
+
509
+ it "should accept nonexistance" do
510
+ Model::DataExprOr.new([@a_each, @null]).should.accept_nonexistence
511
+ Model::DataExprOr.new([@null, @a_each]).should.accept_nonexistence
512
+ end
513
+
514
+ it "should not accept nonexistance" do
515
+ Model::DataExprOr.new([@a_each, @b_each]).should.not.accept_nonexistence
516
+ end
517
+
518
+ it "should get/set exceptions" do
519
+ Model::DataExprOr.new([@a_aster, @b_each]).except(@aa_each).tap do |expr|
520
+ expr.exceptions.should == [@aa_each]
521
+ expr.should.match("AAA")
522
+ expr.should.match("B")
523
+ expr.should.not.match("AA")
524
+ expr.should.not.match("A")
525
+ expr.should.match("AB")
526
+ end
527
+ end
528
+ end
529
+
530
+ #
531
+ # test cases
532
+ #
533
+ yamlname = 'spec_data-expr.yml'
534
+ ymlpath = File.join(File.dirname(__FILE__), yamlname)
535
+ testcases = YAML.load_file(ymlpath)
536
+
537
+ describe "Model::DataExpr variation tests" do
538
+ testcases.each do |expr, testcase|
539
+ data_expr = DocumentTransformer.new.apply(
540
+ DocumentParser.new.expr.parse(expr)
541
+ )
542
+
543
+ testcase['match'].map do |name|
544
+ it "#{expr} should match #{name}" do
545
+ data_expr.eval(VariableTable.new).should.match(name)
546
+ end
547
+ end
548
+
549
+ testcase['unmatch'].map do |name|
550
+ it "#{expr} should unmatch #{name}" do
551
+ data_expr.eval(VariableTable.new).should.not.match(name)
552
+ end
553
+ end
554
+ end
312
555
  end
@@ -0,0 +1,45 @@
1
+ "'*.a'":
2
+ match:
3
+ - "1.a"
4
+ - "2.a"
5
+ - "3.a"
6
+ - "123.a"
7
+ unmatch:
8
+ - "1.b"
9
+ - ".a"
10
+ - "a"
11
+ - "1.1a"
12
+ - "1.aa"
13
+ - "123.aa"
14
+ "'A:B'":
15
+ match:
16
+ - "A"
17
+ - "B"
18
+ unmatch:
19
+ - "AB"
20
+ - "BA"
21
+ "'*.a:*.b'":
22
+ match:
23
+ - "1.a"
24
+ - "1.b"
25
+ unmatch:
26
+ - "1.ab"
27
+ - "1.ba"
28
+ - ".a"
29
+ - ".b"
30
+ "'A' or 'B'":
31
+ match:
32
+ - "A"
33
+ - "B"
34
+ unmatch:
35
+ - "AB"
36
+ - "BA"
37
+ "'*.a' or '*.b'":
38
+ match:
39
+ - "1.a"
40
+ - "1.b"
41
+ unmatch:
42
+ - "1.ab"
43
+ - "1.ba"
44
+ - ".a"
45
+ - ".b"
@@ -36,6 +36,10 @@ message:
36
36
  - ".sync"
37
37
  - ".abc(1, \"s\", '*.txt')"
38
38
  - ".abc(1.0.abc(3.def))"
39
+ data_expr:
40
+ valid:
41
+ - "'test.a'"
42
+ - "null"
39
43
  rule_expr:
40
44
  valid:
41
45
  - "&package:rule_name"
@@ -9,11 +9,11 @@ testcases = YAML.load_file(ymlpath)
9
9
 
10
10
  describe 'DataFinder' do
11
11
  before do
12
- create_remote_tuple_space_server
12
+ create_tuple_space_server
13
13
  end
14
14
 
15
15
  after do
16
- tuple_space_server.terminate
16
+ #tuple_space_server.terminate
17
17
  end
18
18
 
19
19
  it 'should find a data tuple by complete name' do
@@ -59,24 +59,30 @@ describe 'DataFinder' do
59
59
 
60
60
  # tuples
61
61
  testcase['tuples'].map {|name|
62
- Tuple[:data].new(name: name, domain: 'test')
62
+ Tuple[:data].new(name: name, domain: 'test', location: Location[name])
63
63
  }.each do |tuple|
64
64
  tuple_space_server.write(tuple)
65
65
  end
66
66
 
67
67
  # query
68
68
  query = testcase['query'].map {|d|
69
- modifier = d["modifier"] == "all" ? :all : :each
70
- DataExpr.new(d["name"], modifier)
69
+ if d.kind_of?(Hash)
70
+ modifier = d["modifier"] == "all" ? :all : :each
71
+ DataExpr.new(d["name"], modifier)
72
+ else
73
+ DocumentTransformer.new.apply(
74
+ DocumentParser.new.expr.parse(d)
75
+ )
76
+ end
71
77
  }
72
78
 
73
79
  # results
74
80
  results = testcase['results'].map {|res|
75
81
  res.map {|name|
76
82
  if name.kind_of?(Array)
77
- name.map {|n| Tuple[:data].new(name: n, domain: 'test') }
83
+ name.map {|n| Tuple[:data].new(name: n, domain: 'test', location: Location[n]) }
78
84
  else
79
- Tuple[:data].new(name: name, domain: 'test')
85
+ Tuple[:data].new(name: name, domain: 'test', location: Location[name])
80
86
  end
81
87
  }
82
88
  }
@@ -4,7 +4,7 @@ case1:
4
4
  - 2.a
5
5
  - 3.a
6
6
  query:
7
- - { name: 1.a }
7
+ - "'1.a'"
8
8
  results:
9
9
  - [ 1.a ]
10
10
 
@@ -14,7 +14,7 @@ case2:
14
14
  - 2.a
15
15
  - 3.a
16
16
  query:
17
- - { name: "*.a" }
17
+ - "'*.a'"
18
18
  results:
19
19
  - [ 1.a ]
20
20
  - [ 2.a ]
@@ -26,7 +26,7 @@ case3:
26
26
  - 2.a
27
27
  - 3.a
28
28
  query:
29
- - { name: "*.a", modifier: all}
29
+ - "'*.a'.all"
30
30
  results:
31
31
  - [ [1.a, 2.a, 3.a] ]
32
32
 
@@ -39,8 +39,8 @@ case4:
39
39
  - 3.a
40
40
  - 3.b
41
41
  query:
42
- - { name: "*.a" }
43
- - { name: "{$*}.b" }
42
+ - "'*.a'"
43
+ - "'{$*}.b'"
44
44
  results:
45
45
  - [ 1.a, 1.b ]
46
46
  - [ 2.a, 2.b ]
@@ -55,8 +55,8 @@ case5:
55
55
  - 3.a
56
56
  - 3.b
57
57
  query:
58
- - { name: "*.a", modifier: all }
59
- - { name: "*.b" }
58
+ - "'*.a'.all"
59
+ - "'*.b'"
60
60
  results:
61
61
  - [ [1.a, 2.a, 3.a], 1.b ]
62
62
  - [ [1.a, 2.a, 3.a], 2.b ]
@@ -71,8 +71,8 @@ case6:
71
71
  - 3.a
72
72
  - 3.b
73
73
  query:
74
- - { name: "*.a" }
75
- - { name: "*.b", modifier: all }
74
+ - "'*.a'"
75
+ - "'*.b'.all"
76
76
  results:
77
77
  - [ 1.a, [1.b, 2.b, 3.b] ]
78
78
  - [ 2.a, [1.b, 2.b, 3.b] ]
@@ -87,8 +87,8 @@ case7:
87
87
  - 3.a
88
88
  - 3.b
89
89
  query:
90
- - { name: "*.a", modifier: all }
91
- - { name: "*.b", modifier: all }
90
+ - "'*.a'.all"
91
+ - "'*.b'.all"
92
92
  results:
93
93
  - [ [1.a, 2.a, 3.a], [1.b, 2.b, 3.b] ]
94
94
 
@@ -101,8 +101,8 @@ case8:
101
101
  - 3.a
102
102
  - 3.b
103
103
  query:
104
- - { name: "*.a" }
105
- - { name: "*.b" }
104
+ - "'*.a'"
105
+ - "'*.b'"
106
106
  results:
107
107
  - [ 1.a, 1.b ]
108
108
  - [ 1.a, 2.b ]
@@ -113,3 +113,32 @@ case8:
113
113
  - [ 3.a, 1.b ]
114
114
  - [ 3.a, 2.b ]
115
115
  - [ 3.a, 3.b ]
116
+
117
+ case9:
118
+ tuples:
119
+ - 1.a
120
+ - 2.a
121
+ - 3.a
122
+ query:
123
+ - "'*.a'"
124
+ - "'*.b' or null"
125
+ results:
126
+ - [ 1.a, [] ]
127
+ - [ 2.a, [] ]
128
+ - [ 3.a, [] ]
129
+
130
+ case10:
131
+ tuples:
132
+ - 1.a
133
+ - 1.b
134
+ - 2.a
135
+ - 2.b
136
+ - 3.a
137
+ - 3.b
138
+ query:
139
+ - "'*.a'"
140
+ - "'*.b'.all or null"
141
+ results:
142
+ - [ 1.a, [1.b, 2.b, 3.b] ]
143
+ - [ 2.a, [1.b, 2.b, 3.b] ]
144
+ - [ 3.a, [1.b, 2.b, 3.b] ]