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
|
# TestSwiftInterfaceNoDebugInfo.py
#
# This source file is part of the Swift.org open source project
#
# Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See https://swift.org/LICENSE.txt for license information
# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
#
# -----------------------------------------------------------------------------
"""
Test that we load and handle swift modules that only have textual
.swiftinterface files -- i.e. no associated .swiftmodule file -- and no debug
info. The module loader should generate the .swiftmodule for any
.swiftinterface it finds unless it is already in the module cache.
"""
import glob
import lldb
from lldbsuite.test.lldbtest import *
from lldbsuite.test.decorators import *
import lldbsuite.test.lldbutil as lldbutil
import os
import os.path
import unittest2
class TestSwiftInterfaceStaticNoDebugInfo(TestBase):
@swiftTest
def test_swift_interface(self):
"""Test that we load and handle modules that only have textual .swiftinterface files"""
self.build()
self.do_test()
@swiftTest
def test_swift_interface_fallback(self):
"""Test that we fall back to load from the .swiftinterface file if the .swiftmodule is invalid"""
self.build()
# install invalid modules in the build directory first to check we still fall back to the .swiftinterface
modules = ['AA.swiftmodule', 'BB.swiftmodule', 'CC.swiftmodule']
for module in modules:
open(self.getBuildArtifact(module), 'w').close()
self.do_test()
def do_test(self):
# The custom swift module cache location
swift_mod_cache = self.getBuildArtifact("MCP")
# Clear the swift module cache (populated by the Makefile build)
shutil.rmtree(swift_mod_cache)
self.assertFalse(os.path.isdir(swift_mod_cache),
"module cache should not exist")
# Update the settings to use the custom module cache location.
# Note: the clang module cache path setting is used for this currently.
self.runCmd('settings set symbols.clang-modules-cache-path "%s"' % swift_mod_cache)
# Set a breakpoint in and launch the main executable
lldbutil.run_to_source_breakpoint(
self, 'break here', lldb.SBFileSpec('main.swift'),
exe_name=self.getBuildArtifact("main"))
# Check we are able to access the public fields of variables whose
# types are from the .swiftinterface-only modules
var = self.frame().FindVariable("x")
lldbutil.check_variable(self, var, False, typename="AA.MyPoint")
child_y = var.GetChildMemberWithName("y") # MyPoint.y is public
lldbutil.check_variable(self, child_y, False, value="0")
# MyPoint.x isn't public, but LLDB can find it through type metadata.
child_x = var.GetChildMemberWithName("x")
self.assertTrue(child_x.IsValid())
# Expression evaluation using types from the .swiftinterface only
# modules should work too
lldbutil.check_expression(self, self.frame(),
"y.magnitudeSquared", "404",
use_summary=False)
lldbutil.check_expression(self, self.frame(),
"MyPoint(x: 1, y: 2).magnitudeSquared", "5",
use_summary=False)
# Check the swift module cache was populated with the .swiftmodule
# files of the loaded modules
self.assertTrue(os.path.isdir(swift_mod_cache), "module cache exists")
a_modules = glob.glob(os.path.join(swift_mod_cache, 'AA-*.swiftmodule'))
b_modules = glob.glob(os.path.join(swift_mod_cache, 'BB-*.swiftmodule'))
c_modules = glob.glob(os.path.join(swift_mod_cache, 'CC-*.swiftmodule'))
self.assertEqual(len(a_modules), 1)
self.assertEqual(len(b_modules), 1)
self.assertEqual(len(c_modules), 0)
# Update the timestamps of the modules to a time well in the past
for file in a_modules + b_modules:
make_old(file)
# Re-import module A and B
self.runCmd("expr import AA")
self.runCmd("expr import BB")
# Import C for the first time
self.runCmd("expr import CC")
# Check we still have a single .swiftmodule in the cache for A and B
# and that there is now one for C too
a_modules = glob.glob(os.path.join(swift_mod_cache, 'AA-*.swiftmodule'))
b_modules = glob.glob(os.path.join(swift_mod_cache, 'BB-*.swiftmodule'))
c_modules = glob.glob(os.path.join(swift_mod_cache, 'CC-*.swiftmodule'))
self.assertEqual(len(a_modules), 1, "unexpected number of swiftmodules for A.swift")
self.assertEqual(len(b_modules), 1, "unexpected number of swiftmodules for B.swift")
self.assertEqual(len(c_modules), 1, "unexpected number of swiftmodules for C.swift")
# Make sure the .swiftmodule files of A and B were re-used rather than
# re-generated when they were re-imported
for file in a_modules + b_modules:
self.assertTrue(is_old(file), "Swiftmodule file was regenerated rather than reused")
OLD_TIMESTAMP = 1390550700 # 2014-01-24T08:05:00+00:00
def make_old(file):
"""Sets the access and modified time of the given file to a time long past"""
os.utime(file, (OLD_TIMESTAMP, OLD_TIMESTAMP))
def is_old(file):
"""Checks the modified time of the given file matches the timestamp set my make_old"""
return os.stat(file).st_mtime == OLD_TIMESTAMP
|