File: test_convert_utilities.py

package info (click to toggle)
pydevd 3.3.0%2Bds-4
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 13,892 kB
  • sloc: python: 77,508; cpp: 1,869; sh: 368; makefile: 50; ansic: 4
file content (553 lines) | stat: -rw-r--r-- 25,629 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
# coding: utf-8
import os.path
from _pydevd_bundle.pydevd_constants import IS_WINDOWS, IS_MAC
import io
from _pydev_bundle.pydev_log import log_context
import pytest
import sys


@pytest.fixture(autouse=True)
def _reset_ide_os():
    yield
    from pydevd_file_utils import set_ide_os

    set_ide_os("WINDOWS" if sys.platform == "win32" else "UNIX")


@pytest.mark.skipif(sys.platform != "win32", reason="Windows-only test.")
def test_get_path_with_real_case_windows_unc_path(monkeypatch):
    import pydevd_file_utils
    from pydevd_file_utils import get_path_with_real_case

    def temp_listdir(d):
        # When we have a UNC drive in windows the "drive" is something as:
        # \\MACHINE_NAME\MOUNT_POINT\
        if d == "\\\\A\\B\\":
            return ["Cc"]
        raise AssertionError("Unexpected: %s" % (d,))

    monkeypatch.setattr(pydevd_file_utils, "os_path_exists", lambda *args: True)
    monkeypatch.setattr(pydevd_file_utils, "os_listdir", temp_listdir)
    assert get_path_with_real_case(r"\\a\b\cc") == r"\\A\B\Cc"


@pytest.mark.skipif(sys.platform != "win32", reason="Windows-only test.")
def test_get_path_with_real_case_windows_slashes_drive(tmpdir):
    from pydevd_file_utils import get_path_with_real_case

    test_dir = str(tmpdir.mkdir("Test_Convert_Utilities")).lower()
    real_case = get_path_with_real_case(test_dir)
    assert real_case.endswith("Test_Convert_Utilities")

    prefix = "\\\\?\\"
    path = prefix + test_dir
    real_case = get_path_with_real_case(path)
    assert real_case.endswith("Test_Convert_Utilities")
    assert path.startswith(prefix)


@pytest.mark.skipif(not IS_MAC, reason="Mac-only test.")
def test_get_path_with_real_case_mac_os(tmpdir):
    from pydevd_file_utils import get_path_with_real_case

    test_dir = str(tmpdir.mkdir("Test_Convert_Utilities")).lower()
    real_case = get_path_with_real_case(test_dir)
    assert real_case.endswith("Test_Convert_Utilities")


@pytest.mark.skipif(not IS_MAC, reason="Mac-only test.")
def test_double_slash_mac(monkeypatch):
    import pydevd_file_utils
    from pydevd_file_utils import get_path_with_real_case

    def temp_listdir(d):
        if d == "//":
            return ["A"]
        if d == "//A":
            return ["Bb"]
        raise AssertionError("Unexpected: %s" % (d,))

    monkeypatch.setattr(pydevd_file_utils, "os_path_exists", lambda *args: True)
    monkeypatch.setattr(pydevd_file_utils, "os_listdir", temp_listdir)
    assert get_path_with_real_case(r"//a/bb") == r"//A/Bb"


def test_convert_utilities(tmpdir):
    import pydevd_file_utils

    test_dir = str(tmpdir.mkdir("Test_Convert_Utilities"))

    if IS_WINDOWS:
        normalized = pydevd_file_utils.normcase(test_dir)
        assert isinstance(normalized, str)
        assert normalized.lower() == normalized

        upper_version = os.path.join(test_dir, "ÁÉÍÓÚ")
        with open(upper_version, "w") as stream:
            stream.write("test")

        with open(upper_version, "r") as stream:
            assert stream.read() == "test"

        with open(pydevd_file_utils.normcase(upper_version), "r") as stream:
            assert stream.read() == "test"

        assert "~" not in normalized

        for i in range(3):  # Check if cache is ok.
            if i == 2:
                pydevd_file_utils._listdir_cache.clear()

            assert pydevd_file_utils.get_path_with_real_case("<does not EXIST>") == "<does not EXIST>"
            real_case = pydevd_file_utils.get_path_with_real_case(normalized)
            assert isinstance(real_case, str)
            # Note test_dir itself cannot be compared with because pytest may
            # have passed the case normalized.
            assert real_case.endswith("Test_Convert_Utilities")

            if i == 2:
                # Check that we have the expected paths in the cache.
                assert pydevd_file_utils._listdir_cache[os.path.dirname(normalized).lower()] == ["Test_Convert_Utilities"]
                assert (
                    pydevd_file_utils._listdir_cache[(os.path.dirname(normalized).lower(), "Test_Convert_Utilities".lower())] == real_case
                )

        # Check that it works with a shortened path.
        shortened = pydevd_file_utils.convert_to_short_pathname(normalized)
        assert "~" in shortened
        with_real_case = pydevd_file_utils.get_path_with_real_case(shortened)
        assert with_real_case.endswith("Test_Convert_Utilities")
        assert "~" not in with_real_case

    elif IS_MAC:
        assert pydevd_file_utils.normcase(test_dir) == test_dir.lower()
        assert pydevd_file_utils.get_path_with_real_case(test_dir) == test_dir

    else:
        # On Linux, nothing should change
        assert pydevd_file_utils.normcase(test_dir) == test_dir
        assert pydevd_file_utils.get_path_with_real_case(test_dir) == test_dir


def test_source_reference(tmpdir):
    import pydevd_file_utils

    pydevd_file_utils.set_ide_os("WINDOWS")
    if IS_WINDOWS:
        # Client and server are on windows.
        pydevd_file_utils.setup_client_server_paths([("c:\\foo", "c:\\bar")])

        assert pydevd_file_utils.map_file_to_client("c:\\bar\\my") == ("c:\\foo\\my", True)
        assert pydevd_file_utils.get_client_filename_source_reference("c:\\foo\\my") == 0

        assert pydevd_file_utils.map_file_to_client("c:\\another\\my") == ("c:\\another\\my", False)
        source_reference = pydevd_file_utils.get_client_filename_source_reference("c:\\another\\my")
        assert source_reference != 0
        assert pydevd_file_utils.get_server_filename_from_source_reference(source_reference) == "c:\\another\\my"

    else:
        # Client on windows and server on unix
        pydevd_file_utils.set_ide_os("WINDOWS")

        pydevd_file_utils.setup_client_server_paths([("c:\\foo", "/bar")])

        assert pydevd_file_utils.map_file_to_client("/bar/my") == ("c:\\foo\\my", True)
        assert pydevd_file_utils.get_client_filename_source_reference("c:\\foo\\my") == 0

        assert pydevd_file_utils.map_file_to_client("/another/my") == ("\\another\\my", False)
        source_reference = pydevd_file_utils.get_client_filename_source_reference("\\another\\my")
        assert source_reference != 0
        assert pydevd_file_utils.get_server_filename_from_source_reference(source_reference) == "/another/my"


@pytest.mark.skipif(sys.platform != "win32", reason="Windows-only test.")
def test_translate_only_drive():
    import pydevd_file_utils

    assert pydevd_file_utils.get_path_with_real_case("c:\\") == "C:\\"


def test_to_server_and_to_client(tmpdir):
    try:

        def check(obtained, expected):
            assert obtained == expected, "%s (%s) != %s (%s)" % (obtained, type(obtained), expected, type(expected))
            if isinstance(obtained, tuple):
                assert isinstance(obtained[0], str)
            else:
                assert isinstance(obtained, str)

            if isinstance(expected, tuple):
                assert isinstance(expected[0], str)
            else:
                assert isinstance(expected, str)

        import pydevd_file_utils

        if IS_WINDOWS:
            # Check with made-up files

            pydevd_file_utils.setup_client_server_paths([("c:\\foo", "c:\\bar"), ("c:\\foo2", "c:\\bar2")])

            stream = io.StringIO()
            with log_context(0, stream=stream):
                pydevd_file_utils.map_file_to_server("y:\\only_exists_in_client_not_in_server")
            assert (
                r'pydev debugger: unable to find translation for: "y:\only_exists_in_client_not_in_server" in ["c:\foo\", "c:\foo2\", "c:\foo", "c:\foo2"] (please revise your path mappings).'
                in stream.getvalue()
            )

            # Client and server are on windows.
            pydevd_file_utils.set_ide_os("WINDOWS")
            for in_eclipse, in_python in [
                ("c:\\foo", "c:\\bar"),
                ("c:/foo", "c:\\bar"),
                ("c:\\foo", "c:/bar"),
                ("c:\\foo", "c:\\bar\\"),
                ("c:/foo", "c:\\bar\\"),
                ("c:\\foo", "c:/bar/"),
                ("c:\\foo\\", "c:\\bar"),
                ("c:/foo/", "c:\\bar"),
                ("c:\\foo\\", "c:/bar"),
            ]:
                PATHS_FROM_ECLIPSE_TO_PYTHON = [(in_eclipse, in_python)]
                pydevd_file_utils.setup_client_server_paths(PATHS_FROM_ECLIPSE_TO_PYTHON)
                check(pydevd_file_utils.map_file_to_server("c:\\foo\\my"), "c:\\bar\\my")
                check(pydevd_file_utils.map_file_to_server("c:/foo/my"), "c:\\bar\\my")
                check(pydevd_file_utils.map_file_to_server("c:/foo/my/"), "c:\\bar\\my")
                check(pydevd_file_utils.map_file_to_server("c:\\foo\\áéíóú".upper()), "c:\\bar" + "\\áéíóú".upper())
                check(pydevd_file_utils.map_file_to_client("c:\\bar\\my"), ("c:\\foo\\my", True))

            # Client on unix and server on windows
            pydevd_file_utils.set_ide_os("UNIX")
            for in_eclipse, in_python in [
                ("/foo", "c:\\bar"),
                ("/foo", "c:/bar"),
                ("/foo", "c:\\bar\\"),
                ("/foo", "c:/bar/"),
                ("/foo/", "c:\\bar"),
                ("/foo/", "c:\\bar\\"),
            ]:
                PATHS_FROM_ECLIPSE_TO_PYTHON = [(in_eclipse, in_python)]
                pydevd_file_utils.setup_client_server_paths(PATHS_FROM_ECLIPSE_TO_PYTHON)
                check(pydevd_file_utils.map_file_to_server("/foo/my"), "c:\\bar\\my")
                check(pydevd_file_utils.map_file_to_client("c:\\bar\\my"), ("/foo/my", True))
                check(pydevd_file_utils.map_file_to_client("c:\\bar\\my\\"), ("/foo/my", True))
                check(pydevd_file_utils.map_file_to_client("c:/bar/my"), ("/foo/my", True))
                check(pydevd_file_utils.map_file_to_client("c:/bar/my/"), ("/foo/my", True))

            # Test with 'real' files
            # Client and server are on windows.
            pydevd_file_utils.set_ide_os("WINDOWS")

            test_dir = pydevd_file_utils.get_path_with_real_case(str(tmpdir.mkdir("Foo")))
            os.makedirs(os.path.join(test_dir, "Another"))

            in_eclipse = os.path.join(os.path.dirname(test_dir), "Bar")
            in_python = test_dir
            PATHS_FROM_ECLIPSE_TO_PYTHON = [(in_eclipse, in_python)]
            pydevd_file_utils.setup_client_server_paths(PATHS_FROM_ECLIPSE_TO_PYTHON)

            if pydevd_file_utils.map_file_to_server(in_eclipse) != in_python.lower():
                raise AssertionError(
                    "%s != %s\ntmpdir:%s\nin_eclipse: %s\nin_python: %s\ntest_dir: %s"
                    % (pydevd_file_utils.map_file_to_server(in_eclipse), in_python.lower(), tmpdir, in_eclipse, in_python, test_dir)
                )

            found_in_eclipse = pydevd_file_utils.map_file_to_client(in_python)[0]
            assert found_in_eclipse.endswith("Bar")

            assert pydevd_file_utils.map_file_to_server(os.path.join(in_eclipse, "another")) == os.path.join(in_python, "another").lower()
            found_in_eclipse = pydevd_file_utils.map_file_to_client(os.path.join(in_python, "another"))[0]
            assert found_in_eclipse.endswith("Bar\\Another")

            # Client on unix and server on windows
            pydevd_file_utils.set_ide_os("UNIX")
            in_eclipse = "/foo"
            in_python = test_dir
            PATHS_FROM_ECLIPSE_TO_PYTHON = [(in_eclipse, in_python)]
            pydevd_file_utils.setup_client_server_paths(PATHS_FROM_ECLIPSE_TO_PYTHON)
            assert pydevd_file_utils.map_file_to_server("/foo").lower() == in_python.lower()
            assert pydevd_file_utils.map_file_to_client(in_python) == (in_eclipse, True)

            # Test without translation in place (still needs to fix case and separators)
            pydevd_file_utils.set_ide_os("WINDOWS")
            PATHS_FROM_ECLIPSE_TO_PYTHON = []
            pydevd_file_utils.setup_client_server_paths(PATHS_FROM_ECLIPSE_TO_PYTHON)
            assert pydevd_file_utils.map_file_to_server(test_dir) == test_dir
            assert pydevd_file_utils.map_file_to_client(test_dir.lower())[0].endswith("\\Foo")
        else:
            # Client on windows and server on unix
            pydevd_file_utils.set_ide_os("WINDOWS")

            PATHS_FROM_ECLIPSE_TO_PYTHON = [("c:\\BAR", "/bar")]

            pydevd_file_utils.setup_client_server_paths(PATHS_FROM_ECLIPSE_TO_PYTHON)
            assert pydevd_file_utils.map_file_to_server("c:\\bar\\my") == "/bar/my"
            assert pydevd_file_utils.map_file_to_client("/bar/my") == ("c:\\BAR\\my", True)

            for in_eclipse, in_python in [
                ("c:\\foo", "/báéíóúr"),
                ("c:/foo", "/báéíóúr"),
                ("c:/foo/", "/báéíóúr"),
                ("c:/foo/", "/báéíóúr/"),
                ("c:\\foo\\", "/báéíóúr/"),
            ]:
                PATHS_FROM_ECLIPSE_TO_PYTHON = [(in_eclipse, in_python)]

                pydevd_file_utils.setup_client_server_paths(PATHS_FROM_ECLIPSE_TO_PYTHON)
                assert pydevd_file_utils.map_file_to_server("c:\\foo\\my") == "/báéíóúr/my"
                assert pydevd_file_utils.map_file_to_server("C:\\foo\\my") == "/báéíóúr/my"
                assert pydevd_file_utils.map_file_to_server("C:\\foo\\MY") == "/báéíóúr/MY"
                assert pydevd_file_utils.map_file_to_server("C:\\foo\\MY\\") == "/báéíóúr/MY"
                assert pydevd_file_utils.map_file_to_server("c:\\foo\\my\\file.py") == "/báéíóúr/my/file.py"
                assert pydevd_file_utils.map_file_to_server("c:\\foo\\my\\other\\file.py") == "/báéíóúr/my/other/file.py"
                assert pydevd_file_utils.map_file_to_server("c:/foo/my") == "/báéíóúr/my"
                assert pydevd_file_utils.map_file_to_server("c:\\foo\\my\\") == "/báéíóúr/my"
                assert pydevd_file_utils.map_file_to_server("c:/foo/my/") == "/báéíóúr/my"

                assert pydevd_file_utils.map_file_to_client("/báéíóúr/my") == ("c:\\foo\\my", True)
                assert pydevd_file_utils.map_file_to_client("/báéíóúr/my/") == ("c:\\foo\\my", True)

                # Files for which there's no translation have only their separators updated.
                assert pydevd_file_utils.map_file_to_client("/usr/bin/x.py") == ("\\usr\\bin\\x.py", False)
                assert pydevd_file_utils.map_file_to_client("/usr/bin") == ("\\usr\\bin", False)
                assert pydevd_file_utils.map_file_to_client("/usr/bin/") == ("\\usr\\bin", False)
                assert pydevd_file_utils.map_file_to_server("\\usr\\bin") == "/usr/bin"
                assert pydevd_file_utils.map_file_to_server("\\usr\\bin\\") == "/usr/bin"

                # When we have a client file and there'd be no translation, and making it absolute would
                # do something as '$cwd/$file_received' (i.e.: $cwd/c:/another in the case below),
                # warn the user that it's not correct and the path that should be translated instead
                # and don't make it absolute.
                assert pydevd_file_utils.map_file_to_server("c:\\Another") == "c:/Another"

                assert pydevd_file_utils.map_file_to_server("c:/FoO/my/BAR") == "/báéíóúr/my/BAR"
                assert pydevd_file_utils.map_file_to_client("/báéíóúr/my/BAR") == ("c:\\foo\\my\\BAR", True)

            # Client and server on unix
            pydevd_file_utils.set_ide_os("UNIX")
            in_eclipse = "/foo"
            in_python = "/báéíóúr"
            PATHS_FROM_ECLIPSE_TO_PYTHON = [(in_eclipse, in_python)]
            pydevd_file_utils.setup_client_server_paths(PATHS_FROM_ECLIPSE_TO_PYTHON)
            assert pydevd_file_utils.map_file_to_server("/foo/my") == "/báéíóúr/my"
            assert pydevd_file_utils.map_file_to_client("/báéíóúr/my") == ("/foo/my", True)
    finally:
        pydevd_file_utils.setup_client_server_paths([])


def test_relative_paths(tmpdir):
    """
    We need to check that we can deal with relative paths.

    Use cases:
        - Relative path of file that does not exist:
            Use case is a cython-generated module which is generated from a .pyx which
            is not distributed. In this case we need to resolve the file to a library path file.

        - Relative path of a file that exists but not when resolved from the working directory:
            Use case is a cython-generated module which is generated from a .pyx which is
            distributed. In this case we need to resolve to the real file based on the sys.path
            entries.
    """
    import pydevd_file_utils
    import sys

    sys.path.append(str(tmpdir))
    try:
        pydevd_file_utils.NORM_PATHS_AND_BASE_CONTAINER.clear()
        pydevd_file_utils.NORM_PATHS_CONTAINER.clear()
        abs_path = pydevd_file_utils.get_abs_path_real_path_and_base_from_file("my_dir/my_file.pyx")[0]
        assert "site-packages" in abs_path or "dist-packages" in abs_path
        assert os.path.normcase(str(tmpdir)) not in abs_path
        assert not pydevd_file_utils.exists("my_dir/my_file.pyx")

        # If the relative file exists when joined with some entry in the PYTHONPATH we'll consider
        # that the relative path points to that absolute path.
        target_dir = os.path.join(str(tmpdir), "my_dir")
        os.makedirs(target_dir)
        with open(os.path.join(target_dir, "my_file.pyx"), "w") as stream:
            stream.write("empty")

        pydevd_file_utils.NORM_PATHS_AND_BASE_CONTAINER.clear()
        pydevd_file_utils.NORM_PATHS_CONTAINER.clear()
        abs_path = pydevd_file_utils.get_abs_path_real_path_and_base_from_file("my_dir/my_file.pyx")[0]
        assert "site-packages" not in abs_path
        assert str(tmpdir) in abs_path
        assert pydevd_file_utils.exists("my_dir/my_file.pyx")
    finally:
        sys.path.remove(str(tmpdir))


def test_zip_paths(tmpdir):
    import pydevd_file_utils
    import sys
    import zipfile

    for i, zip_basename in enumerate(("MY1.zip", "my2.egg!")):
        zipfile_path = str(tmpdir.join(zip_basename))
        zip_file = zipfile.ZipFile(zipfile_path, "w")
        zip_file.writestr("zipped%s/__init__.py" % (i,), "")
        zip_file.writestr("zipped%s/zipped_contents.py" % (i,), "def call_in_zip():\n    return 1")
        zip_file.close()

        sys.path.append(zipfile_path)
        try:
            import importlib
        except ImportError:
            __import__("zipped%s" % (i,))  # Py2.6 does not have importlib
        else:
            importlib.import_module("zipped%s" % (i,))  # Check that it's importable.

        # Check that we can deal with the zip path.
        assert pydevd_file_utils.exists(zipfile_path)
        abspath, realpath, basename = pydevd_file_utils.get_abs_path_real_path_and_base_from_file(zipfile_path)
        if IS_WINDOWS or IS_MAC:
            assert abspath == zipfile_path
            assert basename == zip_basename.lower()
        else:
            assert abspath == zipfile_path
            assert basename == zip_basename

        # Check that we can deal with zip contents.
        for path in [
            zipfile_path + "/zipped%s/__init__.py" % (i,),
            zipfile_path + "/zipped%s/zipped_contents.py" % (i,),
            zipfile_path + "\\zipped%s\\__init__.py" % (i,),
            zipfile_path + "\\zipped%s\\zipped_contents.py" % (i,),
        ]:
            assert pydevd_file_utils.exists(path), "Expected exists to return True for path:\n%s" % (path,)
            abspath, realpath, basename = pydevd_file_utils.get_abs_path_real_path_and_base_from_file(path)
            assert pydevd_file_utils.exists(abspath), "Expected exists to return True for path:\n%s" % (abspath,)
            assert pydevd_file_utils.exists(realpath), "Expected exists to return True for path:\n%s" % (realpath,)

        assert zipfile_path in pydevd_file_utils._ZIP_SEARCH_CACHE, "%s not in %s" % (
            zipfile_path,
            "\n".join(sorted(pydevd_file_utils._ZIP_SEARCH_CACHE.keys())),
        )


def test_source_mapping():
    from _pydevd_bundle.pydevd_source_mapping import SourceMapping, SourceMappingEntry
    from _pydevd_bundle import pydevd_api

    class _DummyPyDB(object):
        source_mapping = SourceMapping()
        api_received_breakpoints = {}
        file_to_id_to_line_breakpoint = {}
        file_to_id_to_plugin_breakpoint = {}
        breakpoints = {}

    source_mapping = _DummyPyDB.source_mapping

    mapping = [
        SourceMappingEntry(line=3, end_line=6, runtime_line=5, runtime_source="<cell1>"),
        SourceMappingEntry(line=10, end_line=11, runtime_line=1, runtime_source="<cell2>"),
    ]

    api = pydevd_api.PyDevdAPI()
    py_db = _DummyPyDB()
    filename = "c:\\temp\\bar.py" if IS_WINDOWS else "/temp/bar.py"
    api.set_source_mapping(py_db, filename, mapping)

    # Map to server
    assert source_mapping.map_to_server(filename, 1) == (filename, 1, False)
    assert source_mapping.map_to_server(filename, 2) == (filename, 2, False)

    assert source_mapping.map_to_server(filename, 3) == ("<cell1>", 5, True)
    assert source_mapping.map_to_server(filename, 4) == ("<cell1>", 6, True)
    assert source_mapping.map_to_server(filename, 5) == ("<cell1>", 7, True)
    assert source_mapping.map_to_server(filename, 6) == ("<cell1>", 8, True)

    assert source_mapping.map_to_server(filename, 7) == (filename, 7, False)

    assert source_mapping.map_to_server(filename, 10) == ("<cell2>", 1, True)
    assert source_mapping.map_to_server(filename, 11) == ("<cell2>", 2, True)

    assert source_mapping.map_to_server(filename, 12) == (filename, 12, False)

    # Map to client
    assert source_mapping.map_to_client(filename, 1) == (filename, 1, False)
    assert source_mapping.map_to_client(filename, 2) == (filename, 2, False)

    assert source_mapping.map_to_client("<cell1>", 5) == (filename, 3, True)
    assert source_mapping.map_to_client("<cell1>", 6) == (filename, 4, True)
    assert source_mapping.map_to_client("<cell1>", 7) == (filename, 5, True)
    assert source_mapping.map_to_client("<cell1>", 8) == (filename, 6, True)

    assert source_mapping.map_to_client(filename, 7) == (filename, 7, False)

    assert source_mapping.map_to_client("<cell2>", 1) == (filename, 10, True)
    assert source_mapping.map_to_client("<cell2>", 2) == (filename, 11, True)

    assert source_mapping.map_to_client(filename, 12) == (filename, 12, False)


@pytest.mark.skipif(IS_WINDOWS, reason="Linux/Mac-only test")
def test_mapping_conflict_to_client():
    import pydevd_file_utils

    path_mappings = []
    for pathMapping in _MAPPING_CONFLICT:
        localRoot = pathMapping.get("localRoot", "")
        remoteRoot = pathMapping.get("remoteRoot", "")
        if (localRoot != "") and (remoteRoot != ""):
            path_mappings.append((localRoot, remoteRoot))

    pydevd_file_utils.setup_client_server_paths(path_mappings)

    assert pydevd_file_utils.map_file_to_client("/opt/pathsomething/foo.py") == ("/var/home/p2/foo.py", True)

    assert pydevd_file_utils.map_file_to_client("/opt/v2/pathsomething/foo.py") == ("/var/home/p4/foo.py", True)

    # This is an odd case, but the user didn't really put a slash in the end,
    # so, it's possible that this is what the user actually wants.
    assert pydevd_file_utils.map_file_to_client("/opt/v2/path_r1/foo.py") == ("/var/home/p3_r1/foo.py", True)

    # The client said both local and remote end with a slash, so, we can only
    # match it with the slash in the end.
    assert pydevd_file_utils.map_file_to_client("/opt/pathsomething_foo.py") == ("/opt/pathsomething_foo.py", False)


_MAPPING_CONFLICT = [
    {"localRoot": "/var/home/p1/", "remoteRoot": "/opt/path/"},
    {"localRoot": "/var/home/p2/", "remoteRoot": "/opt/pathsomething/"},
    {"localRoot": "/var/home/p3", "remoteRoot": "/opt/v2/path"},
    {"localRoot": "/var/home/p4", "remoteRoot": "/opt/v2/pathsomething"},
]


@pytest.mark.skipif(IS_WINDOWS, reason="Linux/Mac-only test")
def test_mapping_conflict_to_server():
    import pydevd_file_utils

    path_mappings = []
    for pathMapping in _MAPPING_CONFLICT_TO_SERVER:
        localRoot = pathMapping.get("localRoot", "")
        remoteRoot = pathMapping.get("remoteRoot", "")
        if (localRoot != "") and (remoteRoot != ""):
            path_mappings.append((localRoot, remoteRoot))

    pydevd_file_utils.setup_client_server_paths(path_mappings)

    assert pydevd_file_utils.map_file_to_server("/opt/pathsomething/foo.py") == "/var/home/p2/foo.py"

    assert pydevd_file_utils.map_file_to_server("/opt/v2/pathsomething/foo.py") == "/var/home/p4/foo.py"

    # This is an odd case, but the user didn't really put a slash in the end,
    # so, it's possible that this is what the user actually wants.
    assert pydevd_file_utils.map_file_to_server("/opt/v2/path_r1/foo.py") == "/var/home/p3_r1/foo.py"

    # The client said both local and remote end with a slash, so, we can only
    # match it with the slash in the end.
    assert pydevd_file_utils.map_file_to_server("/opt/pathsomething_foo.py") == "/opt/pathsomething_foo.py"


_MAPPING_CONFLICT_TO_SERVER = [
    {"remoteRoot": "/var/home/p1/", "localRoot": "/opt/path/"},
    {"remoteRoot": "/var/home/p2/", "localRoot": "/opt/pathsomething/"},
    {"remoteRoot": "/var/home/p3", "localRoot": "/opt/v2/path"},
    {"remoteRoot": "/var/home/p4", "localRoot": "/opt/v2/pathsomething"},
]