sflkit 0.5.4__tar.gz → 0.5.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. {sflkit-0.5.4/src/sflkit.egg-info → sflkit-0.5.5}/PKG-INFO +1 -1
  2. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/__init__.py +1 -1
  3. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/analysis/spectra.py +7 -1
  4. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/instrumentation/file_instrumentation.py +6 -1
  5. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/language/meta.py +45 -19
  6. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/language/python/factory.py +188 -6
  7. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/language/visitor.py +2 -1
  8. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/model/parallel.py +10 -10
  9. {sflkit-0.5.4 → sflkit-0.5.5/src/sflkit.egg-info}/PKG-INFO +1 -1
  10. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit.egg-info/SOURCES.txt +1 -0
  11. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_analysis_objects.py +4 -1
  12. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_config.py +4 -1
  13. sflkit-0.5.5/tests/test_expression.py +181 -0
  14. {sflkit-0.5.4 → sflkit-0.5.5}/LICENSE +0 -0
  15. {sflkit-0.5.4 → sflkit-0.5.5}/README.md +0 -0
  16. {sflkit-0.5.4 → sflkit-0.5.5}/pyproject.toml +0 -0
  17. {sflkit-0.5.4 → sflkit-0.5.5}/setup.cfg +0 -0
  18. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/analysis/__init__.py +0 -0
  19. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/analysis/analysis_type.py +0 -0
  20. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/analysis/analyzer.py +0 -0
  21. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/analysis/factory.py +0 -0
  22. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/analysis/mapping.py +0 -0
  23. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/analysis/predicate.py +0 -0
  24. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/analysis/similarity.py +0 -0
  25. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/analysis/suggestion.py +0 -0
  26. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/cli.py +0 -0
  27. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/color.py +0 -0
  28. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/config.py +0 -0
  29. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/evaluation.py +0 -0
  30. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/events/__init__.py +0 -0
  31. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/events/event_file.py +0 -0
  32. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/events/mapping.py +0 -0
  33. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/features/__init__.py +0 -0
  34. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/features/handler.py +0 -0
  35. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/features/value.py +0 -0
  36. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/features/vector.py +0 -0
  37. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/instrumentation/__init__.py +0 -0
  38. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/instrumentation/dir_instrumentation.py +0 -0
  39. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/language/__init__.py +0 -0
  40. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/language/extract.py +0 -0
  41. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/language/finder.py +0 -0
  42. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/language/java/__init__.py +0 -0
  43. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/language/java/extract.py +0 -0
  44. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/language/java/factory.py +0 -0
  45. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/language/java/finder.py +0 -0
  46. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/language/java/visitor.py +0 -0
  47. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/language/language.py +0 -0
  48. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/language/python/__init__.py +0 -0
  49. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/language/python/extract.py +0 -0
  50. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/language/python/finder.py +0 -0
  51. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/language/python/visitor.py +0 -0
  52. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/logger.py +0 -0
  53. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/model/__init__.py +0 -0
  54. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/model/model.py +0 -0
  55. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/model/scope.py +0 -0
  56. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/runners/__init__.py +0 -0
  57. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/runners/run.py +0 -0
  58. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/weights/__init__.py +0 -0
  59. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/weights/analyzer.py +0 -0
  60. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit/weights/models.py +0 -0
  61. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit.egg-info/dependency_links.txt +0 -0
  62. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit.egg-info/entry_points.txt +0 -0
  63. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit.egg-info/requires.txt +0 -0
  64. {sflkit-0.5.4 → sflkit-0.5.5}/src/sflkit.egg-info/top_level.txt +0 -0
  65. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_analyzer.py +0 -0
  66. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_cli.py +0 -0
  67. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_color.py +0 -0
  68. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_coverage.py +0 -0
  69. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_dependency_weights.py +0 -0
  70. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_evaluation.py +0 -0
  71. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_events.py +0 -0
  72. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_execution.py +0 -0
  73. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_features.py +0 -0
  74. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_instrumentation.py +0 -0
  75. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_language.py +0 -0
  76. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_parallelization.py +0 -0
  77. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_predicates.py +0 -0
  78. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_runner.py +0 -0
  79. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_runner_parallel.py +0 -0
  80. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_runner_pytest_versions.py +0 -0
  81. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_scope.py +0 -0
  82. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_spectra.py +0 -0
  83. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_suggestions.py +0 -0
  84. {sflkit-0.5.4 → sflkit-0.5.5}/tests/test_visitors.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sflkit
3
- Version: 0.5.4
3
+ Version: 0.5.5
4
4
  Summary: SFLKit: : A Workbench for Statistical Fault Localization
5
5
  Author-email: Marius Smytzek <marius.smytzek@cispa.de>
6
6
  Project-URL: Homepage, https://github.com/smythi93/sflkit/
@@ -6,7 +6,7 @@ from sflkit.config import Config, parse_config
6
6
  from sflkit.instrumentation.dir_instrumentation import DirInstrumentation
7
7
 
8
8
 
9
- __version__ = "0.5.4"
9
+ __version__ = "0.5.5"
10
10
 
11
11
 
12
12
  def instrument_config(conf: Config):
@@ -722,7 +722,13 @@ class DefUse(Spectrum):
722
722
 
723
723
  @staticmethod
724
724
  def events():
725
- return [EventType.DEF, EventType.USE]
725
+ return [
726
+ EventType.DEF,
727
+ EventType.USE,
728
+ EventType.FUNCTION_ENTER,
729
+ EventType.FUNCTION_EXIT,
730
+ EventType.FUNCTION_ERROR,
731
+ ]
726
732
 
727
733
  def get_suggestion(
728
734
  self, metric: Callable = None, base_dir: str = "", use_weight: bool = False
@@ -1,3 +1,4 @@
1
+ import os
1
2
  from pathlib import Path
2
3
  from typing import List, Optional
3
4
 
@@ -11,7 +12,11 @@ class FileInstrumentation(Instrumentation):
11
12
  super().__init__(visitor, mapping_path)
12
13
 
13
14
  def instrument(
14
- self, src: str, dst: str, suffixes: List[str] = None, file: str = ""
15
+ self,
16
+ src: os.PathLike,
17
+ dst: os.PathLike,
18
+ suffixes: List[str] = None,
19
+ file: str = "",
15
20
  ):
16
21
  self.visitor.instrument(src, dst, file)
17
22
  self.events = EventMapping(
@@ -88,6 +88,7 @@ class MetaVisitor(ABC):
88
88
  event_id_generator: IDGenerator,
89
89
  function_id_generator: IDGenerator,
90
90
  tmp_generator: TmpGenerator,
91
+ order: int = 0,
91
92
  **kwargs,
92
93
  ):
93
94
  self.event_id_generator = event_id_generator
@@ -98,6 +99,27 @@ class MetaVisitor(ABC):
98
99
  self.condition_extract = language.condition_extract
99
100
  self.event_count = 0
100
101
  self.file = None
102
+ self.order = order
103
+
104
+ def __lt__(self, other):
105
+ if not isinstance(other, MetaVisitor):
106
+ raise TypeError(f"Cannot compare MetaVisitor with {type(other)}")
107
+ return self.order < other.order
108
+
109
+ def __gt__(self, other):
110
+ if not isinstance(other, MetaVisitor):
111
+ raise TypeError(f"Cannot compare MetaVisitor with {type(other)}")
112
+ return self.order > other.order
113
+
114
+ def __le__(self, other):
115
+ if not isinstance(other, MetaVisitor):
116
+ raise TypeError(f"Cannot compare MetaVisitor with {type(other)}")
117
+ return self.order <= other.order
118
+
119
+ def __ge__(self, other):
120
+ if not isinstance(other, MetaVisitor):
121
+ raise TypeError(f"Cannot compare MetaVisitor with {type(other)}")
122
+ return self.order >= other.order
101
123
 
102
124
  def get_event_call(self, event: Event):
103
125
  pass
@@ -148,26 +170,30 @@ class CombinationVisitor(MetaVisitor):
148
170
  tmp_generator,
149
171
  )
150
172
  if test:
151
- self.visitors = [
152
- visitor(
153
- language,
154
- event_id_generator,
155
- function_id_generator,
156
- tmp_generator,
157
- ignore_inner=ignore_inner,
158
- )
159
- for visitor in visitors
160
- ]
173
+ self.visitors = sorted(
174
+ [
175
+ visitor(
176
+ language,
177
+ event_id_generator,
178
+ function_id_generator,
179
+ tmp_generator,
180
+ ignore_inner=ignore_inner,
181
+ )
182
+ for visitor in visitors
183
+ ],
184
+ )
161
185
  else:
162
- self.visitors = [
163
- visitor(
164
- language,
165
- event_id_generator,
166
- function_id_generator,
167
- tmp_generator,
168
- )
169
- for visitor in visitors
170
- ]
186
+ self.visitors = sorted(
187
+ [
188
+ visitor(
189
+ language,
190
+ event_id_generator,
191
+ function_id_generator,
192
+ tmp_generator,
193
+ )
194
+ for visitor in visitors
195
+ ],
196
+ )
171
197
 
172
198
  def visit_start(self, *args) -> Injection:
173
199
  injections = Injection()
@@ -56,10 +56,15 @@ class PythonEventFactory(MetaVisitor, NodeVisitor):
56
56
  event_id_generator: IDGenerator,
57
57
  function_id_generator: IDGenerator,
58
58
  tmp_generator: TmpGenerator,
59
+ order: int = 0,
59
60
  **kwargs,
60
61
  ):
61
62
  super().__init__(
62
- language, event_id_generator, function_id_generator, tmp_generator
63
+ language,
64
+ event_id_generator,
65
+ function_id_generator,
66
+ tmp_generator,
67
+ order=order,
63
68
  )
64
69
 
65
70
  def visit_start(self, *args) -> Injection:
@@ -291,7 +296,21 @@ class DefEventFactory(PythonEventFactory):
291
296
  def visit_AsyncFunctionDef(self, node: AsyncFunctionDef) -> Injection:
292
297
  return self.visit_function(node)
293
298
 
294
- def get_event(self, node: typing.Union[Assign, AnnAssign, AugAssign], var: str):
299
+ def get_event(
300
+ self,
301
+ node: typing.Union[
302
+ Assign,
303
+ AnnAssign,
304
+ AugAssign,
305
+ FunctionDef,
306
+ AsyncFunctionDef,
307
+ For,
308
+ AsyncFor,
309
+ With,
310
+ AsyncWith,
311
+ ],
312
+ var: str,
313
+ ):
295
314
  return DefEvent(
296
315
  self.file, node.lineno, self.event_id_generator.get_next_id(), var
297
316
  )
@@ -369,18 +388,24 @@ class FunctionEventFactory(PythonEventFactory):
369
388
  event_id_generator: IDGenerator,
370
389
  function_id_generator: IDGenerator,
371
390
  tmp_generator: TmpGenerator,
391
+ order: int,
372
392
  **kwargs,
373
393
  ):
374
394
  super().__init__(
375
- language, event_id_generator, function_id_generator, tmp_generator, **kwargs
395
+ language,
396
+ event_id_generator,
397
+ function_id_generator,
398
+ tmp_generator,
399
+ order=order,
400
+ **kwargs,
376
401
  )
377
402
  self.function_stack = list()
378
403
 
379
404
  def get_function_id(self, node: AST) -> int:
380
405
  if node not in FunctionEventFactory.functions:
381
- FunctionEventFactory.functions[
382
- node
383
- ] = self.function_id_generator.get_next_id()
406
+ FunctionEventFactory.functions[node] = (
407
+ self.function_id_generator.get_next_id()
408
+ )
384
409
  return FunctionEventFactory.functions[node]
385
410
 
386
411
  @staticmethod
@@ -403,6 +428,23 @@ class FunctionEventFactory(PythonEventFactory):
403
428
 
404
429
 
405
430
  class FunctionEnterEventFactory(FunctionEventFactory):
431
+ def __init__(
432
+ self,
433
+ language,
434
+ event_id_generator: IDGenerator,
435
+ function_id_generator: IDGenerator,
436
+ tmp_generator: TmpGenerator,
437
+ **kwargs,
438
+ ):
439
+ super().__init__(
440
+ language,
441
+ event_id_generator,
442
+ function_id_generator,
443
+ tmp_generator,
444
+ order=-2,
445
+ **kwargs,
446
+ )
447
+
406
448
  def get_function(self):
407
449
  return "add_function_enter_event"
408
450
 
@@ -441,6 +483,23 @@ class FunctionEnterEventFactory(FunctionEventFactory):
441
483
 
442
484
 
443
485
  class FunctionExitEventFactor(FunctionEventFactory):
486
+ def __init__(
487
+ self,
488
+ language,
489
+ event_id_generator: IDGenerator,
490
+ function_id_generator: IDGenerator,
491
+ tmp_generator: TmpGenerator,
492
+ **kwargs,
493
+ ):
494
+ super().__init__(
495
+ language,
496
+ event_id_generator,
497
+ function_id_generator,
498
+ tmp_generator,
499
+ order=2,
500
+ **kwargs,
501
+ )
502
+
444
503
  def get_function(self):
445
504
  return "add_function_exit_event"
446
505
 
@@ -521,6 +580,23 @@ class FunctionExitEventFactor(FunctionEventFactory):
521
580
 
522
581
 
523
582
  class FunctionErrorEventFactory(FunctionEventFactory):
583
+ def __init__(
584
+ self,
585
+ language,
586
+ event_id_generator: IDGenerator,
587
+ function_id_generator: IDGenerator,
588
+ tmp_generator: TmpGenerator,
589
+ **kwargs,
590
+ ):
591
+ super().__init__(
592
+ language,
593
+ event_id_generator,
594
+ function_id_generator,
595
+ tmp_generator,
596
+ order=2,
597
+ **kwargs,
598
+ )
599
+
524
600
  def get_function(self):
525
601
  return "add_function_error_event"
526
602
 
@@ -550,6 +626,24 @@ class LoopEventFactory(PythonEventFactory):
550
626
  loops: typing.Dict[AST, int] = dict()
551
627
  loop_id: int = 0
552
628
 
629
+ def __init__(
630
+ self,
631
+ language,
632
+ event_id_generator: IDGenerator,
633
+ function_id_generator: IDGenerator,
634
+ tmp_generator: TmpGenerator,
635
+ order: int,
636
+ **kwargs,
637
+ ):
638
+ super().__init__(
639
+ language,
640
+ event_id_generator,
641
+ function_id_generator,
642
+ tmp_generator,
643
+ order=order,
644
+ **kwargs,
645
+ )
646
+
553
647
  @staticmethod
554
648
  def get_loop_id(node: AST) -> int:
555
649
  if node not in LoopEventFactory.loops:
@@ -571,6 +665,23 @@ class LoopEventFactory(PythonEventFactory):
571
665
 
572
666
 
573
667
  class LoopBeginEventFactory(LoopEventFactory):
668
+ def __init__(
669
+ self,
670
+ language,
671
+ event_id_generator: IDGenerator,
672
+ function_id_generator: IDGenerator,
673
+ tmp_generator: TmpGenerator,
674
+ **kwargs,
675
+ ):
676
+ super().__init__(
677
+ language,
678
+ event_id_generator,
679
+ function_id_generator,
680
+ tmp_generator,
681
+ order=-1,
682
+ **kwargs,
683
+ )
684
+
574
685
  def get_function(self):
575
686
  return "add_loop_begin_event"
576
687
 
@@ -587,6 +698,23 @@ class LoopBeginEventFactory(LoopEventFactory):
587
698
 
588
699
 
589
700
  class LoopHitEventFactory(LoopEventFactory):
701
+ def __init__(
702
+ self,
703
+ language,
704
+ event_id_generator: IDGenerator,
705
+ function_id_generator: IDGenerator,
706
+ tmp_generator: TmpGenerator,
707
+ **kwargs,
708
+ ):
709
+ super().__init__(
710
+ language,
711
+ event_id_generator,
712
+ function_id_generator,
713
+ tmp_generator,
714
+ order=-1,
715
+ **kwargs,
716
+ )
717
+
590
718
  def get_function(self):
591
719
  return "add_loop_hit_event"
592
720
 
@@ -603,6 +731,23 @@ class LoopHitEventFactory(LoopEventFactory):
603
731
 
604
732
 
605
733
  class LoopEndEventFactory(LoopEventFactory):
734
+ def __init__(
735
+ self,
736
+ language,
737
+ event_id_generator: IDGenerator,
738
+ function_id_generator: IDGenerator,
739
+ tmp_generator: TmpGenerator,
740
+ **kwargs,
741
+ ):
742
+ super().__init__(
743
+ language,
744
+ event_id_generator,
745
+ function_id_generator,
746
+ tmp_generator,
747
+ order=1,
748
+ **kwargs,
749
+ )
750
+
606
751
  def get_function(self):
607
752
  return "add_loop_end_event"
608
753
 
@@ -717,6 +862,7 @@ class UseEventFactory(PythonEventFactory):
717
862
  return self._get_try_wrapper(event)
718
863
 
719
864
  def get_event(self, node: AST, use: str) -> UseEvent:
865
+ # noinspection PyUnresolvedReferences
720
866
  return UseEvent(
721
867
  self.file, node.lineno, self.event_id_generator.get_next_id(), use
722
868
  )
@@ -894,6 +1040,23 @@ class LenEventFactory(DefEventFactory):
894
1040
 
895
1041
 
896
1042
  class TestStartEventFactory(FunctionEventFactory):
1043
+ def __init__(
1044
+ self,
1045
+ language,
1046
+ event_id_generator: IDGenerator,
1047
+ function_id_generator: IDGenerator,
1048
+ tmp_generator: TmpGenerator,
1049
+ **kwargs,
1050
+ ):
1051
+ super().__init__(
1052
+ language,
1053
+ event_id_generator,
1054
+ function_id_generator,
1055
+ tmp_generator,
1056
+ order=2,
1057
+ **kwargs,
1058
+ )
1059
+
897
1060
  def get_function(self):
898
1061
  return "add_test_start_event"
899
1062
 
@@ -924,6 +1087,23 @@ class TestStartEventFactory(FunctionEventFactory):
924
1087
 
925
1088
 
926
1089
  class TestEndEventFactory(FunctionEventFactory):
1090
+ def __init__(
1091
+ self,
1092
+ language,
1093
+ event_id_generator: IDGenerator,
1094
+ function_id_generator: IDGenerator,
1095
+ tmp_generator: TmpGenerator,
1096
+ **kwargs,
1097
+ ):
1098
+ super().__init__(
1099
+ language,
1100
+ event_id_generator,
1101
+ function_id_generator,
1102
+ tmp_generator,
1103
+ order=2,
1104
+ **kwargs,
1105
+ )
1106
+
927
1107
  def get_function(self):
928
1108
  return "add_test_end_event"
929
1109
 
@@ -991,6 +1171,7 @@ class TestLineEventFactory(LineEventFactory):
991
1171
  return "add_test_line_event"
992
1172
 
993
1173
  def visit_line(self, node: AST) -> Injection:
1174
+ # noinspection PyUnresolvedReferences
994
1175
  line_event = TestLineEvent(
995
1176
  self.file, node.lineno, self.event_id_generator.get_next_id()
996
1177
  )
@@ -1113,6 +1294,7 @@ class TestUseEventFactory(UseEventFactory):
1113
1294
  return "add_test_use_event"
1114
1295
 
1115
1296
  def get_event(self, node: AST, use: str) -> TestUseEvent:
1297
+ # noinspection PyUnresolvedReferences
1116
1298
  return TestUseEvent(
1117
1299
  self.file, node.lineno, self.event_id_generator.get_next_id(), use
1118
1300
  )
@@ -1,3 +1,4 @@
1
+ import os
1
2
  from abc import abstractmethod, ABC
2
3
 
3
4
  from sflkit.language.meta import MetaVisitor
@@ -22,7 +23,7 @@ class ASTVisitor(ABC):
22
23
  def start_visit(self, ast):
23
24
  raise NotImplementedError()
24
25
 
25
- def instrument(self, src: str, dst: str, file: str = ""):
26
+ def instrument(self, src: os.PathLike, dst: os.PathLike, file: str = ""):
26
27
  self.file = file
27
28
  with open(src, "r") as fp:
28
29
  source = fp.read()
@@ -1,15 +1,11 @@
1
- from typing import Optional, Set
2
-
3
1
  from sflkitlib.events.event import (
4
2
  FunctionEnterEvent,
5
3
  FunctionExitEvent,
6
4
  FunctionErrorEvent,
7
5
  DefEvent,
8
6
  UseEvent,
9
- Event,
10
7
  )
11
8
 
12
- from sflkit.analysis.analysis_type import AnalysisObject
13
9
  from sflkit.events.event_file import EventFile
14
10
  from sflkit.model.model import Model
15
11
  from sflkit.model.scope import Scope
@@ -89,11 +85,15 @@ class ParallelModel(Model):
89
85
  )
90
86
 
91
87
  def enter_parallel_scope(self, thread_id: int, event_file: EventFile):
92
- self.variables_map[event_file][thread_id] = self.variables_map.get(
93
- thread_id, self.variables
94
- ).enter()
88
+ self.variables_map[event_file][thread_id] = (
89
+ self.variables_map[event_file]
90
+ .get(thread_id, self.variables[event_file])
91
+ .enter()
92
+ )
95
93
 
96
94
  def exit_parallel_scope(self, thread_id: int, event_file: EventFile):
97
- self.variables_map[event_file][thread_id] = self.variables_map.get(
98
- thread_id, self.variables
99
- ).exit()
95
+ self.variables_map[event_file][thread_id] = (
96
+ self.variables_map[event_file]
97
+ .get(thread_id, self.variables[event_file])
98
+ .exit()
99
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sflkit
3
- Version: 0.5.4
3
+ Version: 0.5.5
4
4
  Summary: SFLKit: : A Workbench for Statistical Fault Localization
5
5
  Author-email: Marius Smytzek <marius.smytzek@cispa.de>
6
6
  Project-URL: Homepage, https://github.com/smythi93/sflkit/
@@ -67,6 +67,7 @@ tests/test_dependency_weights.py
67
67
  tests/test_evaluation.py
68
68
  tests/test_events.py
69
69
  tests/test_execution.py
70
+ tests/test_expression.py
70
71
  tests/test_features.py
71
72
  tests/test_instrumentation.py
72
73
  tests/test_language.py
@@ -86,9 +86,12 @@ class TestAnalysisObjects(BaseTest):
86
86
  self.assertEqual(2, obj.use_line)
87
87
  self.assertEqual("x", obj.var)
88
88
  self.assertEqual(AnalysisType.DEF_USE, obj.analysis_type())
89
- self.assertEqual(2, len(obj.events()))
89
+ self.assertEqual(5, len(obj.events()))
90
90
  self.assertIn(EventType.DEF, obj.events())
91
91
  self.assertIn(EventType.USE, obj.events())
92
+ self.assertIn(EventType.FUNCTION_ENTER, obj.events())
93
+ self.assertIn(EventType.FUNCTION_EXIT, obj.events())
94
+ self.assertIn(EventType.FUNCTION_ERROR, obj.events())
92
95
 
93
96
  def test_condition(self):
94
97
  obj = Condition(self.ACCESS, 1, "x < y")
@@ -63,9 +63,12 @@ class ConfigTests(unittest.TestCase):
63
63
  )
64
64
  self.assertEqual(Path("test", "path"), config.target_path)
65
65
  self.assertEqual(Language.PYTHON, config.language)
66
- self.assertEqual(2, len(config.events))
66
+ self.assertEqual(5, len(config.events))
67
67
  self.assertIn(EventType.DEF, config.events)
68
68
  self.assertIn(EventType.USE, config.events)
69
+ self.assertIn(EventType.FUNCTION_ENTER, config.events)
70
+ self.assertIn(EventType.FUNCTION_EXIT, config.events)
71
+ self.assertIn(EventType.FUNCTION_ERROR, config.events)
69
72
  self.assertEqual(1, len(config.predicates))
70
73
  self.assertIn(AnalysisType.DEF_USE, config.predicates)
71
74
  self.assertEqual(1, len(config.factory.factories))
@@ -0,0 +1,181 @@
1
+ import os
2
+
3
+ from sflkit import Analyzer
4
+ from sflkit.analysis.analysis_type import AnalysisType
5
+ from sflkit.analysis.spectra import DefUse
6
+ from utils import BaseTest
7
+
8
+
9
+ class ExpressionTest(BaseTest):
10
+ EXPRESSIONS = "expressions"
11
+
12
+ def test_expression(self):
13
+ config, relevant_event_files, irrelevant_event_files = (
14
+ self.run_analysis_event_files(
15
+ self.EXPRESSIONS,
16
+ events="",
17
+ predicates="def_use",
18
+ relevant=[["2 - 3"], ["2 * (1 - 1)"]],
19
+ irrelevant=[
20
+ ["2 + 3"],
21
+ ["5 / 6"],
22
+ ["1 + (2 * 3)"],
23
+ ["(1 + 2) * 3"],
24
+ ["1 + 1"],
25
+ ["1 - 0"],
26
+ ["~ 4"],
27
+ ],
28
+ access="evaluate.py",
29
+ )
30
+ )
31
+ analyzer = Analyzer(
32
+ relevant_event_files, irrelevant_event_files, config.factory, workers=1
33
+ )
34
+ analyzer.analyze()
35
+ expected_def_use = {
36
+ # evaluate.py
37
+ ("arg", "evaluate.py", 7): {
38
+ ("evaluate.py", 8),
39
+ },
40
+ ("term", "evaluate.py", 8): {
41
+ ("evaluate.py", 9),
42
+ },
43
+ ("result", "evaluate.py", 9): {
44
+ ("evaluate.py", 10),
45
+ },
46
+ # expr/parse.py
47
+ # parse()
48
+ ("s", os.path.join("expr", "parse.py"), 15): {
49
+ (os.path.join("expr", "parse.py"), 16),
50
+ },
51
+ ("s", os.path.join("expr", "parse.py"), 16): {
52
+ (os.path.join("expr", "parse.py"), 17),
53
+ },
54
+ ("s", os.path.join("expr", "parse.py"), 17): {
55
+ (os.path.join("expr", "parse.py"), 18),
56
+ (os.path.join("expr", "parse.py"), 19),
57
+ (os.path.join("expr", "parse.py"), 20),
58
+ },
59
+ ("s", os.path.join("expr", "parse.py"), 19): {
60
+ (os.path.join("expr", "parse.py"), 18),
61
+ },
62
+ ("s", os.path.join("expr", "parse.py"), 19): {
63
+ (os.path.join("expr", "parse.py"), 20),
64
+ },
65
+ ("s", os.path.join("expr", "parse.py"), 20): {
66
+ (os.path.join("expr", "parse.py"), 21),
67
+ },
68
+ ("tokens", os.path.join("expr", "parse.py"), 21): {
69
+ (os.path.join("expr", "parse.py"), 22),
70
+ (os.path.join("expr", "parse.py"), 23),
71
+ (os.path.join("expr", "parse.py"), 24),
72
+ },
73
+ ("term", os.path.join("expr", "parse.py"), 23): {
74
+ (os.path.join("expr", "parse.py"), 25),
75
+ },
76
+ # parse_terminal()
77
+ ("tokens", os.path.join("expr", "parse.py"), 28): {
78
+ (os.path.join("expr", "parse.py"), 29),
79
+ (os.path.join("expr", "parse.py"), 33),
80
+ (os.path.join("expr", "parse.py"), 34),
81
+ },
82
+ ("token", os.path.join("expr", "parse.py"), 29): {
83
+ (os.path.join("expr", "parse.py"), 30),
84
+ (os.path.join("expr", "parse.py"), 31),
85
+ (os.path.join("expr", "parse.py"), 32),
86
+ },
87
+ ("term", os.path.join("expr", "parse.py"), 33): {
88
+ (os.path.join("expr", "parse.py"), 36),
89
+ },
90
+ ("token", os.path.join("expr", "parse.py"), 34): {
91
+ (os.path.join("expr", "parse.py"), 35),
92
+ },
93
+ # parse_neg()
94
+ ("tokens", os.path.join("expr", "parse.py"), 41): {
95
+ (os.path.join("expr", "parse.py"), 42),
96
+ (os.path.join("expr", "parse.py"), 43),
97
+ (os.path.join("expr", "parse.py"), 44),
98
+ },
99
+ ("term", os.path.join("expr", "parse.py"), 42): {
100
+ (os.path.join("expr", "parse.py"), 45),
101
+ (os.path.join("expr", "parse.py"), 47),
102
+ },
103
+ # parse_mul_div()
104
+ ("tokens", os.path.join("expr", "parse.py"), 50): {
105
+ (os.path.join("expr", "parse.py"), 51),
106
+ (os.path.join("expr", "parse.py"), 52),
107
+ (os.path.join("expr", "parse.py"), 53),
108
+ (os.path.join("expr", "parse.py"), 55),
109
+ (os.path.join("expr", "parse.py"), 57),
110
+ },
111
+ ("term", os.path.join("expr", "parse.py"), 51): {
112
+ (os.path.join("expr", "parse.py"), 55),
113
+ (os.path.join("expr", "parse.py"), 57),
114
+ (os.path.join("expr", "parse.py"), 59),
115
+ },
116
+ ("token", os.path.join("expr", "parse.py"), 53): {
117
+ (os.path.join("expr", "parse.py"), 54),
118
+ },
119
+ # parse_add_sub()
120
+ ("tokens", os.path.join("expr", "parse.py"), 62): {
121
+ (os.path.join("expr", "parse.py"), 63),
122
+ (os.path.join("expr", "parse.py"), 64),
123
+ (os.path.join("expr", "parse.py"), 65),
124
+ (os.path.join("expr", "parse.py"), 67),
125
+ (os.path.join("expr", "parse.py"), 69),
126
+ },
127
+ ("term", os.path.join("expr", "parse.py"), 63): {
128
+ (os.path.join("expr", "parse.py"), 67),
129
+ (os.path.join("expr", "parse.py"), 69),
130
+ (os.path.join("expr", "parse.py"), 71),
131
+ },
132
+ ("token", os.path.join("expr", "parse.py"), 65): {
133
+ (os.path.join("expr", "parse.py"), 66),
134
+ },
135
+ # expr/arithmetic.py
136
+ # Binary.__init__()
137
+ ("left", os.path.join("expr", "arithmetic.py"), 7): {
138
+ (os.path.join("expr", "arithmetic.py"), 8),
139
+ },
140
+ ("right", os.path.join("expr", "arithmetic.py"), 7): {
141
+ (os.path.join("expr", "arithmetic.py"), 9),
142
+ },
143
+ ("self.left", os.path.join("expr", "arithmetic.py"), 8): {
144
+ (os.path.join("expr", "arithmetic.py"), 14),
145
+ (os.path.join("expr", "arithmetic.py"), 19),
146
+ (os.path.join("expr", "arithmetic.py"), 24),
147
+ (os.path.join("expr", "arithmetic.py"), 29),
148
+ },
149
+ ("self.right", os.path.join("expr", "arithmetic.py"), 9): {
150
+ (os.path.join("expr", "arithmetic.py"), 14),
151
+ (os.path.join("expr", "arithmetic.py"), 19),
152
+ (os.path.join("expr", "arithmetic.py"), 24),
153
+ (os.path.join("expr", "arithmetic.py"), 29),
154
+ },
155
+ # Neg.__init__()
156
+ ("term", os.path.join("expr", "arithmetic.py"), 33): {
157
+ (os.path.join("expr", "arithmetic.py"), 34),
158
+ },
159
+ ("self.term", os.path.join("expr", "arithmetic.py"), 34): {
160
+ (os.path.join("expr", "arithmetic.py"), 37),
161
+ },
162
+ # Constant.__init__()
163
+ ("value", os.path.join("expr", "arithmetic.py"), 41): {
164
+ (os.path.join("expr", "arithmetic.py"), 42),
165
+ },
166
+ ("self.value", os.path.join("expr", "arithmetic.py"), 42): {
167
+ (os.path.join("expr", "arithmetic.py"), 45),
168
+ },
169
+ }
170
+
171
+ actual = {}
172
+
173
+ for analysis in analyzer.get_analysis_by_type(AnalysisType.DEF_USE):
174
+ if not isinstance(analysis, DefUse):
175
+ continue
176
+ key = (analysis.var, analysis.file, analysis.line)
177
+ if key not in actual:
178
+ actual[key] = set()
179
+ actual[key].add((analysis.use_file, analysis.use_line))
180
+
181
+ self.assertEqual(expected_def_use, actual)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes