|  | 
|  | 1 | +//===----------------------------------------------------------------------===// | 
|  | 2 | +// | 
|  | 3 | +// This source file is part of the SwiftAWSLambdaRuntime open source project | 
|  | 4 | +// | 
|  | 5 | +// Copyright (c) 2025 Apple Inc. and the SwiftAWSLambdaRuntime project authors | 
|  | 6 | +// Licensed under Apache License v2.0 | 
|  | 7 | +// | 
|  | 8 | +// See LICENSE.txt for license information | 
|  | 9 | +// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors | 
|  | 10 | +// | 
|  | 11 | +// SPDX-License-Identifier: Apache-2.0 | 
|  | 12 | +// | 
|  | 13 | +//===----------------------------------------------------------------------===// | 
|  | 14 | + | 
|  | 15 | +import Logging | 
|  | 16 | +import NIOCore | 
|  | 17 | +import NIOPosix | 
|  | 18 | +import Testing | 
|  | 19 | + | 
|  | 20 | +@testable import AWSLambdaRuntime | 
|  | 21 | + | 
|  | 22 | +extension LambdaRuntimeTests { | 
|  | 23 | + | 
|  | 24 | +    @Test("Local server respects LOCAL_LAMBDA_PORT environment variable") | 
|  | 25 | +    func testLocalServerCustomPort() async throws { | 
|  | 26 | +        let customPort = 8080 | 
|  | 27 | + | 
|  | 28 | +        // Set environment variable | 
|  | 29 | +        setenv("LOCAL_LAMBDA_PORT", "\(customPort)", 1) | 
|  | 30 | +        defer { unsetenv("LOCAL_LAMBDA_PORT") } | 
|  | 31 | + | 
|  | 32 | +        let result = try? await withThrowingTaskGroup(of: Bool.self) { group in | 
|  | 33 | + | 
|  | 34 | +            // start a local lambda + local server on custom port | 
|  | 35 | +            group.addTask { | 
|  | 36 | +                // Create a simple handler | 
|  | 37 | +                struct TestHandler: StreamingLambdaHandler { | 
|  | 38 | +                    func handle( | 
|  | 39 | +                        _ event: ByteBuffer, | 
|  | 40 | +                        responseWriter: some LambdaResponseStreamWriter, | 
|  | 41 | +                        context: LambdaContext | 
|  | 42 | +                    ) async throws { | 
|  | 43 | +                        try await responseWriter.write(ByteBuffer(string: "test")) | 
|  | 44 | +                        try await responseWriter.finish() | 
|  | 45 | +                    } | 
|  | 46 | +                } | 
|  | 47 | + | 
|  | 48 | +                // create the Lambda Runtime | 
|  | 49 | +                let runtime = LambdaRuntime( | 
|  | 50 | +                    handler: TestHandler(), | 
|  | 51 | +                    logger: Logger(label: "test", factory: { _ in SwiftLogNoOpLogHandler() }) | 
|  | 52 | +                ) | 
|  | 53 | + | 
|  | 54 | +                // Start runtime | 
|  | 55 | +                try await runtime._run() | 
|  | 56 | + | 
|  | 57 | +                // we reach this line when the group is cancelled | 
|  | 58 | +                return false | 
|  | 59 | +            } | 
|  | 60 | + | 
|  | 61 | +            // start a client to check if something responds on the custom port | 
|  | 62 | +            group.addTask { | 
|  | 63 | +                // Give server time to start | 
|  | 64 | +                try await Task.sleep(for: .milliseconds(100)) | 
|  | 65 | + | 
|  | 66 | +                // Verify server is listening on custom port | 
|  | 67 | +                return try await isPortResponding(host: "127.0.0.1", port: customPort) | 
|  | 68 | +            } | 
|  | 69 | + | 
|  | 70 | +            let first = try await group.next() | 
|  | 71 | +            group.cancelAll() | 
|  | 72 | +            return first ?? false | 
|  | 73 | + | 
|  | 74 | +        } | 
|  | 75 | + | 
|  | 76 | +        #expect(result == true) | 
|  | 77 | +    } | 
|  | 78 | + | 
|  | 79 | +    private func isPortResponding(host: String, port: Int) async throws -> Bool { | 
|  | 80 | +        let group = MultiThreadedEventLoopGroup(numberOfThreads: 1) | 
|  | 81 | + | 
|  | 82 | +        let bootstrap = ClientBootstrap(group: group) | 
|  | 83 | + | 
|  | 84 | +        do { | 
|  | 85 | +            let channel = try await bootstrap.connect(host: host, port: port).get() | 
|  | 86 | +            try await channel.close().get() | 
|  | 87 | +            try await group.shutdownGracefully() | 
|  | 88 | +            return true | 
|  | 89 | +        } catch { | 
|  | 90 | +            try await group.shutdownGracefully() | 
|  | 91 | +            return false | 
|  | 92 | +        } | 
|  | 93 | +    } | 
|  | 94 | +} | 
0 commit comments