Repository: secdev/scapy

Issue:
Execute each campaign in own environment
### Problem
The current test approach adds a dependency on the order of the test execution.
It might succeed in one test execution order but fail in another.
It might succeed locally but fail on the Travis server.
I think Unit Tests should be independent units which are reliable and not rely on side effects.
For clarification, I only talk about the order of campaigns/uts files, not about the containing test sets or tests.

### Example 1
Some automotive related tests import _ISOTPSocket_ what, depending on the execution environment, actually imports _ISOTPSoftSocket_ or _ISOTPNativeSocket_. Now if _ISOTPSoftSocket_ is imported in one test and _ISOTPNativeSocket_ should have been imported in a later one through configuration, _ISOTPSoftSocket_ is still used since it was already imported and python does not reimport.

### Example 2
Execution Order 1:
```C
myTests1.uts // succeeds
myTests2.uts // succeeds
```

Execution Order 2:
```C
myTests2.uts // succeeds
myTests1.uts // fails
```

### Idea
Execute each campaign in an own python process and get its output over _stdout_. I guess it shouldn't be very time costly and would add a lot of reliability to the unit tests.
This would also allow running tests in parallel.


Discussion:
This used to be the case, but loading scapy over and over doubles the load time... when we had fewer files, it already took for ever, so nowadays it would be even worse...
see https://github.com/secdev/scapy/pull/543
I wonder if moving from UTScapy to pytest will improve this situation. I have being thinking of porting the unit tests to pytest in order to benefit from tests parallelization.
I have a silly idea. Could we use the https://docs.python.org/3/library/functions.html?highlight=globals#globals builtin function to achieve a better reliability ?
For example, backuping and restoring at https://github.com/secdev/scapy/blob/master/scapy/tools/UTscapy.py#L1057 ?

Resolving patch:
diff --git a/scapy/tools/UTscapy.py b/scapy/tools/UTscapy.py
--- a/scapy/tools/UTscapy.py
+++ b/scapy/tools/UTscapy.py
@@ -30,8 +30,8 @@
 from scapy.config import conf
 from scapy.compat import base64_bytes, bytes_hex, plain_str
 
-#   Util class   #
 
+#   Util class   #
 
 class Bunch:
     __init__ = lambda self, **kw: setattr(self, '__dict__', kw)
@@ -522,14 +522,14 @@ def import_UTscapy_tools(ses):
         ses["conf"].route6.routes = conf.route6.routes
 
 
-def run_campaign(test_campaign, get_interactive_session, drop_to_interpreter=False, verb=3, ignore_globals=None):  # noqa: E501
+def run_campaign(test_campaign, get_interactive_session, drop_to_interpreter=False, verb=3, ignore_globals=None, scapy_ses=None):  # noqa: E501
     passed = failed = 0
-    scapy_ses = importlib.import_module(".all", "scapy").__dict__
-    import_UTscapy_tools(scapy_ses)
     if test_campaign.preexec:
-        test_campaign.preexec_output = get_interactive_session(test_campaign.preexec.strip(), ignore_globals=ignore_globals, my_globals=scapy_ses)[0]
-    # Drop
+        test_campaign.preexec_output = get_interactive_session(
+            test_campaign.preexec.strip(), ignore_globals=ignore_globals,
+            my_globals=scapy_ses)[0]
 
+    # Drop
     def drop(scapy_ses):
         code.interact(banner="Test '%s' failed. "
                              "exit() to stop, Ctrl-D to leave "
@@ -786,7 +786,7 @@ def usage():
 #    MAIN    #
 
 def execute_campaign(TESTFILE, OUTPUTFILE, PREEXEC, NUM, KW_OK, KW_KO, DUMP, DOCS,
-                     FORMAT, VERB, ONLYFAILED, CRC, INTERPRETER, autorun_func, pos_begin=0, ignore_globals=None):  # noqa: E501
+                     FORMAT, VERB, ONLYFAILED, CRC, INTERPRETER, autorun_func, pos_begin=0, ignore_globals=None, scapy_ses=None):  # noqa: E501
     # Parse test file
     test_campaign = parse_campaign_file(TESTFILE)
 
@@ -820,7 +820,7 @@ def execute_campaign(TESTFILE, OUTPUTFILE, PREEXEC, NUM, KW_OK, KW_KO, DUMP, DOC
 
     # Run tests
     test_campaign.output_file = OUTPUTFILE
-    result = run_campaign(test_campaign, autorun_func[FORMAT], drop_to_interpreter=INTERPRETER, verb=VERB, ignore_globals=None)  # noqa: E501
+    result = run_campaign(test_campaign, autorun_func[FORMAT], drop_to_interpreter=INTERPRETER, verb=VERB, ignore_globals=None, scapy_ses=scapy_ses)  # noqa: E501
 
     # Shrink passed
     if ONLYFAILED:
@@ -1055,17 +1055,20 @@ def main():
     pos_begin = 0
 
     runned_campaigns = []
+
+    scapy_ses = importlib.import_module(".all", "scapy").__dict__
+    import_UTscapy_tools(scapy_ses)
+
     # Execute all files
     for TESTFILE in TESTFILES:
         if VERB > 2:
             print("### Loading:", TESTFILE, file=sys.stderr)
         PREEXEC = PREEXEC_DICT[TESTFILE] if TESTFILE in PREEXEC_DICT else GLOB_PREEXEC
         with open(TESTFILE) as testfile:
-            output, result, campaign = execute_campaign(testfile, OUTPUTFILE,
-                                                        PREEXEC, NUM, KW_OK, KW_KO,
-                                                        DUMP, DOCS, FORMAT, VERB, ONLYFAILED,
-                                                        CRC, INTERPRETER, autorun_func, pos_begin,
-                                                        ignore_globals)
+            output, result, campaign = execute_campaign(
+                testfile, OUTPUTFILE, PREEXEC, NUM, KW_OK, KW_KO, DUMP, DOCS,
+                FORMAT, VERB, ONLYFAILED, CRC, INTERPRETER, autorun_func,
+                pos_begin, ignore_globals, copy.copy(scapy_ses))
         runned_campaigns.append(campaign)
         pos_begin = campaign.end_pos
         if UNIQUE:


Test patch:
diff --git a/test/can.uts b/test/can.uts
--- a/test/can.uts
+++ b/test/can.uts
@@ -15,7 +15,7 @@ import random
 
 random.seed()
 
-load_layer("can")
+load_layer("can", globals_dict=globals())
 
 = Build a packet
 
diff --git a/test/contrib/automotive/bmw/enet.uts b/test/contrib/automotive/bmw/enet.uts
--- a/test/contrib/automotive/bmw/enet.uts
+++ b/test/contrib/automotive/bmw/enet.uts
@@ -1,8 +1,7 @@
 + ENET Contrib tests
 
 = Load Contrib Layer
-
-load_contrib("automotive.bmw.enet")
+load_contrib("automotive.bmw.enet", globals_dict=globals())
 
 = Basic Test 1
 
diff --git a/test/contrib/automotive/ccp.uts b/test/contrib/automotive/ccp.uts
--- a/test/contrib/automotive/ccp.uts
+++ b/test/contrib/automotive/ccp.uts
@@ -4,9 +4,9 @@
 ~ conf
 
 = Imports
-load_layer("can")
+load_layer("can", globals_dict=globals())
 conf.contribs['CAN']['swap-bytes'] = False
-import threading, six
+import scapy.modules.six as six
 from subprocess import call
 from scapy.consts import LINUX
 
@@ -47,7 +47,6 @@ print("CAN should work now")
 
 from scapy.contrib.cansocket_python_can import *
 
-import can as python_can
 new_can_socket = lambda iface: CANSocket(bustype='virtual', channel=iface)
 new_can_socket0 = lambda: CANSocket(bustype='virtual', channel=iface0, timeout=0.01)
 new_can_socket1 = lambda: CANSocket(bustype='virtual', channel=iface1, timeout=0.01)
@@ -91,9 +90,7 @@ s.close()
 + Basic operations
 
 = Load module
-
-load_contrib("automotive.ccp")
-from scapy.contrib.automotive.ccp import CONNECT, DISCONNECT
+load_contrib("automotive.ccp", globals_dict=globals())
 
 = Build CRO CONNECT
 
diff --git a/test/contrib/automotive/ecu.uts b/test/contrib/automotive/ecu.uts
--- a/test/contrib/automotive/ecu.uts
+++ b/test/contrib/automotive/ecu.uts
@@ -9,16 +9,15 @@
 ~ conf command
 
 = Load modules
-
-load_contrib('isotp')
-load_contrib("automotive.uds")
-load_contrib("automotive.gm.gmlan")
-load_layer("can")
+load_contrib("isotp", globals_dict=globals())
+load_contrib("automotive.uds", globals_dict=globals())
+load_contrib("automotive.gm.gmlan", globals_dict=globals())
+load_layer("can", globals_dict=globals())
 conf.contribs["CAN"]["swap-bytes"] = True
 
 = Load ECU module
 
-load_contrib("automotive.ecu")
+load_contrib("automotive.ecu", globals_dict=globals())
 
 + Basic checks
 
@@ -230,4 +229,4 @@ assert len([m for m in gmlanmsgs if m.sprintf("%GMLAN.service%") == "ReadDataByI
 assert len(ecu.log["SecurityAccess"]) == 2
 assert len(ecu.log["SecurityAccessPositiveResponse"]) == 2
 
-assert ecu.log["TransferData"][-1][1][0] == "downloadAndExecuteOrExecute"
\ No newline at end of file
+assert ecu.log["TransferData"][-1][1][0] == "downloadAndExecuteOrExecute"
diff --git a/test/contrib/automotive/ecu_am.uts b/test/contrib/automotive/ecu_am.uts
--- a/test/contrib/automotive/ecu_am.uts
+++ b/test/contrib/automotive/ecu_am.uts
@@ -4,7 +4,7 @@
 ~ conf
 
 = Imports
-load_layer("can")
+load_layer("can", globals_dict=globals())
 conf.contribs['CAN']['swap-bytes'] = False
 import subprocess, sys
 import scapy.modules.six as six
@@ -109,15 +109,17 @@ if p1.wait() == 0 and p2.wait() == 0 and b"can_isotp" in p2.stdout.read():
 = Import isotp
 
 conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': ISOTP_KERNEL_MODULE_AVAILABLE}
-load_contrib("isotp")
+
+if six.PY3:
+    import importlib
+    if "scapy.contrib.isotp" in sys.modules:
+        importlib.reload(scapy.contrib.isotp)
+
+load_contrib("isotp", globals_dict=globals())
 
 if six.PY3 and ISOTP_KERNEL_MODULE_AVAILABLE:
-    from scapy.contrib.isotp import ISOTPNativeSocket
-    ISOTPSocket = ISOTPNativeSocket
     assert ISOTPSocket == ISOTPNativeSocket
 else:
-    from scapy.contrib.isotp import ISOTPSoftSocket
-    ISOTPSocket = ISOTPSoftSocket
     assert ISOTPSocket == ISOTPSoftSocket
 
 ############
@@ -126,8 +128,8 @@ else:
 
 = Load contribution layer
 
-load_contrib('automotive.uds')
-load_contrib('automotive.ecu')
+load_contrib("automotive.uds", globals_dict=globals())
+load_contrib("automotive.ecu", globals_dict=globals())
 
 
 + Simulator tests
diff --git a/test/contrib/automotive/gm/gmlan.uts b/test/contrib/automotive/gm/gmlan.uts
--- a/test/contrib/automotive/gm/gmlan.uts
+++ b/test/contrib/automotive/gm/gmlan.uts
@@ -7,17 +7,14 @@
 
 + Configuration of scapy
 = Load gmlan layer
-~ conf command
-
-from scapy.contrib.automotive.ecu import ECU
-
-load_contrib('automotive.gm.gmlan')
+~ conf
+load_contrib("automotive.ecu", globals_dict=globals())
+load_contrib("automotive.gm.gmlan", globals_dict=globals())
 
 + Basic Packet Tests()
 = Set GMLAN ECU AddressingScheme
 
 conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 2
-
 assert conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] == 2
 
 = Craft Packet
diff --git a/test/contrib/automotive/gm/gmlanutils.uts b/test/contrib/automotive/gm/gmlanutils.uts
--- a/test/contrib/automotive/gm/gmlanutils.uts
+++ b/test/contrib/automotive/gm/gmlanutils.uts
@@ -4,7 +4,7 @@
 ~ conf
 
 = Imports
-load_layer("can")
+load_layer("can", globals_dict=globals())
 conf.contribs['CAN']['swap-bytes'] = False
 import subprocess, sys
 import scapy.modules.six as six
@@ -57,7 +57,6 @@ print("CAN should work now")
 
 from scapy.contrib.cansocket_python_can import *
 
-import can as python_can
 new_can_socket = lambda iface: CANSocket(bustype='virtual', channel=iface, timeout=0.01)
 new_can_socket0 = lambda: CANSocket(bustype='virtual', channel=iface0, timeout=0.01)
 new_can_socket1 = lambda: CANSocket(bustype='virtual', channel=iface1, timeout=0.01)
@@ -92,7 +91,6 @@ if "python_can" in CANSocket.__module__:
 s = new_can_socket(iface0)
 s.close()
 
-
 = Check if can-isotp and can-utils are installed on this system
 ~ linux
 p1 = subprocess.Popen(['lsmod'], stdout = subprocess.PIPE)
@@ -109,15 +107,17 @@ if p1.wait() == 0 and p2.wait() == 0 and b"can_isotp" in p2.stdout.read():
 
 = Import isotp
 conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': ISOTP_KERNEL_MODULE_AVAILABLE}
-load_contrib("isotp")
+
+if six.PY3:
+    import importlib
+    if "scapy.contrib.isotp" in sys.modules:
+        importlib.reload(scapy.contrib.isotp)
+
+load_contrib("isotp", globals_dict=globals())
 
 if six.PY3 and ISOTP_KERNEL_MODULE_AVAILABLE:
-    from scapy.contrib.isotp import ISOTPNativeSocket
-    ISOTPSocket = ISOTPNativeSocket
     assert ISOTPSocket == ISOTPNativeSocket
 else:
-    from scapy.contrib.isotp import ISOTPSoftSocket
-    ISOTPSocket = ISOTPSoftSocket
     assert ISOTPSocket == ISOTPSoftSocket
 
 ############
@@ -126,8 +126,8 @@ else:
 
 = Load contribution layer
 
-load_contrib("automotive.gm.gmlan")
-load_contrib("automotive.gm.gmlanutils")
+load_contrib("automotive.gm.gmlan", globals_dict=globals())
+load_contrib("automotive.gm.gmlanutils", globals_dict=globals())
 
 ##############################################################################
 + GMLAN_RequestDownload Tests
diff --git a/test/contrib/automotive/obd/obd.uts b/test/contrib/automotive/obd/obd.uts
--- a/test/contrib/automotive/obd/obd.uts
+++ b/test/contrib/automotive/obd/obd.uts
@@ -9,9 +9,7 @@
 + Basic operations
 
 = Load module
-
-load_contrib("automotive.obd.obd")
-
+load_contrib("automotive.obd.obd", globals_dict=globals())
 
 = Check if positive response answers
 
diff --git a/test/contrib/automotive/obd/scanner.uts b/test/contrib/automotive/obd/scanner.uts
--- a/test/contrib/automotive/obd/scanner.uts
+++ b/test/contrib/automotive/obd/scanner.uts
@@ -4,7 +4,7 @@
 ~ conf
 
 = Imports
-load_layer("can")
+load_layer("can", globals_dict=globals())
 conf.contribs['CAN']['swap-bytes'] = False
 import subprocess, sys
 import scapy.modules.six as six
@@ -57,7 +57,6 @@ print("CAN should work now")
 
 from scapy.contrib.cansocket_python_can import *
 
-import can as python_can
 new_can_socket = lambda iface: CANSocket(bustype='virtual', channel=iface)
 new_can_socket0 = lambda: CANSocket(bustype='virtual', channel=iface0, timeout=0.01)
 new_can_socket1 = lambda: CANSocket(bustype='virtual', channel=iface1, timeout=0.01)
@@ -107,15 +106,17 @@ if p1.wait() == 0 and p2.wait() == 0 and b"can_isotp" in p2.stdout.read():
 
 = Import isotp
 conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': ISOTP_KERNEL_MODULE_AVAILABLE}
-load_contrib("isotp")
+
+if six.PY3:
+    import importlib
+    if "scapy.contrib.isotp" in sys.modules:
+        importlib.reload(scapy.contrib.isotp)
+
+load_contrib("isotp", globals_dict=globals())
 
 if six.PY3 and ISOTP_KERNEL_MODULE_AVAILABLE:
-    from scapy.contrib.isotp import ISOTPNativeSocket
-    ISOTPSocket = ISOTPNativeSocket
     assert ISOTPSocket == ISOTPNativeSocket
 else:
-    from scapy.contrib.isotp import ISOTPSoftSocket
-    ISOTPSocket = ISOTPSoftSocket
     assert ISOTPSocket == ISOTPSoftSocket
 
 ############
@@ -123,16 +124,15 @@ else:
 + Load general modules
 
 = Load contribution layer
-
-load_contrib('automotive.obd.obd')
+load_contrib("automotive.obd.obd", globals_dict=globals())
 
 + Load OBD_scan
 = imports
 
 from subprocess import call
 
-from scapy.contrib.automotive.obd.scanner import *
-from scapy.contrib.automotive.ecu import *
+load_contrib("automotive.obd.scanner", globals_dict=globals())
+load_contrib("automotive.ecu", globals_dict=globals())
 
 = Create answers
 
diff --git a/test/contrib/automotive/someip.uts b/test/contrib/automotive/someip.uts
--- a/test/contrib/automotive/someip.uts
+++ b/test/contrib/automotive/someip.uts
@@ -32,7 +32,7 @@
 + Basic operations
 
 = Load module
-load_contrib("automotive.someip")
+load_contrib("automotive.someip", globals_dict=globals())
 
 + SOME/IP operation
 
diff --git a/test/contrib/automotive/uds.uts b/test/contrib/automotive/uds.uts
--- a/test/contrib/automotive/uds.uts
+++ b/test/contrib/automotive/uds.uts
@@ -9,10 +9,8 @@
 + Basic operations
 
 = Load module
-
-load_contrib("automotive.uds")
-
-from scapy.contrib.automotive.ecu import ECU
+load_contrib("automotive.uds", globals_dict=globals())
+load_contrib("automotive.ecu", globals_dict=globals())
 
 = Check if positive response answers
 
diff --git a/test/contrib/automotive/uds_utils.uts b/test/contrib/automotive/uds_utils.uts
--- a/test/contrib/automotive/uds_utils.uts
+++ b/test/contrib/automotive/uds_utils.uts
@@ -4,7 +4,7 @@
 ~ conf
 
 = Imports
-load_layer("can")
+load_layer("can", globals_dict=globals())
 conf.contribs['CAN']['swap-bytes'] = False
 import subprocess, sys
 import scapy.modules.six as six
@@ -108,15 +108,17 @@ if p1.wait() == 0 and p2.wait() == 0 and b"can_isotp" in p2.stdout.read():
 
 = Import isotp
 conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': ISOTP_KERNEL_MODULE_AVAILABLE}
-load_contrib("isotp")
+
+if six.PY3:
+    import importlib
+    if "scapy.contrib.isotp" in sys.modules:
+        importlib.reload(scapy.contrib.isotp)
+
+load_contrib("isotp", globals_dict=globals())
 
 if six.PY3 and ISOTP_KERNEL_MODULE_AVAILABLE:
-    from scapy.contrib.isotp import ISOTPNativeSocket
-    ISOTPSocket = ISOTPNativeSocket
     assert ISOTPSocket == ISOTPNativeSocket
 else:
-    from scapy.contrib.isotp import ISOTPSoftSocket
-    ISOTPSocket = ISOTPSoftSocket
     assert ISOTPSocket == ISOTPSoftSocket
 
 ############
@@ -124,8 +126,7 @@ else:
 + Load general modules
 
 = Load contribution layer
-load_contrib('automotive.uds')
-
+load_contrib("automotive.uds", globals_dict=globals())
 
 = Test Session Enumerator
 drain_bus(iface0)
diff --git a/test/contrib/cansocket.uts b/test/contrib/cansocket.uts
--- a/test/contrib/cansocket.uts
+++ b/test/contrib/cansocket.uts
@@ -10,20 +10,16 @@
 ~ conf
 
 = Load module
-
-load_layer("can")
+load_layer("can", globals_dict=globals())
 from scapy.contrib.cansocket_python_can import PythonCANSocket
 from scapy.contrib.cansocket_native import NativeCANSocket
 
 conf.contribs['CAN'] = {'swap-bytes': False}
 
 = Setup string for vcan
-~ conf command
-
 bashCommand = "/bin/bash -c 'sudo modprobe vcan; sudo ip link add name vcan0 type vcan; sudo ip link set dev vcan0 up'"
 
 = Load os
-
 import os
 import threading
 from subprocess import call
diff --git a/test/contrib/cansocket_native.uts b/test/contrib/cansocket_native.uts
--- a/test/contrib/cansocket_native.uts
+++ b/test/contrib/cansocket_native.uts
@@ -7,48 +7,37 @@
 ############
 ############
 + Configuration of CAN virtual sockets
+~ conf
 
 = Load module
-~ conf command needs_root linux
-
-load_layer("can")
+load_layer("can", globals_dict=globals())
 conf.contribs['CANSocket'] = {'use-python-can': False}
 from scapy.contrib.cansocket_native import *
 conf.contribs['CAN'] = {'swap-bytes': False}
 
 
 = Setup string for vcan
-~ conf command
-    bashCommand = "/bin/bash -c 'sudo modprobe vcan; sudo ip link add name vcan0 type vcan; sudo ip link set dev vcan0 up'"
+bashCommand = "/bin/bash -c 'sudo modprobe vcan; sudo ip link add name vcan0 type vcan; sudo ip link set dev vcan0 up'"
 
 = Load os
-~ conf command needs_root linux
-
 import os
 import threading
 from time import sleep
 from subprocess import call
 
 = Setup vcan0
-~ conf command needs_root linux
-
 0 == os.system(bashCommand)
 
 + Basic Packet Tests()
 = CAN Packet init
-
-
 canframe = CAN(identifier=0x7ff,length=8,data=b'\x01\x02\x03\x04\x05\x06\x07\x08')
 bytes(canframe) == b'\x00\x00\x07\xff\x08\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08'
 
 + Basic Socket Tests()
 = CAN Socket Init
-
-
 sock1 = CANSocket(channel="vcan0")
 
 = CAN Socket send recv small packet
-
 def sender():
     sleep(0.1)
     sock2 = CANSocket(channel="vcan0")
@@ -62,8 +51,6 @@ rx == CAN(identifier=0x7ff,length=1,data=b'\x01')
 thread.join(timeout=5)
 
 = CAN Socket send recv
-
-
 def sender():
     sleep(0.1)
     sock2 = CANSocket(channel="vcan0")
@@ -77,8 +64,6 @@ rx == CAN(identifier=0x7ff,length=8,data=b'\x01\x02\x03\x04\x05\x06\x07\x08')
 thread.join(timeout=5)
 
 = CAN Socket basecls test
-
-
 def sender():
     sleep(0.1)
     sock2 = CANSocket(channel="vcan0")
@@ -95,13 +80,9 @@ thread.join(timeout=5)
 
 + Advanced Socket Tests()
 = CAN Socket sr1
-
-
 tx = CAN(identifier=0x7ff,length=8,data=b'\x01\x02\x03\x04\x05\x06\x07\x08')
 
 = CAN Socket sr1 init time
-
-
 tx.sent_time == None
 
 def sender():
@@ -120,18 +101,12 @@ sock1.close()
 thread.join(timeout=5)
 
 = CAN Socket sr1 time check
-
-
 assert tx.sent_time < rx.time and rx.time > 0
 
 = sr can
-
-
 tx = CAN(identifier=0x7ff,length=8,data=b'\x01\x02\x03\x04\x05\x06\x07\x08')
 
 = sr can check init time
-
-
 assert tx.sent_time == None
 
 def sender():
diff --git a/test/contrib/cansocket_python_can.uts b/test/contrib/cansocket_python_can.uts
--- a/test/contrib/cansocket_python_can.uts
+++ b/test/contrib/cansocket_python_can.uts
@@ -9,13 +9,12 @@
 + Configuration of CAN virtual sockets
 
 = Load module
-~ conf command
-
+~ conf
+ 
 conf.contribs['CAN'] = {'swap-bytes': False}
-load_layer("can")
+load_layer("can", globals_dict=globals())
 conf.contribs['CANSocket'] = {'use-python-can': True}
 from scapy.contrib.cansocket_python_can import *
-import can
 
 = Setup string for vcan
 ~ conf command
diff --git a/test/contrib/isotp.uts b/test/contrib/isotp.uts
--- a/test/contrib/isotp.uts
+++ b/test/contrib/isotp.uts
@@ -4,7 +4,7 @@
 ~ conf
 
 = Imports
-load_layer("can")
+load_layer("can", globals_dict=globals())
 conf.contribs['CAN']['swap-bytes'] = False
 import scapy.modules.six as six
 import subprocess, sys
@@ -140,7 +140,7 @@ if p1.wait() == 0 and p2.wait() == 0 and b"can_isotp" in p2.stdout.read():
 
 = Import isotp
 conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': False}
-load_contrib("isotp")
+load_contrib("isotp", globals_dict=globals())
 
 ISOTPSocket = ISOTPSoftSocket
 
diff --git a/test/contrib/isotpscan.uts b/test/contrib/isotpscan.uts
--- a/test/contrib/isotpscan.uts
+++ b/test/contrib/isotpscan.uts
@@ -4,7 +4,7 @@
 ~ conf
 
 = Imports
-load_layer("can")
+load_layer("can", globals_dict=globals())
 conf.contribs['CAN']['swap-bytes'] = False
 import os, subprocess, sys
 from subprocess import call
@@ -110,15 +110,17 @@ if p1.wait() == 0 and p2.wait() == 0 and b"can_isotp" in p2.stdout.read():
 
 = Import isotp
 conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': ISOTP_KERNEL_MODULE_AVAILABLE}
-load_contrib("isotp")
+
+if six.PY3:
+    import importlib
+    if "scapy.contrib.isotp" in sys.modules:
+        importlib.reload(scapy.contrib.isotp)
+
+load_contrib("isotp", globals_dict=globals())
 
 if six.PY3 and ISOTP_KERNEL_MODULE_AVAILABLE:
-    from scapy.contrib.isotp import ISOTPNativeSocket
-    ISOTPSocket = ISOTPNativeSocket
     assert ISOTPSocket == ISOTPNativeSocket
 else:
-    from scapy.contrib.isotp import ISOTPSoftSocket
-    ISOTPSocket = ISOTPSoftSocket
     assert ISOTPSocket == ISOTPSoftSocket
 
 
diff --git a/test/tools/isotpscanner.uts b/test/tools/isotpscanner.uts
--- a/test/tools/isotpscanner.uts
+++ b/test/tools/isotpscanner.uts
@@ -6,7 +6,8 @@
 ~ conf
 
 = Imports
-load_layer("can")
+load_layer("can", globals_dict=globals())
+
 import threading, subprocess, sys
 import scapy.modules.six as six
 from subprocess import call
@@ -100,7 +101,7 @@ if p1.wait() == 0 and p2.wait() == 0 and b"can_isotp" in p2.stdout.read():
 
 = Import isotp
 conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': False}
-load_contrib("isotp")
+load_contrib("isotp", globals_dict=globals())
 
 ISOTPSocket = ISOTPSoftSocket
 
diff --git a/test/tools/obdscanner.uts b/test/tools/obdscanner.uts
--- a/test/tools/obdscanner.uts
+++ b/test/tools/obdscanner.uts
@@ -5,10 +5,10 @@
 ~ conf
 
 = Imports
-load_layer("can")
+load_layer("can", globals_dict=globals())
+import scapy.modules.six as six
 import subprocess, sys
 from subprocess import call
-import scapy.modules.six as six
 from scapy.contrib.automotive.ecu import *
 
 = Definition of constants, utility functions and mock classes
@@ -104,18 +104,19 @@ if p1.wait() == 0 and p2.wait() == 0 and b"can_isotp" in p2.stdout.read():
 
 = Import isotp
 conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': ISOTP_KERNEL_MODULE_AVAILABLE}
-load_contrib("isotp")
+
+if six.PY3:
+    import importlib
+    if "scapy.contrib.isotp" in sys.modules:
+        importlib.reload(scapy.contrib.isotp)
+
+load_contrib("isotp", globals_dict=globals())
 
 if six.PY3 and ISOTP_KERNEL_MODULE_AVAILABLE:
-    from scapy.contrib.isotp import ISOTPNativeSocket
-    ISOTPSocket = ISOTPNativeSocket
     assert ISOTPSocket == ISOTPNativeSocket
 else:
-    from scapy.contrib.isotp import ISOTPSoftSocket
-    ISOTPSocket = ISOTPSoftSocket
     assert ISOTPSocket == ISOTPSoftSocket
 
-
 + Usage tests
 
 = Test wrong usage
diff --git a/test/windows.uts b/test/windows.uts
--- a/test/windows.uts
+++ b/test/windows.uts
@@ -2,6 +2,12 @@
 
 # More information at http://www.secdev.org/projects/UTscapy/
 
++ Configuration
+
+= Imports
+
+import mock
+
 ############
 ############
 + Mechanics tests