From 56cd550e27c787f6dd1b090c69b84f4f1b8dd09e Mon Sep 17 00:00:00 2001 From: Pavel Punegov Date: Mon, 20 Mar 2023 13:56:42 +0000 Subject: [PATCH] [K/N][test] Remove old lldb tests that were replaced in the new infra These tests were replaced by the 842a66c3 and now located in :native:native.tests project Merge-request: KT-MR-9256 Merged-by: Pavel Punegov --- .../backend.native/tests/build.gradle | 24 - .../native/test/debugger/DistProperties.kt | 28 - .../kotlin/native/test/debugger/Driver.kt | 153 ---- .../native/test/debugger/DwarfDumpParser.kt | 363 --------- .../kotlin/native/test/debugger/DwarfTests.kt | 73 -- .../kotlin/native/test/debugger/LldbTests.kt | 755 ------------------ .../kotlin/native/test/debugger/Matchers.kt | 331 -------- .../kotlin/native/test/debugger/Utils.kt | 54 -- 8 files changed, 1781 deletions(-) delete mode 100644 kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DistProperties.kt delete mode 100644 kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/Driver.kt delete mode 100644 kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DwarfDumpParser.kt delete mode 100644 kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DwarfTests.kt delete mode 100644 kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/LldbTests.kt delete mode 100644 kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/Matchers.kt delete mode 100644 kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/Utils.kt diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index c3ed542bc44..cbc10eacce8 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -6193,11 +6193,6 @@ sourceSets { srcDir 'extensions/nop/src/main/kotlin' } } - test { - kotlin { - srcDir 'debugger/src/test/kotlin' - } - } } compileNopPluginKotlin { @@ -6625,25 +6620,6 @@ dependencies { api DependenciesKt.commonDependency(project, "junit") } -project.tasks.named("test").configure { - // Don't run this task as it will try to execute debugger tests too - // that is not desired as they are platform-specific. - enabled = false -} - -project.tasks.register("debugger_test", Test.class) { - enabled = (target.family.appleFamily) // KT-30366 - && !isAggressiveGC // No need to test with different GC schedulers - testLogging { exceptionFormat = 'full' } - UtilsKt.dependsOnDist(it) - systemProperties = ['kotlin.native.home': kotlinNativeDist, - 'kotlin.native.host': HostManager.@Companion.getHost(), - 'kotlin.native.test.target': target, - 'kotlin.native.test.debugger.simulator.enabled': findProperty("kotlin.native.test.debugger.simulator.enabled"), - 'kotlin.native.test.debugger.simulator.delay': findProperty("kotlin.native.test.debugger.simulator.delay")] - outputs.upToDateWhen { false } -} - // Configure build for iOS device targets. if (UtilsKt.supportsRunningTestsOnDevice(target) && !UtilsKt.getCompileOnlyTests(project)) { project.tasks diff --git a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DistProperties.kt b/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DistProperties.kt deleted file mode 100644 index 9d1de2ad171..00000000000 --- a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DistProperties.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the LICENSE file. - */ - -package org.jetbrains.kotlin.native.test.debugger - -import org.jetbrains.kotlin.konan.target.Family -import org.jetbrains.kotlin.konan.target.HostManager -import java.nio.file.Path -import java.nio.file.Paths - -object DistProperties { - private val dist: Path = Paths.get(requireProp("kotlin.native.home")) - private val konancDriver = if (HostManager.host.family == Family.MINGW) "konanc.bat" else "konanc" - private val cinteropDriver = if (HostManager.host.family == Family.MINGW) "cinterop.bat" else "cinterop" - val konanc: Path = dist.resolve("bin/$konancDriver") - val cinterop: Path = dist.resolve("bin/$cinteropDriver") - val lldb: Path = Paths.get("lldb") - val xcrun: Path = Paths.get("xcrun") - val devToolsSecurity: Path = Paths.get("DevToolsSecurity") - val dwarfDump: Path = Paths.get("dwarfdump") - val swiftc: Path = Paths.get("swiftc") - val lldbPrettyPrinters: Path = dist.resolve("tools/konan_lldb.py") - - private fun requireProp(name: String): String - = System.getProperty(name) ?: error("Property `$name` is not defined") -} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/Driver.kt b/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/Driver.kt deleted file mode 100644 index 9fe11fc091a..00000000000 --- a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/Driver.kt +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the LICENSE file. - */ - -package org.jetbrains.kotlin.native.test.debugger - -import kotlinx.coroutines.* -import org.jetbrains.kotlin.cli.bc.K2Native -import java.io.ByteArrayOutputStream -import java.io.InputStream -import java.io.StringReader -import java.lang.Thread.sleep -import java.nio.file.Files -import java.nio.file.Path -import java.util.concurrent.TimeUnit - - -class ToolDriver( - private val useInProcessCompiler: Boolean = false -) { - fun compile(source: Path, output: Path, vararg args: String) = compile(output, *args) { - listOf("-output", output.toString(), source.toString(), *args).toTypedArray() - } - - fun compile(output: Path, srcs: Array, vararg args: String) = compile(output, *args) { - listOf("-output", output.toString(), *srcs.map { it.toString() }.toTypedArray(), *args).toTypedArray() - } - - private fun crossPlatform(): Array = if (targetIsHost()) - emptyArray() - else - arrayOf("-target", target()) - - @Suppress("UNUSED_PARAMETER") - private fun compile(output: Path, vararg args: String, argsCalculator:() -> Array) { - check(!Files.exists(output)) - val allArgs = arrayOf(*crossPlatform(), *argsCalculator()) - - if (useInProcessCompiler) { - K2Native.main(allArgs) - } else { - subprocess(DistProperties.konanc, *allArgs).thrownIfFailed() - } - check(Files.exists(output)) { - "Compiler has not produced an output at $output" - } - } - - fun cinterop(defFile:Path, output: Path, pkg: String, vararg args: String) { - val allArgs = listOf("-o", output.toString(), "-def", defFile.toString(), "-pkg", pkg, *args).toTypedArray() - - //TODO: do we need in process cinterop? - subprocess(DistProperties.cinterop, *allArgs).thrownIfFailed() - check(Files.exists(output)) { - "Compiler has not produced an output at $output" - } - } - - fun runLldb(program: Path, commands: List): String { - val args = listOf("-b", *program.programOrAttach(), "-o", "command script import \"${DistProperties.lldbPrettyPrinters}\"", - *commands.flatMap { listOf("-o", it) }.toTypedArray()) - if (!targetIsHost()) { - return subprocess(DistProperties.xcrun, "simctl", "spawn", "-w", "-s", "iPhone 11", program.toString()) { - sleep(simulatorDelay()) - DistProperties.lldb to listOf(*args.toTypedArray(), "-o", "detach") - }.thrownIfFailed().stdout - } - return subprocess(DistProperties.lldb, *args.toTypedArray()).thrownIfFailed().stdout - } - - fun runDwarfDump(program: Path, vararg args:String = emptyArray(), processor:List.()->Unit) { - val dwarfProcess = subprocess(DistProperties.dwarfDump, *args, "${program}.dSYM/Contents/Resources/DWARF/${program.fileName}") - val out = dwarfProcess.takeIf { it.process.exitValue() == 0 }?.stdout ?: error(dwarfProcess.stderr) - DwarfUtilParser().parse(StringReader(out)).tags.toList().processor() - } - - fun swiftc(output: Path, swiftSrc: Path, vararg args: String): String { - val swiftProcess = subprocess(DistProperties.swiftc, "-o", output.toString(), swiftSrc.toString(), *args) - return swiftProcess.takeIf { it.process.exitValue() == 0 }?.stdout ?: error(swiftProcess.stderr) - } -} - -private fun Path.programOrAttach() = if (targetIsHost()) arrayOf(toString()) else arrayOf("-o", "process attach -n ${this.toString()}") - -data class ProcessOutput( - val program: Path, - val process: Process, - val stdout: String, - val stderr: String, - val durationMs: Long -) { - fun thrownIfFailed(): ProcessOutput { - fun renderStdStream(name: String, text: String): String = - if (text.isBlank()) "$name is empty" else "$name:\n$text" - - check(process.exitValue() == 0) { - """$program exited with non-zero value: ${process.exitValue()} - |${renderStdStream("stdout", stdout)} - |${renderStdStream("stderr", stderr)} - """.trimMargin() - } - return this - } -} - -fun subprocess(program: Path, vararg args: String, action: (() -> Pair>)? = null): ProcessOutput { - val start = System.currentTimeMillis() - val process = ProcessBuilder(program.toString(), *args).start() - val out = GlobalScope.async(Dispatchers.IO) { - readStream(process, process.inputStream.buffered()) - } - - val err = GlobalScope.async(Dispatchers.IO) { - readStream(process, process.errorStream.buffered()) - } - - val actionOutput = action?.let { - val p = it() - subprocess(p.first, *p.second.toTypedArray()) - } - - try { - val status = process.waitFor(5L, TimeUnit.MINUTES) - if (!status) { - out.cancel() - err.cancel() - error("$program timeouted") - } - }catch (e:Exception) { - out.cancel() - err.cancel() - error(e) - } - - return actionOutput ?: runBlocking { - ProcessOutput(program, process, out.await(), err.await(), System.currentTimeMillis() - start) - } -} - -private fun readStream(process: Process, stream: InputStream): String { - var size = 4096 - val buffer = ByteArray(size) { 0 } - val sunk = ByteArrayOutputStream() - while (true) { - size = stream.read(buffer, 0, buffer.size) - if (size < 0 && !process.isAlive) - break - if (size > 0) - sunk.write(buffer, 0, size) - } - return String(sunk.toByteArray()) -} diff --git a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DwarfDumpParser.kt b/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DwarfDumpParser.kt deleted file mode 100644 index d9d89e30ec5..00000000000 --- a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DwarfDumpParser.kt +++ /dev/null @@ -1,363 +0,0 @@ -package org.jetbrains.kotlin.native.test.debugger - -import java.io.File -import java.io.Reader -import java.lang.StringBuilder - -sealed class DwarfTag(val tag: Tag) { - enum class Tag(val value: Int) { - DW_TAG_array_type(0x0001), - DW_TAG_class_type(0x0002), - DW_TAG_entry_point(0x0003), - DW_TAG_enumeration_type(0x0004), - DW_TAG_formal_parameter(0x0005), - DW_TAG_imported_declaration(0x0008), - DW_TAG_label(0x000a), - DW_TAG_lexical_block(0x000b), - DW_TAG_member(0x000d), - DW_TAG_pointer_type(0x000f), - DW_TAG_reference_type(0x0010), - DW_TAG_compile_unit(0x0011), - DW_TAG_string_type(0x0012), - DW_TAG_structure_type(0x0013), - DW_TAG_subroutine_type(0x0015), - DW_TAG_typedef(0x0016), - DW_TAG_union_type(0x0017), - DW_TAG_unspecified_parameters(0x0018), - DW_TAG_variant(0x0019), - DW_TAG_common_block(0x001a), - DW_TAG_common_inclusion(0x001b), - DW_TAG_inheritance(0x001c), - DW_TAG_inlined_subroutine(0x001d), - DW_TAG_module(0x001e), - DW_TAG_ptr_to_member_type(0x001f), - DW_TAG_set_type(0x0020), - DW_TAG_subrange_type(0x0021), - DW_TAG_with_stmt(0x0022), - DW_TAG_access_declaration(0x0023), - DW_TAG_base_type(0x0024), - DW_TAG_catch_block(0x0025), - DW_TAG_const_type(0x0026), - DW_TAG_constant(0x0027), - DW_TAG_enumerator(0x0028), - DW_TAG_file_type(0x0029), - DW_TAG_friend(0x002a), - DW_TAG_namelist(0x002b), - DW_TAG_namelist_item(0x002c), - DW_TAG_packed_type(0x002d), - DW_TAG_subprogram(0x002e), - DW_TAG_template_type_parameter(0x002f), - DW_TAG_template_value_parameter(0x0030), - DW_TAG_thrown_type(0x0031), - DW_TAG_try_block(0x0032), - DW_TAG_variant_part(0x0033), - DW_TAG_variable(0x0034), - DW_TAG_volatile_type(0x0035), - DW_TAG_dwarf_procedure(0x0036), - DW_TAG_restrict_type(0x0037), - DW_TAG_interface_type(0x0038), - DW_TAG_namespace(0x0039), - DW_TAG_imported_module(0x003a), - DW_TAG_unspecified_type(0x003b), - DW_TAG_partial_unit(0x003c), - DW_TAG_imported_unit(0x003d), - DW_TAG_condition(0x003f), - DW_TAG_shared_type(0x0040), - DW_TAG_type_unit(0x0041), - DW_TAG_rvalue_reference_type(0x0042), - DW_TAG_template_alias(0x0043), - DW_TAG_coarray_type(0x0044), - DW_TAG_generic_subrange(0x0045), - DW_TAG_dynamic_type(0x0046), - DW_TAG_MIPS_loop(0x4081), - DW_TAG_format_label(0x4101), - DW_TAG_function_template(0x4102), - DW_TAG_class_template(0x4103), - DW_TAG_GNU_template_template_param(0x4106), - DW_TAG_GNU_template_parameter_pack(0x4107), - DW_TAG_GNU_formal_parameter_pack(0x4108), - DW_TAG_APPLE_property(0x4200), - DW_TAG_BORLAND_property(0xb000), - DW_TAG_BORLAND_Delphi_string(0xb001), - DW_TAG_BORLAND_Delphi_dynamic_array(0xb002), - DW_TAG_BORLAND_Delphi_set(0xb003), - DW_TAG_BORLAND_Delphi_variant(0xb004), - } - val attributes = mutableMapOf() - operator fun DwarfAttribute.unaryPlus() { attributes[this.attribute] = this } - companion object { - fun by(name: String) = by(Tag.valueOf(name)) - fun by(tag: Tag) = when(tag) { - Tag.DW_TAG_subprogram -> DwarfTagSubprogram() - else -> DwarfTagDefault(tag) - } - } -} - -class DwarfTagDefault(tag: DwarfTag.Tag): DwarfTag(tag) -class DwarfTagSubprogram: DwarfTag(Tag.DW_TAG_subprogram) { - val name: String - get() = attributes[DwarfAttribute.Attribute.DW_AT_name]!!.rvString - val path: String? - get() = attributes[DwarfAttribute.Attribute.DW_AT_decl_file]?.rvString - val file: File? - get() = path?.run { File(this) } -} - -class DwarfAttribute(val attribute: Attribute, val rawValue: String) { - enum class Attribute(val value: Int) { - DW_AT_sibling(0x01), - DW_AT_location(0x02), - DW_AT_name(0x03), - DW_AT_ordering(0x09), - DW_AT_byte_size(0x0b), - DW_AT_bit_offset(0x0c), - DW_AT_bit_size(0x0d), - DW_AT_stmt_list(0x10), - DW_AT_low_pc(0x11), - DW_AT_high_pc(0x12), - DW_AT_language(0x13), - DW_AT_discr(0x15), - DW_AT_discr_value(0x16), - DW_AT_visibility(0x17), - DW_AT_import(0x18), - DW_AT_string_length(0x19), - DW_AT_common_reference(0x1a), - DW_AT_comp_dir(0x1b), - DW_AT_const_value(0x1c), - DW_AT_containing_type(0x1d), - DW_AT_default_value(0x1e), - DW_AT_inline(0x20), - DW_AT_is_optional(0x21), - DW_AT_lower_bound(0x22), - DW_AT_producer(0x25), - DW_AT_prototyped(0x27), - DW_AT_return_addr(0x2a), - DW_AT_start_scope(0x2c), - DW_AT_bit_stride(0x2e), - DW_AT_upper_bound(0x2f), - DW_AT_abstract_origin(0x31), - DW_AT_accessibility(0x32), - DW_AT_address_class(0x33), - DW_AT_artificial(0x34), - DW_AT_base_types(0x35), - DW_AT_calling_convention(0x36), - DW_AT_count(0x37), - DW_AT_data_member_location(0x38), - DW_AT_decl_column(0x39), - DW_AT_decl_file(0x3a), - DW_AT_decl_line(0x3b), - DW_AT_declaration(0x3c), - DW_AT_discr_list(0x3d), - DW_AT_encoding(0x3e), - DW_AT_external(0x3f), - DW_AT_frame_base(0x40), - DW_AT_friend(0x41), - DW_AT_identifier_case(0x42), - DW_AT_macro_info(0x43), - DW_AT_namelist_item(0x44), - DW_AT_priority(0x45), - DW_AT_segment(0x46), - DW_AT_specification(0x47), - DW_AT_static_link(0x48), - DW_AT_type(0x49), - DW_AT_use_location(0x4a), - DW_AT_variable_parameter(0x4b), - DW_AT_virtuality(0x4c), - DW_AT_vtable_elem_location(0x4d), - DW_AT_allocated(0x4e), - DW_AT_associated(0x4f), - DW_AT_data_location(0x50), - DW_AT_byte_stride(0x51), - DW_AT_entry_pc(0x52), - DW_AT_use_UTF8(0x53), - DW_AT_extension(0x54), - DW_AT_ranges(0x55), - DW_AT_trampoline(0x56), - DW_AT_call_column(0x57), - DW_AT_call_file(0x58), - DW_AT_call_line(0x59), - DW_AT_description(0x5a), - DW_AT_binary_scale(0x5b), - DW_AT_decimal_scale(0x5c), - DW_AT_small(0x5d), - DW_AT_decimal_sign(0x5e), - DW_AT_digit_count(0x5f), - DW_AT_picture_string(0x60), - DW_AT_mutable(0x61), - DW_AT_threads_scaled(0x62), - DW_AT_explicit(0x63), - DW_AT_object_pointer(0x64), - DW_AT_endianity(0x65), - DW_AT_elemental(0x66), - DW_AT_pure(0x67), - DW_AT_recursive(0x68), - DW_AT_signature(0x69), - DW_AT_main_subprogram(0x6a), - DW_AT_data_bit_offset(0x6b), - DW_AT_const_expr(0x6c), - DW_AT_enum_class(0x6d), - DW_AT_linkage_name(0x6e), - DW_AT_string_length_bit_size(0x6f), - DW_AT_string_length_byte_size(0x70), - DW_AT_rank(0x71), - DW_AT_str_offsets_base(0x72), - DW_AT_addr_base(0x73), - DW_AT_rnglists_base(0x74), - DW_AT_dwo_id(0x75), ///< Retracted from DWARF v5. - DW_AT_dwo_name(0x76), - DW_AT_reference(0x77), - DW_AT_rvalue_reference(0x78), - DW_AT_macros(0x79), - DW_AT_call_all_calls(0x7a), - DW_AT_call_all_source_calls(0x7b), - DW_AT_call_all_tail_calls(0x7c), - DW_AT_call_return_pc(0x7d), - DW_AT_call_value(0x7e), - DW_AT_call_origin(0x7f), - DW_AT_call_parameter(0x80), - DW_AT_call_pc(0x81), - DW_AT_call_tail_call(0x82), - DW_AT_call_target(0x83), - DW_AT_call_target_clobbered(0x84), - DW_AT_call_data_location(0x85), - DW_AT_call_data_value(0x86), - DW_AT_noreturn(0x87), - DW_AT_alignment(0x88), - DW_AT_export_symbols(0x89), - DW_AT_deleted(0x8a), - DW_AT_defaulted(0x8b), - DW_AT_loclists_base(0x8c), - DW_AT_MIPS_loop_begin(0x2002), - DW_AT_MIPS_tail_loop_begin(0x2003), - DW_AT_MIPS_epilog_begin(0x2004), - DW_AT_MIPS_loop_unroll_factor(0x2005), - DW_AT_MIPS_software_pipeline_depth(0x2006), - DW_AT_MIPS_linkage_name(0x2007), - DW_AT_MIPS_stride(0x2008), - DW_AT_MIPS_abstract_name(0x2009), - DW_AT_MIPS_clone_origin(0x200a), - DW_AT_MIPS_has_inlines(0x200b), - DW_AT_MIPS_stride_byte(0x200c), - DW_AT_MIPS_stride_elem(0x200d), - DW_AT_MIPS_ptr_dopetype(0x200e), - DW_AT_MIPS_allocatable_dopetype(0x200f), - DW_AT_MIPS_assumed_shape_dopetype(0x2010), - DW_AT_MIPS_assumed_size(0x2011), - DW_AT_sf_names(0x2101), - DW_AT_src_info(0x2102), - DW_AT_mac_info(0x2103), - DW_AT_src_coords(0x2104), - DW_AT_body_begin(0x2105), - DW_AT_body_end(0x2106), - DW_AT_GNU_vector(0x2107), - DW_AT_GNU_template_name(0x2110), - DW_AT_GNU_odr_signature(0x210f), - DW_AT_GNU_call_site_value(0x2111), - DW_AT_GNU_all_call_sites(0x2117), - DW_AT_GNU_macros(0x2119), - DW_AT_GNU_dwo_name(0x2130), - DW_AT_GNU_dwo_id(0x2131), - DW_AT_GNU_ranges_base(0x2132), - DW_AT_GNU_addr_base(0x2133), - DW_AT_GNU_pubnames(0x2134), - DW_AT_GNU_pubtypes(0x2135), - DW_AT_GNU_discriminator(0x2136), - DW_AT_BORLAND_property_read(0x3b11), - DW_AT_BORLAND_property_write(0x3b12), - DW_AT_BORLAND_property_implements(0x3b13), - DW_AT_BORLAND_property_index(0x3b14), - DW_AT_BORLAND_property_default(0x3b15), - DW_AT_BORLAND_Delphi_unit(0x3b20), - DW_AT_BORLAND_Delphi_class(0x3b21), - DW_AT_BORLAND_Delphi_record(0x3b22), - DW_AT_BORLAND_Delphi_metaclass(0x3b23), - DW_AT_BORLAND_Delphi_constructor(0x3b24), - DW_AT_BORLAND_Delphi_destructor(0x3b25), - DW_AT_BORLAND_Delphi_anonymous_method(0x3b26), - DW_AT_BORLAND_Delphi_interface(0x3b27), - DW_AT_BORLAND_Delphi_ABI(0x3b28), - DW_AT_BORLAND_Delphi_return(0x3b29), - DW_AT_BORLAND_Delphi_frameptr(0x3b30), - DW_AT_BORLAND_closure(0x3b31), - DW_AT_LLVM_include_path(0x3e00), - DW_AT_LLVM_config_macros(0x3e01), - DW_AT_LLVM_isysroot(0x3e02), - DW_AT_APPLE_optimized(0x3fe1), - DW_AT_APPLE_flags(0x3fe2), - DW_AT_APPLE_isa(0x3fe3), - DW_AT_APPLE_block(0x3fe4), - DW_AT_APPLE_major_runtime_vers(0x3fe5), - DW_AT_APPLE_runtime_class(0x3fe6), - DW_AT_APPLE_omit_frame_ptr(0x3fe7), - DW_AT_APPLE_property_name(0x3fe8), - DW_AT_APPLE_property_getter(0x3fe9), - DW_AT_APPLE_property_setter(0x3fea), - DW_AT_APPLE_property_attribute(0x3feb), - DW_AT_APPLE_objc_complete_type(0x3fec), - DW_AT_APPLE_property(0x3fed), - } - - companion object { - fun by(name: String, rawValue: String): DwarfAttribute = by(Attribute.valueOf(name), rawValue) - fun by(attribute: Attribute, rawValue: String) = DwarfAttribute(attribute, rawValue) - } -} - -val DwarfAttribute.rvString: String - get() = rawValue.trim().substring(1, rawValue.length - 2) - - -class DwarfUtilParser() { - val tags = mutableListOf() - var currentTag: DwarfTag? = null - var currentAttribute: DwarfAttribute.Attribute? = null - val currentAttributePayload = StringBuilder() - companion object { - val tagRegexp = Regex("^(0x[0-9a-f]{8}):\\ +([^\\ .]*)$") - val attributeRegexp = Regex("^\\s+(DW_AT_[a-zA-Z0-9_]*)\\s+\\((.*)\\)$") - } - - fun tag(tag: DwarfTag) { - appendCurrentAttribute() - tags.add(tag) - currentTag = tag - currentAttribute = null - } - - private fun appendCurrentAttribute() { - currentTag ?: return - with(currentTag!!) { - currentAttribute ?: return - +DwarfAttribute.by(currentAttribute!!, currentAttributePayload.toString()) - currentAttributePayload.clear() - } - } - - fun attribute(attribute: DwarfAttribute.Attribute, payload: String) { - appendCurrentAttribute() - currentAttribute = attribute - currentAttributePayload.appendLine(payload) - } - - fun parse(reader: Reader): DwarfUtilParser { - reader.forEachLine { line -> - tagRegexp.find(line)?.apply { - val str = this.destructured.component2().trim() - if (str == "NULL") - return@forEachLine - tag(DwarfTag.by(str)) - return@forEachLine - } - - attributeRegexp.find(line)?.apply { - attribute(DwarfAttribute.Attribute.valueOf(destructured.component1()), destructured.component2()) - return@forEachLine - } - - currentTag ?: return@forEachLine - currentAttributePayload.appendLine(line) - } - return this - } -} diff --git a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DwarfTests.kt b/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DwarfTests.kt deleted file mode 100644 index bfc1e204374..00000000000 --- a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DwarfTests.kt +++ /dev/null @@ -1,73 +0,0 @@ -package org.jetbrains.kotlin.native.test.debugger - -import org.junit.Assert.* -import org.junit.Ignore -import org.junit.Test - -class DwarfTests { - @Test - fun `prefix test`() = dwarfDumpTest(""" - fun main(args: Array) { - val xs = intArrayOf(3, 5, 8) - return - } - - data class Point(val x: Int, val y: Int) - """.trimIndent(), listOf("-Xdebug-prefix-map=${System.getProperty("user.home")}=/xxx")){ - val map = flatMap( fun (it: DwarfTag): List { return it.attributes.values.toList()}) - .filter { it.attribute == DwarfAttribute.Attribute.DW_AT_decl_file }.map { it.rvString } - assertNotSame(0, map.size) - } - - /** - * TODO: to enable this test it's required to fix issue with poisonig call site with wrong file owner ship of lambda - * passed as parameter to inline function. - */ - @Test - fun `address of VolatileLambda lookup`() = dwarfDumpComplexTest { - val callbackLibrary = """ - --- - int callback(int (*f)(int)) { - return 42 + f(0xdeadbeef); - } - """.trimIndent().cinterop("callback", "callback") - val trapLibrary = """ - --- - void trap() { - __builtin_trap(); - } - """.trimIndent().cinterop("trap", "trap") - - val poisonLibrary = """ - package poison - import trap.* - import callback.* - import kotlinx.cinterop.staticCFunction - - - inline fun execute():Int { - return callback(staticCFunction{ - a -> - trap() - 2 * a - }) - } - """.trimIndent().library("poison", "-l", callbackLibrary.toString(), "-l", trapLibrary.toString()) - - val binary = """ - import poison.* - - fun main() { - execute() - } - """.trimIndent().binary("poisoned", "-g", "-l", poisonLibrary.toString(), "-l", callbackLibrary.toString(), "-l", trapLibrary.toString()) - - binary.dwarfDumpLookup("kfun:main\$lambda$0#internal") { - assertFalse(this.isEmpty()) - val subprogram = single { it.tag == DwarfTag.Tag.DW_TAG_subprogram } as DwarfTagSubprogram - assertEquals(subprogram.file!!.name, "poison.kt") - } - } - - -} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/LldbTests.kt b/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/LldbTests.kt deleted file mode 100644 index e60c9c78aa5..00000000000 --- a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/LldbTests.kt +++ /dev/null @@ -1,755 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the LICENSE file. - */ - -import org.jetbrains.kotlin.native.test.debugger.lldbCommandRunOrContinue -import org.jetbrains.kotlin.native.test.debugger.lldbComplexTest -import org.jetbrains.kotlin.native.test.debugger.lldbCheckLineNumbers -import org.jetbrains.kotlin.native.test.debugger.lldbTest -import org.junit.Test - -class LldbTests { - @Test - fun `can step through code`() = lldbTest(""" - fun main(args: Array) { - var x = 1 - var y = 2 - var z = x + y - println(z) - } - """, """ - > b main.kt:2 - Breakpoint 1: [..] - - > ${lldbCommandRunOrContinue()} - Process [..] stopped - [..] stop reason = breakpoint 1.1 - [..] at main.kt:2[..] - - > n - Process [..] stopped - [..] stop reason = step over - [..] at main.kt:3[..] - - > n - Process [..] stopped - [..] stop reason = step over - [..] at main.kt:4[..] - - > n - Process [..] stopped - [..] stop reason = step over - [..] at main.kt:5[..] - > q - """) - - @Test - fun `can inspect values of primitive types`() = lldbTest(""" - fun main(args: Array) { - var a: Byte = 1 - var b: Int = 2 - var c: Long = -3 - var d: Char = 'c' - var e: Boolean = true - return - } - """, """ - > b main.kt:7 - > ${lldbCommandRunOrContinue()} - > fr var - (char) a = '\x01' - (int) b = 2 - (long) c = -3 - (short) d = 99 - (bool) e = true - > q - """) - - @Test - fun `can inspect classes`() = lldbTest(""" - fun main(args: Array) { - val point = Point(1, 2) - val person = Person() - return - } - - data class Point(val x: Int, val y: Int) - class Person { - override fun toString() = "John Doe" - } - """, """ - > b main.kt:4 - > ${lldbCommandRunOrContinue()} - > fr var - (ObjHeader *) args = [] - (ObjHeader *) point = [x: ..., y: ...] - (ObjHeader *) person = [] - > q - """) - - @Test - fun `can inspect arrays`() = lldbTest(""" - fun main(args: Array) { - val xs = IntArray(3) - xs[0] = 1 - xs[1] = 2 - xs[2] = 3 - val ys: Array = arrayOfNulls(2) - ys[0] = Point(1, 2) - return - } - - data class Point(val x: Int, val y: Int) - """, """ - > b main.kt:8 - > ${lldbCommandRunOrContinue()} - > fr var - (ObjHeader *) args = [] - (ObjHeader *) xs = [..., ..., ...] - (ObjHeader *) ys = [..., ...] - > q - """) - - @Test - fun `can inspect array children`() = lldbTest(""" - fun main(args: Array) { - val xs = intArrayOf(3, 5, 8) - return - } - - data class Point(val x: Int, val y: Int) - """, """ - > b main.kt:3 - > ${lldbCommandRunOrContinue()} - > fr var xs - (ObjHeader *) xs = [..., ..., ...] - > q - """) - - @Test - fun `can inspect catch parameter`() = lldbTest(""" - fun main() { - try { - throw Exception("message 1") - } catch (e1: Throwable) { - println(e1.message) - } - - try { - throwError() - } catch (e2: Throwable) { - println(e2.message) - } - } - - fun throwError() { - throw Error("message 2") - } - """, """ - > b main.kt:5 - > ${lldbCommandRunOrContinue()} - > fr var - (ObjHeader *) e1 = [..] - > b main.kt:11 - > c - > fr var - (ObjHeader *) e2 = [..] - > q - """) - - @Test - fun `swift with kotlin static framework`() = lldbComplexTest { - val aKtSrc = """ - fun a() = "a" - """.feedOutput("a.kt") - val bKtSrc = """ - fun b() = "b" - """.feedOutput("b.kt") - - arrayOf(aKtSrc, bKtSrc).framework("AandBFramework", "-g", "-Xstatic-framework") - - val swiftSrc = """ - import AandBFramework - - print(AKt.a()) - print(BKt.b()) - - """.feedOutput("test.swift") - val application = swiftc("application", swiftSrc, "-F", root.toString()) - """ - > b kfun:#b(){}kotlin.String - Breakpoint 1: where = [..]`kfun:#b(){}kotlin.String [..] at b.kt:1:1, [..] - - > b kfun:#a(){}kotlin.String - Breakpoint 2: where = [..]`kfun:#a(){}kotlin.String [..] at a.kt:1:1, [..] - > q - """.trimIndent().lldb(application) - } - - @Test - fun `kt33055`() = lldbComplexTest { - val kt33055 = """ - |fun question(subject: String, names: Array = emptyArray()): String { - | return buildString { // breakpoint here - | append("${"$"}subject?") // actual stop - | for (name in names) - | append(" ${"$"}name?") - | } - |} - | - |fun main(args: Array) { - | println(question("Subject", args)) - |} - """.trimMargin().binary("kt33055", "-g", "-Xg-generate-debug-trampoline=enable") - """ - > b 2 - Breakpoint 1: where = [..]`kfun:#question(kotlin.String;kotlin.Array){}kotlin.String [..] at kt33055.kt:2:12, [..] - > q - """.trimIndent().lldb(kt33055) - } - - @Test - fun `kt33364`() = lldbComplexTest { - val kt33364 = """ - |fun main() { - | val param = 3 - | - | //breakpoint here (line: 4, breakpoint is set to 5th line) - | when(param) { - | 1 -> print("A") - | 2 -> print("B") - | else -> print("C") - | } - | - | // breakpoint here (line: 11, breakpoint is set to 12th line) - | when { - | param == 1 -> print("A") - | param == 2 -> print("B") - | else -> print("C") - | } - |} - """.trimMargin().binary("kt33364", "-g", "-Xg-generate-debug-trampoline=enable") - """ - > b 5 - Breakpoint 1: where = [..]kfun:#main(){} [..] at kt33364.kt:5:[..] - > b 11 - Breakpoint 2: where = [..]kfun:#main(){} [..] at kt33364.kt:12:[..] - > q - """.trimIndent().lldb(kt33364) - } - - @Test - fun `kt42208`() = lldbComplexTest { - val kt42208One = """ - fun main() { - foo()() - } - """.feedOutput("kt42208-1.kt") - val kt42208Two = """ - // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - inline fun foo() = { - throw Error() - } - """.feedOutput("kt42208-2.kt") - val binary = arrayOf(kt42208One, kt42208Two).binary("kt42208", "-g") - """ - > b ThrowException - > ${lldbCommandRunOrContinue()} - > bt - * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 - * frame #0: [..] kt42208.kexe`ThrowException - frame #1: [..] kt42208.kexe`kfun:main${'$'}lambda${'$'}0#internal at kt42208-2.kt:3:18 - frame #2: [..] kt42208.kexe`kfun:${'$'}main${'$'}lambda${'$'}0${'$'}FUNCTION_REFERENCE${'$'}0.invoke#internal(_this=[..]) at kt42208-1.kt:2:5 - frame #3: [..] kt42208.kexe`kfun:${'$'}main${'$'}lambda${'$'}0${'$'}FUNCTION_REFERENCE${'$'}0.${'$'}invoke(_this=[..]){}kotlin.Nothing#internal at kt42208-1.kt:2:5 - frame #4: [..] kt42208.kexe`kfun:#main(){} at kt42208-1.kt:2:5 - frame #5: [..] kt42208.kexe`Konan_start(args=[..]) at kt42208-1.kt:1:1 - frame #6: [..] - frame #7: [..] - > q - """.trimIndent().lldb(binary) - } - - @Test - fun `kt42208 with variable`() = lldbComplexTest { - val kt42208One = """ - fun main() { - val a = foo() - a() - a() - a() - } - """.feedOutput("kt42208-1.kt") - val kt42208Two = """ - // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - class A - val list = mutableListOf() - inline fun foo() = { -> - list.add(A()) - } - """.feedOutput("kt42208-2.kt") - val binary = arrayOf(kt42208One, kt42208Two).binary("kt42208", "-g") - """ - > b kt42208-2.kt:5 - > ${lldbCommandRunOrContinue()} - > bt - * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 - * frame #0: [..] kt42208.kexe`kfun:main${'$'}lambda${'$'}0#internal at kt42208-2.kt:5:5 - frame #1: [..] kt42208.kexe`kfun:${'$'}main${'$'}lambda${'$'}0${'$'}FUNCTION_REFERENCE${'$'}0.invoke#internal(_this=[..]) at kt42208-1.kt:2:5 - frame #2: [..] kt42208.kexe`kfun:${'$'}main${'$'}lambda${'$'}0${'$'}FUNCTION_REFERENCE${'$'}0.${'$'}invoke(_this=[..]){}kotlin.Boolean#internal at kt42208-1.kt:2:5 - frame #3: [..] kt42208.kexe`kfun:#main(){} at kt42208-1.kt:3:5 - frame #4: [..] kt42208.kexe`Konan_start(args=[..]) at kt42208-1.kt:1:1 - frame #5: [..] - > c - > bt - * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 - * frame #0: [..] kt42208.kexe`kfun:main${'$'}lambda${'$'}0#internal at kt42208-2.kt:5:5 - frame #1: [..] kt42208.kexe`kfun:${'$'}main${'$'}lambda${'$'}0${'$'}FUNCTION_REFERENCE${'$'}0.invoke#internal(_this=[..]) at kt42208-1.kt:2:5 - frame #2: [..] kt42208.kexe`kfun:${'$'}main${'$'}lambda${'$'}0${'$'}FUNCTION_REFERENCE${'$'}0.${'$'}invoke(_this=[..]){}kotlin.Boolean#internal at kt42208-1.kt:2:5 - frame #3: [..] kt42208.kexe`kfun:#main(){} at kt42208-1.kt:4:5 - frame #4: [..] kt42208.kexe`Konan_start(args=[..]) at kt42208-1.kt:1:1 - > c - > bt - * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 - * frame #0: [..] kt42208.kexe`kfun:main${'$'}lambda${'$'}0#internal at kt42208-2.kt:5:5 - frame #1: [..] kt42208.kexe`kfun:${'$'}main${'$'}lambda${'$'}0${'$'}FUNCTION_REFERENCE${'$'}0.invoke#internal(_this=[..]) at kt42208-1.kt:2:5 - frame #2: [..] kt42208.kexe`kfun:${'$'}main${'$'}lambda${'$'}0${'$'}FUNCTION_REFERENCE${'$'}0.${'$'}invoke(_this=[..]){}kotlin.Boolean#internal at kt42208-1.kt:2:5 - frame #3: [..] kt42208.kexe`kfun:#main(){} at kt42208-1.kt:5:5 - frame #4: [..] kt42208.kexe`Konan_start(args=[..]) at kt42208-1.kt:1:1 - > q - """.trimIndent().lldb(binary) - } - - - @Test - fun `kt42208 with passing lambda to another function`() = lldbComplexTest { - val kt42208One = """ - fun main() { - val a = foo() - bar(a) - } - """.feedOutput("kt42208-1.kt") - val kt42208Two = """ - // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - class A - val list = mutableListOf() - inline fun foo() = { -> - list.add(A()) - } - """.feedOutput("kt42208-2.kt") - - val kt42208Three = """ - fun bar(v:(()->Unit)) { - v() - } - """.feedOutput("kt42208-3.kt") - val binary = arrayOf(kt42208One, kt42208Two, kt42208Three).binary("kt42208", "-g", "-XXLanguage:+UnitConversionsOnArbitraryExpressions") - """ - > b kt42208-2.kt:5 - > ${lldbCommandRunOrContinue()} - > bt - * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 - * frame #0: [..] kt42208.kexe`kfun:main${'$'}lambda${'$'}0#internal at kt42208-2.kt:5:5 - frame #1: [..] kt42208.kexe`kfun:${'$'}main${'$'}lambda${'$'}0${'$'}FUNCTION_REFERENCE${'$'}0.invoke#internal(_this=[..]) at kt42208-1.kt:2:5 - frame #2: [..] kt42208.kexe`kfun:${'$'}main${'$'}lambda${'$'}0${'$'}FUNCTION_REFERENCE${'$'}0.${'$'}invoke(_this=[..]){}kotlin.Boolean#internal at kt42208-1.kt:2:5 - frame #3: [..] kt42208.kexe`kfun:#bar(v=[]){} at kt42208-3.kt:2:4 - frame #4: [..] kt42208.kexe`kfun:#main(){} at kt42208-1.kt:3:5 - frame #5: [..] kt42208.kexe`Konan_start(args=[]) at kt42208-1.kt:1:1 - > c - > q - """.trimIndent().lldb(binary) - } - - @Test - fun `kt47198`() = lldbComplexTest { - val kt47198 = """ - fun foo(a:Int) = print("a: ${'$'}a") - - fun main() { - foo(33) - } - """.feedOutput("kt47198.kt") - - val binary = arrayOf(kt47198).binary("kt47198", "-g") - """ - > b 1 - Breakpoint 1: where = kt47198.kexe`kfun:#foo(kotlin.Int){} [..] at kt47198.kt:1:1, [..] - > ${lldbCommandRunOrContinue()} - > fr v - (int) a = 33 - > q - """.trimIndent().lldb(binary) - } - - @Test - fun `kt47198 with body`() = lldbComplexTest { - val kt47198 = """ - fun foo(a:Int){ - print("a: ${'$'}a") - } - - fun main() { - foo(33) - } - """.feedOutput("kt47198.kt") - - val binary = arrayOf(kt47198).binary("kt47198", "-g") - """ - > b 1 - Breakpoint 1: where = kt47198.kexe`kfun:#foo(kotlin.Int){} [..] at kt47198.kt:1:[..] - > ${lldbCommandRunOrContinue()} - > fr v - (int) a = 33 - > q - """.trimIndent().lldb(binary) - } - - @Test - fun `lldb line numbers are valid in source`() { - // Whitespace is important, since the character offsets are what defines source lines - lldbCheckLineNumbers(mapOf( - "main.kt" to """ - - fun main() { - - inliner { - - println("1") - - } - - inliner { - - println("2") - - } - - } - -""", "inliner.kt" to """ - ${" ".repeat(1000)} - inline fun inliner(block: ()->Unit) { - - block() - - } - -"""), "main.kt:2", 15) - } - - @Test - fun `works in native thread state`() = lldbComplexTest { - // This test checks that K/N runtime debug interface properly handles the cases when a calling thread is in native state. - - // So we need to stop on a breakpoint in native code, but inspect Kotlin code. - // To achieve that, we set breakpoint on `write` function, and call `println` to trigger it. - // The `test` function is recursive -- this little trick helps us to switch to frame 10 in the debugger, - // and be sure that it is in `test` function regardless of how the inline works for println and its callees. - - val program = """ - fun main() { - test(10) - } - - fun test(n: Int) { - val myData = MyData(1, longArrayOf(2, 3), "four", arrayOf("five", "six")) - val i = 7 - val la = longArrayOf(8, 9) - val s = "ten" - val a = arrayOf("eleven") - - if (n > 0) test(n - 1) - - println("Hello") - } - - class MyData(val i: Int, val la: LongArray, val s: String, val a: Array) - - """.trimIndent().binary("nativestate", "-g", "-Xbinary=runtimeAssertionsMode=panic") - - // Now we can just stop on `write`, switch frame to Kotlin code and try using different debug interface functions, both directly - // and indirectly (through konan_lldb.py, which integrates the built-in lldb capabilities like `frame variable` command with - // K/N debug interface). - """ - > b write - Breakpoint 1: [..] - > ${lldbCommandRunOrContinue()} - [..] stop reason = breakpoint [..] - > frame select 10 - -> 12 if (n > 0) test(n - 1) - > frame variable - (int) i = 7 - (ObjHeader *) myData = [la: ..., s: ..., a: ..., i: ...] - (ObjHeader *) la = [..., ...] - (ObjHeader *) s = [..] - (ObjHeader *) a = [...] - > expression -- (int32_t)Konan_DebugPrint(s) - ten(int32_t) [..] = 0 - > expression -- (int32_t)Konan_DebugPrint(la) - [8, 9](int32_t) [..] = 0 - > expression -- (int32_t)Konan_DebugPrint(myData) - MyData@[..](int32_t) [..] = 0 - > script lldb.frame.FindVariable("myData").GetChildMemberWithName("i").Dereference().GetValue() - '1' - > q - """.trimIndent().lldb(program) - } - - @Test - fun `inline function arguments as expressions are visible`() = lldbTest(""" - inline fun foo( - p1: Int, p2: Int, p3: Int, p4: Int, p5: Int, p6: Int, p7: Int, - f: (Int, Int, Int, Int, Int, Int, Int) -> Unit - ) { - println() - f(p1, p2, p3, p4, p5, p6, p7) - } - - fun bar() = 3 - inline fun baz() = 3 - fun getCondition() = true - fun getNull(): Int? = null - - const val X = 10 - - fun main() { - val tmp = bar() - foo( - 1, - tmp, - tmp + 2, - bar(), - X, - if (getCondition()) 1 else 2, - when { - tmp >= 0 -> 1 - tmp < 0 -> 2 - else -> 0 - } - ) { p1, p2, p3, p4, p5, p6, p7 -> - println(p1 + p2 + p3 + p4 + p5 + p6 + p7) - } - - foo( - { 2 + 2 }(), - baz(), - listOf(1, 2, 3).filter { it > 2 }.sum(), - getNull()?.let { it + 1 } ?: 0, - try { bar() } finally { baz() }, - "".length, - object : Any() { - override fun hashCode(): Int { - return 1 - } - }.hashCode() - ) { p1, p2, p3, p4, p5, p6, p7 -> - println(p1 + p2 + p3 + p4 + p5 + p6 + p7) - } - } - """, """ - > b main.kt:5 - > b main.kt:31 - > b main.kt:47 - > ${lldbCommandRunOrContinue()} - > v - (int) p1 = 1 - (int) p2 = 3 - (int) p3 = 5 - (int) p4 = 3 - (int) p5 = 10 - (int) p6 = 1 - (int) p7 = 1 - > c - > v - (int) p1 = 1 - (int) p2 = 3 - (int) p3 = 5 - (int) p4 = 3 - (int) p5 = 10 - (int) p6 = 1 - (int) p7 = 1 - > c - > v - (int) p1 = 4 - (int) p2 = 3 - (int) p3 = 3 - (int) p4 = 0 - (int) p5 = 3 - (int) p6 = 0 - (int) p7 = 1 - > c - > v - (int) p1 = 4 - (int) p2 = 3 - (int) p3 = 3 - (int) p4 = 0 - (int) p5 = 3 - (int) p6 = 0 - (int) p7 = 1 - > q - """) - - @Test - fun `inline lambda anonymous argument is visible`() = lldbTest(""" - fun main() { - val list = listOf(1) - list.filter { - it > 2 - } - - list.map { - it * 2 - } - - list.find { - it == 1 - } - } - """, """ - > b main.kt:4 - > b main.kt:8 - > b main.kt:12 - > ${lldbCommandRunOrContinue()} - > v - (int) it = 1 - > c - > v - (int) it = 1 - > c - > v - (int) it = 1 - > q - """) - - @Test - fun `inline function arguments of various types are visible`() = lldbTest(""" - class A - object B - data class C(val x: Int) - interface I - - inline fun foo(a: A, b: B, c: C, i: I, f: (A, B, C, I) -> Unit) { - println() - f(a, b, c, i) - } - - fun main() { - val a = A() - val b = B - val c = C(0) - val i = object : I {} - foo(a, b, c, i) { pa, pb, pc, pi -> - println(pa) - println(pb) - println(pc) - println(pi) - } - - foo(A(), B, C(0), object : I {}) { pa, pb, pc, pi -> - println(pa) - println(pb) - println(pc) - println(pi) - } - } - """, """ - > b main.kt:7 - > b main.kt:17 - > b main.kt:24 - > ${lldbCommandRunOrContinue()} - > v - (ObjHeader *) a = [] - (ObjHeader *) b = [] - (ObjHeader *) c = [x: ...] - (ObjHeader *) i = [] - > c - > v - (ObjHeader *) pa = [] - (ObjHeader *) pb = [] - (ObjHeader *) pc = [x: ...] - (ObjHeader *) pi = [] - > c - > v - (ObjHeader *) a = [] - (ObjHeader *) b = [] - (ObjHeader *) c = [x: ...] - (ObjHeader *) i = [] - > c - > v - (ObjHeader *) pa = [] - (ObjHeader *) pb = [] - (ObjHeader *) pc = [x: ...] - (ObjHeader *) pi = [] - > q - """) - - @Test - fun `inline function default parameters are visible`() = lldbTest(""" - inline fun foo(x: Int = 0, y: String = "STRING", z: Any? = null) { - println(x) - println(y) - println(z) - } - - fun main() { - foo() - foo(1) - foo(1, "TEST_STRING") - foo(1, "TEST_STRING", Any()) - } - """, """ - > b main.kt:2 - > ${lldbCommandRunOrContinue()} - > v - (int) x = 0 - (ObjHeader *) y = STRING - (ObjHeader *) z = NULL - > c - > v - (int) x = 1 - (ObjHeader *) y = STRING - (ObjHeader *) z = NULL - > c - > v - (int) x = 1 - (ObjHeader *) y = TEST_STRING - (ObjHeader *) z = NULL - > c - > v - (int) x = 1 - (ObjHeader *) y = TEST_STRING - (ObjHeader *) z = [] - > q - """) - - @Test - fun `inline function extension receiver is visible`() = lldbTest(""" - class A { - inline fun String.foo(f: String.() -> Unit) { - println() - f() - } - - fun bar() { - "TEST".foo { - println() - } - } - } - - fun main() { - A().bar() - } - """, """ - > b main.kt:3 - > b main.kt:9 - > ${lldbCommandRunOrContinue()} - > v - (ObjHeader *) _this = [] - (ObjHeader *) __this = TEST - > c - > v - (ObjHeader *) ${"$"}this${"$"}foo = TEST - > q - """) -} diff --git a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/Matchers.kt b/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/Matchers.kt deleted file mode 100644 index c5f8c81efcc..00000000000 --- a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/Matchers.kt +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the LICENSE file. - */ - -package org.jetbrains.kotlin.native.test.debugger - -import org.intellij.lang.annotations.Language -import org.junit.Assert.fail -import java.nio.file.Files -import java.nio.file.Path - -/** - * An integration test for debug info. - * - * It works by compiling a given [programText] with debug info, - * then launching lldb, feeding it commands from [lldbSession] - * and matching the output. - * - * [lldbSession] specifies both lldb commands and expected output - * using a DLS, which looks like this: - * - * > b main.kt:5 - * Breakpoint 1: [..] - * > r - * Process [..] stopped - * [..] at main.kt:5, [..] stop reason = breakpoint [..] - * > fr var - * (int) a = 92 - * (int) b = 2 - * - * It consists of blocks of the form - * - * > lldb command - * response line pattern - * another pattern - * - * Command after `>` is passed to lldb exactly. The output of the command - * is then matched against a set of patterns. Matching is done line by line: - * for every pattern, there must be a matching line in the output, but you don't - * have to specify a pattern for every line. In particular, it's possible not to - * specify any patterns at all: - * - * > b main.kt:2 - * > r - * > n - * [..] at main.kt:3, [..] stop reason = step over - * - * The patterns themselves are simple. The only special symbol is `[..]` which - * means arbitrary substring, which can help match random data, timings, and OS-dependent output. - * For example, to match - * - * Current executable set to '/tmp/debugger_test7458723719928260513/program.kexe' (x86_64). - * - * one writes - * - * Current executable set to [..]program.kexe[..] - */ -fun lldbTest(@Language("kotlin") programText: String, lldbSession: String) { - lldbReasonToAbort()?.let { - println(it) - return - } - - val lldbSessionSpec = LldbSessionSpecification.parse(lldbSession) - - val tmpdir = Files.createTempDirectory("debugger_test") - tmpdir.toFile().deleteOnExit() - val source = tmpdir.resolve("main.kt") - val output = tmpdir.resolve("program.kexe") - - val driver = ToolDriver() - Files.write(source, programText.trimIndent().toByteArray()) - driver.compile(source, output, "-g") - val result = driver.runLldb(output, lldbSessionSpec.commands) - lldbSessionSpec.match(result) -} - -fun lldbReasonToAbort() = when { - !haveLldb -> - "Skipping test: no LLDB" - !targetIsHost() && !simulatorTestEnabled() -> - "simulator tests disabled, check 'kotlin.native.test.debugger.simulator.enabled' property" - !isOsxDevToolsEnabled -> - """Development tools aren't available. - |Please consider to execute: - | ${DistProperties.devToolsSecurity} -enable - |or - | csrutil disable - |to run lldb tests""".trimMargin() - else -> null -} - -/** - * Another integration test for debug info. - * - * It works by compiling a given set of [src] files with debug info, then - * launching lldb, running to the given [breakpoint] and "step in" [steps] times. - * It then checks that none of the reached break points correspond to blank - * lines in the given source files. - */ -fun lldbCheckLineNumbers(src: Map, breakpoint: String, steps: Int) { - lldbReasonToAbort()?.let { - println(it) - return - } - - val tmpdir = Files.createTempDirectory("debugger_test") - tmpdir.toFile().deleteOnExit() - - val source = src.map { (filename, content) -> - val path = tmpdir.resolve(filename) - Files.write(path, content.trimIndent().toByteArray()) - path - }.toTypedArray() - - val output = tmpdir.resolve("program.kexe") - val driver = ToolDriver() - driver.compile(output, source, "-g") - - val commands = listOf("b ${breakpoint}", "r") + (1..steps).map { "s" } + listOf("q") - val result = driver.runLldb(output, commands) - - val noCodeLine = Regex("^\\s*(//.*)?$") - val validSourceBreaks = src.flatMap { (filename, content) -> - content.lines().withIndex() - .filterNot { noCodeLine.matches(it.value) } - .map{ "$filename:${it.index}"} - }.toSet() - - Regex("(${src.keys.joinToString("|")}):\\d+").findAll(result).forEach { - check(it.value in validSourceBreaks, { "${it.value} is not a meaningful debug stop" }) - } -} - - -private val isOsxDevToolsEnabled: Boolean by lazy { - //TODO: add OSX checks. - val rawStatus = subprocess(DistProperties.devToolsSecurity, "-status") - println("> status: $rawStatus") - - val r = Regex("^.*\\ (enabled|disabled).$") - r.find(rawStatus.stdout)?.destructured?.component1() == "enabled" -} - -fun dwarfDumpTest(@Language("kotlin") programText: String, flags: List, test:List.()->Unit) { - if (!haveDwarfDump || !targetIsHost()) { - println("Skipping test") - return - } - - - with(Files.createTempDirectory("dwarfdump_test")) { - toFile().deleteOnExit() - val source = resolve("main.kt") - val output = resolve("program.kexe") - - val driver = ToolDriver() - Files.write(source, programText.trimIndent().toByteArray()) - driver.compile(source, output, "-g", *flags.toTypedArray()) - driver.runDwarfDump(output, processor = test) - } -} - -class ToolDriverHelper(private val driver: ToolDriver, val root:Path) { - fun String.cinterop(pkg:String, output: String):Path { - val def = feedOutput("$output.def") - val lib = root.resolve("$output.klib") - driver.cinterop(def, lib, pkg) - return lib - } - - - fun String.library(output: String, vararg flags:String) = feedOutput("$output.kt").compile(root.resolve("$output.klib"), "-p", "library", *flags) - - fun String.binary(output: String, vararg flags:String)= feedOutput("$output.kt").compile(root.resolve("$output.kexe"), *flags) - - private fun Path.compile(output: Path, vararg flags:String) = output.also{ driver.compile(source = this, it, *flags) } - - fun Path.dwarfDumpLookup(address: Long, parser:List.() -> Unit) = driver.runDwarfDump(this, "-lookup", address.toString(), processor = parser) - fun Path.dwarfDumpLookup(name: String, parser:List.() -> Unit) = driver.runDwarfDump(this, "-find", name, processor = parser) - - - fun String.feedOutput(output: String) = root.resolve(output).also { - Files.write(it, this.trimIndent().toByteArray()) - } - - fun Array.framework(name:String, vararg args:String = emptyArray()):Path = root.resolve("$name.framework").also { - - driver.compile(it, this, "-produce", "framework", *args) - } - - fun Array.binary(name:String, vararg args:String = emptyArray()):Path = root.resolve("$name.kexe").also { - driver.compile(it, this, *args) - } - - fun swiftc(output: String, swiftSrc: Path, vararg args: String) = root.resolve(output).also { - driver.swiftc(it, swiftSrc, *args, "-Xlinker", "-rpath", "-Xlinker", "@executable_path") - } - - fun String.lldb(program:Path) { - val lldbSessionSpec = LldbSessionSpecification.parse(this) - val result = driver.runLldb(program, lldbSessionSpec.commands) - lldbSessionSpec.match(result) - } - -} - -fun dwarfDumpComplexTest(test:ToolDriverHelper.()->Unit) { - if (!haveDwarfDump || !targetIsHost()) { - println("Skipping test") - return - } - - - with(Files.createTempDirectory("dwarfdump_test_complex")) { - toFile().deleteOnExit() - ToolDriverHelper(ToolDriver(), this).test() - } -} - -fun lldbComplexTest(test:ToolDriverHelper.()->Unit) { - if (!haveLldb || !targetIsHost()) { - println("Skipping test") - return - } - - - with(Files.createTempDirectory("lldb_test_complex")) { - toFile().deleteOnExit() - ToolDriverHelper(ToolDriver(), this).test() - } -} - -private class LldbSessionSpecification private constructor( - val commands: List, - val patterns: List> -) { - - fun match(output: String) { - val blocks = output.split("""(?=\(lldb\))""".toRegex()).filterNot(String::isEmpty) - if (targetIsHost()) { - check(blocks[0].startsWith("(lldb) target create")) { "Missing block \"target create\". Got: ${blocks[0]}" } - check(blocks[1].startsWith("(lldb) command script import")) { - "Missing block \"command script import\". Got: ${blocks[0]}" - } - } - val responses = if (targetIsHost()) - blocks.drop(2) - else - blocks.drop(2).dropLast(1) - - val executedCommands = responses.map { it.lines().first() } - val bodies = responses.map { it.lines().drop(1) } - val responsesMatch = executedCommands.size == commands.size - && commands.zip(executedCommands).all { (cmd, h) -> h == "(lldb) $cmd" } - - if (!responsesMatch) { - val message = """ - |Responses do not match commands. - | - |COMMANDS: |$commands (${commands.size}) - |RESPONSES: |$executedCommands (${executedCommands.size}) - | - |FULL SESSION: - |$output - """.trimMargin() - fail(message) - } - - for ((patternBody, command) in patterns.zip(bodies).zip(executedCommands)) { - val (pattern, body) = patternBody - val mismatch = findMismatch(pattern, body) - if (mismatch != null) { - val message = """ - |Wrong LLDB output. - | - |COMMAND: $command - |PATTERN: $mismatch - |OUTPUT: - |${body.joinToString("\n")} - | - |FULL SESSION: - |$output - """.trimMargin() - fail(message) - } - } - } - - private fun findMismatch(patterns: List, actualLines: List): String? { - val indices = mutableListOf() - for (pattern in patterns) { - val idx = actualLines.indexOfFirst { match(pattern, it) } - if (idx == -1) { - return pattern - } - indices += idx - } - check(indices == indices.sorted()) - return null - } - - private fun match(pattern: String, line: String): Boolean { - val chunks = pattern.split("""\s*\[\.\.]\s*""".toRegex()) - .filter { it.isNotBlank() } - .map { it.trim() } - check(chunks.isNotEmpty()) - val trimmedLine = line.trim() - - val indices = chunks.map { trimmedLine.indexOf(it) } - if (indices.any { it == -1 } || indices != indices.sorted()) return false - if (!(trimmedLine.startsWith(chunks.first()) || pattern.startsWith("[..]"))) return false - if (!(trimmedLine.endsWith(chunks.last()) || pattern.endsWith("[..]"))) return false - return true - } - - companion object { - fun parse(spec: String): LldbSessionSpecification { - val blocks = spec.trimIndent() - .split("(?=^>)".toRegex(RegexOption.MULTILINE)) - .filterNot(String::isEmpty) - for (cmd in blocks) { - check(cmd.startsWith(">")) { "Invalid lldb session specification: $cmd" } - } - val commands = blocks.map { it.lines().first().substring(1).trim() } - val patterns = blocks.map { it.lines().drop(1).filter { it.isNotBlank() } } - return LldbSessionSpecification(commands, patterns) - } - } -} diff --git a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/Utils.kt b/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/Utils.kt deleted file mode 100644 index d0cb6dff0c4..00000000000 --- a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/Utils.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.native.test.debugger - -import java.io.IOException - -internal fun targetIsHost() = System.getProperty("kotlin.native.host") == System.getProperty("kotlin.native.test.target") - -internal fun simulatorTestEnabled() = System.getProperty("kotlin.native.test.debugger.simulator.enabled")?.toBoolean() ?: false - -internal fun simulatorDelay() = System.getProperty("kotlin.native.test.debugger.simulator.delay")?.toLongOrNull() ?: 300 - -internal fun target() = System.getProperty("kotlin.native.test.target") - -internal val haveDwarfDump: Boolean by lazy { - val version = try { - subprocess(DistProperties.dwarfDump, "--version") - .takeIf { it.process.exitValue() == 0 } - ?.stdout - } catch (e: IOException) { - null - } - - if (version == null) { - println("No LLDB found") - } else { - println("Using $version") - } - - version != null -} - -internal val haveLldb: Boolean by lazy { - val lldbVersion = try { - subprocess(DistProperties.lldb, "-version") - .takeIf { it.process.exitValue() == 0 } - ?.stdout - } catch (e: IOException) { - null - } - - if (lldbVersion == null) { - println("No LLDB found") - } else { - println("Using $lldbVersion") - } - - lldbVersion != null -} - -internal fun lldbCommandRunOrContinue() = if (targetIsHost()) "r" else "c" \ No newline at end of file