sflkit 0.5.4__tar.gz → 0.5.6__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.
- {sflkit-0.5.4/src/sflkit.egg-info → sflkit-0.5.6}/PKG-INFO +1 -1
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/__init__.py +1 -2
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/analysis/spectra.py +7 -1
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/instrumentation/file_instrumentation.py +6 -1
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/language/meta.py +45 -19
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/language/python/factory.py +188 -6
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/language/visitor.py +2 -1
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/model/parallel.py +10 -10
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/runners/run.py +1 -1
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/weights/__init__.py +2 -2
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/weights/analyzer.py +5 -3
- {sflkit-0.5.4 → sflkit-0.5.6/src/sflkit.egg-info}/PKG-INFO +1 -1
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit.egg-info/SOURCES.txt +1 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_analysis_objects.py +4 -1
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_config.py +4 -1
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_dependency_weights.py +8 -8
- sflkit-0.5.6/tests/test_expression.py +181 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_runner_parallel.py +3 -1
- {sflkit-0.5.4 → sflkit-0.5.6}/LICENSE +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/README.md +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/pyproject.toml +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/setup.cfg +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/analysis/__init__.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/analysis/analysis_type.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/analysis/analyzer.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/analysis/factory.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/analysis/mapping.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/analysis/predicate.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/analysis/similarity.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/analysis/suggestion.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/cli.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/color.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/config.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/evaluation.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/events/__init__.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/events/event_file.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/events/mapping.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/features/__init__.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/features/handler.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/features/value.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/features/vector.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/instrumentation/__init__.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/instrumentation/dir_instrumentation.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/language/__init__.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/language/extract.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/language/finder.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/language/java/__init__.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/language/java/extract.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/language/java/factory.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/language/java/finder.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/language/java/visitor.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/language/language.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/language/python/__init__.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/language/python/extract.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/language/python/finder.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/language/python/visitor.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/logger.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/model/__init__.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/model/model.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/model/scope.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/runners/__init__.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit/weights/models.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit.egg-info/dependency_links.txt +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit.egg-info/entry_points.txt +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit.egg-info/requires.txt +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/src/sflkit.egg-info/top_level.txt +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_analyzer.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_cli.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_color.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_coverage.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_evaluation.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_events.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_execution.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_features.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_instrumentation.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_language.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_parallelization.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_predicates.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_runner.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_runner_pytest_versions.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_scope.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_spectra.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_suggestions.py +0 -0
- {sflkit-0.5.4 → sflkit-0.5.6}/tests/test_visitors.py +0 -0
|
@@ -5,8 +5,7 @@ from sflkit.analysis.analyzer import Analyzer
|
|
|
5
5
|
from sflkit.config import Config, parse_config
|
|
6
6
|
from sflkit.instrumentation.dir_instrumentation import DirInstrumentation
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
__version__ = "0.5.4"
|
|
8
|
+
__version__ = "0.5.6"
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
def instrument_config(conf: Config):
|
|
@@ -722,7 +722,13 @@ class DefUse(Spectrum):
|
|
|
722
722
|
|
|
723
723
|
@staticmethod
|
|
724
724
|
def events():
|
|
725
|
-
return [
|
|
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,
|
|
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
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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,
|
|
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(
|
|
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,
|
|
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
|
-
|
|
383
|
-
|
|
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:
|
|
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] =
|
|
93
|
-
|
|
94
|
-
|
|
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] =
|
|
98
|
-
|
|
99
|
-
|
|
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
|
+
)
|
|
@@ -666,7 +666,7 @@ class ParallelInputRunner(InputRunner):
|
|
|
666
666
|
|
|
667
667
|
with ProcessPoolExecutor(max_workers=self.workers) as executor:
|
|
668
668
|
# Consume the iterator to ensure all tasks complete
|
|
669
|
-
executor.map(self.process_test, tests)
|
|
669
|
+
list(executor.map(self.process_test, tests))
|
|
670
670
|
|
|
671
671
|
# Ensure all files are flushed to disk (helps with race conditions in CI)
|
|
672
672
|
os.sync()
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from sflkit.weights.analyzer import
|
|
1
|
+
from sflkit.weights.analyzer import ProximityAnalyzer
|
|
2
2
|
from sflkit.weights.models import (
|
|
3
3
|
TestTimeModel,
|
|
4
4
|
TestFunctionModel,
|
|
@@ -10,7 +10,7 @@ from sflkit.weights.models import (
|
|
|
10
10
|
)
|
|
11
11
|
|
|
12
12
|
__all__ = [
|
|
13
|
-
"
|
|
13
|
+
"ProximityAnalyzer",
|
|
14
14
|
"TestTimeModel",
|
|
15
15
|
"TestFunctionModel",
|
|
16
16
|
"TestLineModel",
|
|
@@ -12,7 +12,7 @@ from sflkit.events.event_file import EventFile
|
|
|
12
12
|
from sflkit.model.model import MetaModel
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
class
|
|
15
|
+
class ProximityAnalyzer(Analyzer):
|
|
16
16
|
def __init__(
|
|
17
17
|
self,
|
|
18
18
|
model_class: Type[TestTimeModel],
|
|
@@ -51,10 +51,12 @@ class TimeAnalyzer(Analyzer):
|
|
|
51
51
|
|
|
52
52
|
@staticmethod
|
|
53
53
|
def load_with_dependencies(path: os.PathLike, model_class: Type[TestTimeModel]):
|
|
54
|
-
return
|
|
54
|
+
return ProximityAnalyzer(
|
|
55
|
+
model_class, meta_model=MetaModel(load_analysis_json(path))
|
|
56
|
+
)
|
|
55
57
|
|
|
56
58
|
@staticmethod
|
|
57
59
|
def loads_with_dependencies(data: str, model_class: Type[TestTimeModel]):
|
|
58
|
-
return
|
|
60
|
+
return ProximityAnalyzer(
|
|
59
61
|
model_class, meta_model=MetaModel(set(map(deserialize, json.loads(data))))
|
|
60
62
|
)
|
|
@@ -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(
|
|
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(
|
|
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))
|
|
@@ -4,7 +4,7 @@ from pathlib import Path
|
|
|
4
4
|
from sflkit import Config, instrument_config
|
|
5
5
|
from sflkit.analysis.analysis_type import AnalysisType
|
|
6
6
|
from sflkit.analysis.suggestion import Location
|
|
7
|
-
from sflkit.weights.analyzer import
|
|
7
|
+
from sflkit.weights.analyzer import ProximityAnalyzer
|
|
8
8
|
from sflkit.weights.models import (
|
|
9
9
|
TestLineModel,
|
|
10
10
|
TestDefUseModel,
|
|
@@ -39,7 +39,7 @@ class TestTimeWeights(BaseTest):
|
|
|
39
39
|
output = Path(BaseTest.TEST_DIR, "events").absolute()
|
|
40
40
|
runner.run(Path(BaseTest.TEST_DIR), output, files=["test.py"])
|
|
41
41
|
mapping = EventMapping.load(config)
|
|
42
|
-
analyzer =
|
|
42
|
+
analyzer = ProximityAnalyzer(
|
|
43
43
|
TestFunctionModel,
|
|
44
44
|
[
|
|
45
45
|
EventFile(
|
|
@@ -82,7 +82,7 @@ class TestTimeWeights(BaseTest):
|
|
|
82
82
|
output = Path(BaseTest.TEST_DIR, "events").absolute()
|
|
83
83
|
runner.run(Path(BaseTest.TEST_DIR), output, files=["test.py"])
|
|
84
84
|
mapping = EventMapping.load(config)
|
|
85
|
-
analyzer =
|
|
85
|
+
analyzer = ProximityAnalyzer(
|
|
86
86
|
TestLineModel,
|
|
87
87
|
[
|
|
88
88
|
EventFile(
|
|
@@ -130,7 +130,7 @@ class TestTimeWeights(BaseTest):
|
|
|
130
130
|
output = Path(BaseTest.TEST_DIR, "events").absolute()
|
|
131
131
|
runner.run(Path(BaseTest.TEST_DIR), output, files=["test.py"])
|
|
132
132
|
mapping = EventMapping.load(config)
|
|
133
|
-
analyzer =
|
|
133
|
+
analyzer = ProximityAnalyzer(
|
|
134
134
|
TestDefUseModel,
|
|
135
135
|
[
|
|
136
136
|
EventFile(
|
|
@@ -178,7 +178,7 @@ class TestTimeWeights(BaseTest):
|
|
|
178
178
|
output = Path(BaseTest.TEST_DIR, "events").absolute()
|
|
179
179
|
runner.run(Path(BaseTest.TEST_DIR), output, files=["test.py"])
|
|
180
180
|
mapping = EventMapping.load(config)
|
|
181
|
-
analyzer =
|
|
181
|
+
analyzer = ProximityAnalyzer(
|
|
182
182
|
TestDefUsesModel,
|
|
183
183
|
[
|
|
184
184
|
EventFile(
|
|
@@ -225,7 +225,7 @@ class TestTimeWeights(BaseTest):
|
|
|
225
225
|
output = Path(BaseTest.TEST_DIR, "events").absolute()
|
|
226
226
|
runner.run(Path(BaseTest.TEST_DIR), output, files=["test.py"])
|
|
227
227
|
mapping = EventMapping.load(config)
|
|
228
|
-
analyzer =
|
|
228
|
+
analyzer = ProximityAnalyzer(
|
|
229
229
|
TestAssertDefUseModel,
|
|
230
230
|
[
|
|
231
231
|
EventFile(
|
|
@@ -272,7 +272,7 @@ class TestTimeWeights(BaseTest):
|
|
|
272
272
|
output = Path(BaseTest.TEST_DIR, "events").absolute()
|
|
273
273
|
runner.run(Path(BaseTest.TEST_DIR), output, files=["test.py"])
|
|
274
274
|
mapping = EventMapping.load(config)
|
|
275
|
-
analyzer =
|
|
275
|
+
analyzer = ProximityAnalyzer(
|
|
276
276
|
TestAssertDefUsesModel,
|
|
277
277
|
[
|
|
278
278
|
EventFile(
|
|
@@ -337,7 +337,7 @@ class TestTimeWeights(BaseTest):
|
|
|
337
337
|
],
|
|
338
338
|
expectations,
|
|
339
339
|
):
|
|
340
|
-
analyzer =
|
|
340
|
+
analyzer = ProximityAnalyzer(
|
|
341
341
|
model_class,
|
|
342
342
|
[
|
|
343
343
|
EventFile(
|
|
@@ -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)
|
|
@@ -80,13 +80,15 @@ class ParallelRunnerTests(BaseTest):
|
|
|
80
80
|
working=BaseTest.TEST_DIR,
|
|
81
81
|
exclude="tests",
|
|
82
82
|
mapping_path=BaseTest.TEST_MAPPING,
|
|
83
|
+
thread_support=True,
|
|
83
84
|
)
|
|
84
85
|
instrument_config(config)
|
|
85
86
|
runner = ParallelInputRunner(
|
|
86
|
-
"main.py",
|
|
87
|
+
Path("main.py"),
|
|
87
88
|
failing=[["2", "1", "3"]],
|
|
88
89
|
passing=[["3", "2", "1"], ["3", "1", "2"]],
|
|
89
90
|
workers=4,
|
|
91
|
+
thread_support=True,
|
|
90
92
|
)
|
|
91
93
|
output = Path(BaseTest.TEST_DIR, "events").absolute()
|
|
92
94
|
runner.run(Path(BaseTest.TEST_DIR), output)
|
|
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
|
|
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
|
|
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
|