Files
swift-mirror/test/Macros/macro_plugin_server.swift
Rintaro Ishizaki a0b9b54944 [Macros] Send termination signal to macro plugin
When shutting down, the plugin, we send SIGTERM, then wait(2) on it. But
we observed some cases the compiler waits for the plugin process exit
for long time.

To resolve that, send an empty message to the plugin and let them exit
itself.

rdar://160820381
2025-10-10 15:13:13 -07:00

119 lines
7.7 KiB
Swift

// REQUIRES: swift_swift_parser
// REQUIRES: swift_feature_Macros
// RUN: %empty-directory(%t)
// RUN: %empty-directory(%t/plugins)
//
//== Build the plugin library
// RUN: %host-build-swift \
// RUN: -swift-version 5 \
// RUN: -emit-library \
// RUN: -o %t/plugins/%target-library-name(MacroDefinition) \
// RUN: -module-name=MacroDefinition \
// RUN: %S/Inputs/syntax_macro_definitions.swift \
// RUN: -g -no-toolchain-stdlib-rpath
// RUN: %host-build-swift \
// RUN: -swift-version 5 \
// RUN: -emit-library \
// RUN: -o %t/plugins/%target-library-name(EvilMacros) \
// RUN: -module-name=EvilMacros \
// RUN: %S/Inputs/evil_macro_definitions.swift \
// RUN: -g -no-toolchain-stdlib-rpath
// RUN: env SWIFT_DUMP_PLUGIN_MESSAGING=1 %target-swift-frontend \
// RUN: -typecheck -verify \
// RUN: -swift-version 5 -enable-experimental-feature Macros \
// RUN: -external-plugin-path %t/plugins#%swift-plugin-server \
// RUN: -Rmacro-loading -verify-ignore-unknown \
// RUN: -module-name MyApp \
// RUN: %s \
// RUN: 2>&1 | tee %t/macro-expansions.txt
// RUN: %FileCheck -strict-whitespace %s < %t/macro-expansions.txt
/// Create file with matching name in alt directories and test
/// `-load-resolved-plugin` takes the priority over other options.
// RUN: %empty-directory(%t/alt)
// RUN: touch %t/alt/%target-library-name(MacroDefinition)
// RUN: env SWIFT_DUMP_PLUGIN_MESSAGING=1 %target-swift-frontend \
// RUN: -typecheck -verify \
// RUN: -swift-version 5 -enable-experimental-feature Macros \
// RUN: -external-plugin-path %t/alt#%swift-plugin-server \
// RUN: -load-resolved-plugin lib-do-not-exist.dylib##MacroDefinition \
// RUN: -load-resolved-plugin %t/plugins/%target-library-name(MacroDefinition)#%swift-plugin-server#MacroDefinition \
// RUN: -load-resolved-plugin %t/plugins/%target-library-name(EvilMacros)#%swift-plugin-server#EvilMacros \
// RUN: -external-plugin-path %t/alt#%swift-plugin-server \
// RUN: -Rmacro-loading -verify-ignore-unknown \
// RUN: -module-name MyApp \
// RUN: %s \
// RUN: 2>&1 | tee %t/macro-expansions-2.txt
// RUN: %FileCheck -strict-whitespace %s < %t/macro-expansions-2.txt
// RUN: not %target-swift-frontend \
// RUN: -typecheck \
// RUN: -swift-version 5 \
// RUN: -external-plugin-path %t/plugins#%swift-plugin-server \
// RUN: -Rmacro-loading \
// RUN: -module-name MyApp \
// RUN: %s \
// RUN: 2>&1 | tee %t/macro-loading.txt
// RUN: %FileCheck -check-prefix=CHECK-DIAGS %s < %t/macro-loading.txt
// CHECK-DIAGS: loaded macro implementation module 'MacroDefinition' from compiler plugin server
// CHECK: ->(plugin:[[#PID1:]]) {"getCapability":{"capability":{"protocolVersion":[[#PROTOCOL_VERSION:]]}}}
// CHECK-NEXT: <-(plugin:[[#PID1]]) {"getCapabilityResult":{"capability":{"features":["load-plugin-library"],"protocolVersion":[[#PROTOCOL_VERSION]]}}}
// CHECK-NEXT: ->(plugin:[[#PID1]]) {"loadPluginLibrary":{"libraryPath":"{{.*}}MacroDefinition.{{dylib|so|dll}}","moduleName":"MacroDefinition"}}
// CHECK-NEXT: <-(plugin:[[#PID1]]) {"loadPluginLibraryResult":{"diagnostics":[],"loaded":true}}
// CHECK-NEXT: ->(plugin:[[#PID1]]) {"loadPluginLibrary":{"libraryPath":"{{.*}}EvilMacros.{{dylib|so|dll}}","moduleName":"EvilMacros"}}
// CHECK-NEXT: <-(plugin:[[#PID1]]) {"loadPluginLibraryResult":{"diagnostics":[],"loaded":true}}
// CHECK-NEXT: ->(plugin:[[#PID1]]) {"expandFreestandingMacro":{"discriminator":"${{.*}}","lexicalContext":[{{.*}}],"macro":{"moduleName":"MacroDefinition","name":"stringify","typeName":"StringifyMacro"},"macroRole":"expression","staticBuildConfiguration"{{.*}},"syntax":{"kind":"expression","location":{{{.+}}},"source":"#stringify(a + b)"}}}
// CHECK-NEXT: <-(plugin:[[#PID1]]) {"expandMacroResult":{"diagnostics":[],"expandedSource":"(a + b, \"a + b\")"}}
// CHECK-NEXT: ->(plugin:[[#PID1]]) {"expandFreestandingMacro":{"discriminator":"${{.*}}","lexicalContext":[{{.*}}],"macro":{"moduleName":"EvilMacros","name":"evil","typeName":"CrashingMacro"},"macroRole":"expression","staticBuildConfiguration"{{.*}},"syntax":{"kind":"expression","location":{{{.+}}},"source":"#evil(42)"}}}
// CHECK-NOT: ->(plugin:[[#PID1]]) {{$}}
// ^ This crashes the plugin server.
// CHECK: ->(plugin:[[#PID2:]]) {"getCapability":{"capability":{"protocolVersion":[[#PROTOCOL_VERSION]]}}}
// CHECK-NEXT: <-(plugin:[[#PID2]]) {"getCapabilityResult":{"capability":{"features":["load-plugin-library"],"protocolVersion":[[#PROTOCOL_VERSION]]}}}
// CHECK-NEXT: ->(plugin:[[#PID2]]) {"loadPluginLibrary":{"libraryPath":"{{.*}}MacroDefinition.{{dylib|so|dll}}","moduleName":"MacroDefinition"}}
// CHECK-NEXT: <-(plugin:[[#PID2]]) {"loadPluginLibraryResult":{"diagnostics":[],"loaded":true}}
// CHECK-NEXT: ->(plugin:[[#PID2]]) {"loadPluginLibrary":{"libraryPath":"{{.*}}EvilMacros.{{dylib|so|dll}}","moduleName":"EvilMacros"}}
// CHECK-NEXT: <-(plugin:[[#PID2]]) {"loadPluginLibraryResult":{"diagnostics":[],"loaded":true}}
// CHECK-NEXT: ->(plugin:[[#PID2]]) {"expandFreestandingMacro":{"discriminator":"${{.*}}","lexicalContext":[{{.*}}],"macro":{"moduleName":"MacroDefinition","name":"stringify","typeName":"StringifyMacro"},"macroRole":"expression","staticBuildConfiguration"{{.*}},"syntax":{"kind":"expression","location":{{{.+}}},"source":"#stringify(b + a)"}}}
// CHECK-NEXT: <-(plugin:[[#PID2]]) {"expandMacroResult":{"diagnostics":[],"expandedSource":"(b + a, \"b + a\")"}}
// CHECK-NEXT: ->(plugin:[[#PID2]]) {"expandFreestandingMacro":{"discriminator":"${{.*}}","lexicalContext":[{{.*}}],"macro":{"moduleName":"MacroDefinition","name":"missing","typeName":"TypeDoesNotExist"},"macroRole":"expression","staticBuildConfiguration"{{.*}},"syntax":{"kind":"expression","location":{{({.+})}},"source":"#missing()"}}}
// CHECK-NEXT: <-(plugin:[[#PID2]]) {"expandMacroResult":{"diagnostics":[{"fixIts":[],"highlights":[{{{.*}}}],"message":"type 'MacroDefinition.TypeDoesNotExist' could not be found in library plugin '{{.*}}MacroDefinition.{{dylib|so|dll}}'","notes":[],"position":{{{.*}}},"severity":"error"}]}}
// CHECK-NEXT: ->(plugin:[[#PID2]]) {"expandFreestandingMacro":{"discriminator":"${{.*}}","lexicalContext":[{{.*}}],"macro":{"moduleName":"MacroDefinition","name":"notMacro","typeName":"NotMacroStruct"},"macroRole":"expression","staticBuildConfiguration"{{.*}},"syntax":{"kind":"expression","location":{{({.+})}},"source":"#notMacro()"}}}
// CHECK-NEXT: <-(plugin:[[#PID2]]) {"expandMacroResult":{"diagnostics":[{"fixIts":[],"highlights":[{{{.*}}}],"message":"type 'MacroDefinition.NotMacroStruct' is not a valid macro implementation type in library plugin '{{.*}}MacroDefinition.{{dylib|so|dll}}'","notes":[],"position":{{{.*}}},"severity":"error"}]}}
// CHECK-NEXT: ->(plugin:[[#PID2]]) {{$}}
@freestanding(expression) macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "MacroDefinition", type: "StringifyMacro")
@freestanding(expression) macro evil(_ value: Int) -> String = #externalMacro(module: "EvilMacros", type: "CrashingMacro")
// FIXME: Diagnose for missing type.
@freestanding(expression) macro missing() = #externalMacro(module: "MacroDefinition", type: "TypeDoesNotExist")
// FIXME: Diagnose for non-macro type.
@freestanding(expression) macro notMacro() = #externalMacro(module: "MacroDefinition", type: "NotMacroStruct")
func testStringify(a: Int, b: Int) {
let s1: String = #stringify(a + b).1
print(s1)
// expected-error @+1 {{failed to receive result from plugin (from macro 'evil')}}
let s2: String = #evil(42)
print(s2)
let s3: String = #stringify(b + a).1
print(s3)
// expected-error @+1 {{type 'MacroDefinition.TypeDoesNotExist' could not be found in library plugin '}}
_ = #missing()
// expected-error @+1 {{type 'MacroDefinition.NotMacroStruct' is not a valid macro implementation type in library plugin '}}
_ = #notMacro()
}