From 4f9a257b10c42e73f55f0808184bc4bf813e1438 Mon Sep 17 00:00:00 2001 From: Mahdi Bahrami Date: Tue, 30 Jan 2024 10:42:40 +0330 Subject: [PATCH] Compatibility for building all targets together in release mode + Use `package` instead of `public` (#164) * use 'package' instead of 'public' * move 'Fake' into 'PennyTests' * remove 'package' attributes in 'Fake' folder * remove import Fake s --- Lambdas/AutoFaqs/S3AutoFaqsRepository.swift | 12 ++--- Lambdas/AutoPings/S3AutoPingsRepository.swift | 12 ++--- Lambdas/Faqs/S3FaqsRepository.swift | 12 ++--- Lambdas/GHOAuth/Models/GHOAuthPayload.swift | 12 ++--- Lambdas/LambdasShared/+APIGatewayV2.swift | 14 +++--- Lambdas/LambdasShared/SecretsRetriever.swift | 6 +-- Lambdas/LambdasShared/Utilities.swift | 6 +-- Lambdas/Sponsors/GithubWebhookPayload.swift | 2 +- Lambdas/Sponsors/SponsorType.swift | 2 +- Lambdas/Users/InternalUsersService.swift | 14 +++--- Package.swift | 27 ---------- Sources/Models/AccountLinkRequest.swift | 4 +- Sources/Models/AutoFaqsRequest.swift | 2 +- Sources/Models/AutoPingsRequest.swift | 8 +-- Sources/Models/CoinEntry.swift | 22 ++++----- Sources/Models/CoinResponse.swift | 10 ++-- Sources/Models/DynamoDBUser.swift | 18 +++---- Sources/Models/FaqsRequest.swift | 2 +- Sources/Models/GitHubIDResponse.swift | 2 +- Sources/Models/S3AutoPingItems.swift | 24 ++++----- Sources/Models/UserRequest.swift | 16 +++--- Sources/Penny/BotStateManager.swift | 2 - .../DiscordService/DiscordService.swift | 10 ---- Sources/Rendering/+LeafRenderer.swift | 2 +- Sources/Rendering/RenderClient.swift | 8 +-- Sources/Shared/+String.swift | 6 +-- Sources/Shared/SerialProcessor.swift | 6 +-- Sources/Shared/ServiceFactory.swift | 4 +- .../UsersService/GitHubUserResponse.swift | 2 +- .../Shared/UsersService/UsersService.swift | 2 +- Tests/Fake/AnyBox.swift | 9 ---- Tests/Fake/FakeAutoFaqsService.swift | 49 ------------------- Tests/Fake/FakeFaqsService.swift | 26 ---------- Tests/Fake/FakeMessageLookupRepo.swift | 17 ------- Tests/Fake/FakeProposalsService.swift | 15 ------ Tests/Fake/FakeUsersService.swift | 35 ------------- Tests/{ => PennyTests}/Fake/+Endpoint.swift | 0 Tests/PennyTests/Fake/AnyBox.swift | 9 ++++ Tests/{ => PennyTests}/Fake/EventKey.swift | 4 +- .../PennyTests/Fake/FakeAutoFaqsService.swift | 49 +++++++++++++++++++ .../Fake/FakeCacheService.swift | 8 +-- .../Fake/FakeClientTransport.swift | 6 +-- .../Fake/FakeDiscordClient.swift | 12 ++--- Tests/PennyTests/Fake/FakeFaqsService.swift | 26 ++++++++++ .../Fake/FakeMainService.swift | 24 ++++----- Tests/{ => PennyTests}/Fake/FakeManager.swift | 32 ++++++------ .../Fake/FakeMessageLookupRepo.swift | 17 +++++++ .../Fake/FakePingsService.swift | 16 +++--- .../Fake/FakeProposalsService.swift | 15 ++++++ .../Fake/FakeResponseStorage.swift | 10 ++-- .../{ => PennyTests}/Fake/FakeSOService.swift | 0 Tests/PennyTests/Fake/FakeUsersService.swift | 35 +++++++++++++ Tests/{ => PennyTests}/Fake/TestData.swift | 16 +++--- Tests/PennyTests/{ => Tests}/+XCTest.swift | 0 .../{ => Tests}/CoinHandlerTests.swift | 0 .../PennyTests/{ => Tests}/GHHooksTests.swift | 1 - .../{ => Tests}/GatewayProcessingTests.swift | 3 +- .../{ => Tests}/LeafRenderTests.swift | 1 - Tests/PennyTests/{ => Tests}/OtherTests.swift | 1 - 59 files changed, 331 insertions(+), 374 deletions(-) delete mode 100644 Tests/Fake/AnyBox.swift delete mode 100644 Tests/Fake/FakeAutoFaqsService.swift delete mode 100644 Tests/Fake/FakeFaqsService.swift delete mode 100644 Tests/Fake/FakeMessageLookupRepo.swift delete mode 100644 Tests/Fake/FakeProposalsService.swift delete mode 100644 Tests/Fake/FakeUsersService.swift rename Tests/{ => PennyTests}/Fake/+Endpoint.swift (100%) create mode 100644 Tests/PennyTests/Fake/AnyBox.swift rename Tests/{ => PennyTests}/Fake/EventKey.swift (99%) create mode 100644 Tests/PennyTests/Fake/FakeAutoFaqsService.swift rename Tests/{ => PennyTests}/Fake/FakeCacheService.swift (60%) rename Tests/{ => PennyTests}/Fake/FakeClientTransport.swift (88%) rename Tests/{ => PennyTests}/Fake/FakeDiscordClient.swift (84%) create mode 100644 Tests/PennyTests/Fake/FakeFaqsService.swift rename Tests/{ => PennyTests}/Fake/FakeMainService.swift (89%) rename Tests/{ => PennyTests}/Fake/FakeManager.swift (69%) create mode 100644 Tests/PennyTests/Fake/FakeMessageLookupRepo.swift rename Tests/{ => PennyTests}/Fake/FakePingsService.swift (75%) create mode 100644 Tests/PennyTests/Fake/FakeProposalsService.swift rename Tests/{ => PennyTests}/Fake/FakeResponseStorage.swift (97%) rename Tests/{ => PennyTests}/Fake/FakeSOService.swift (100%) create mode 100644 Tests/PennyTests/Fake/FakeUsersService.swift rename Tests/{ => PennyTests}/Fake/TestData.swift (85%) rename Tests/PennyTests/{ => Tests}/+XCTest.swift (100%) rename Tests/PennyTests/{ => Tests}/CoinHandlerTests.swift (100%) rename Tests/PennyTests/{ => Tests}/GHHooksTests.swift (99%) rename Tests/PennyTests/{ => Tests}/GatewayProcessingTests.swift (99%) rename Tests/PennyTests/{ => Tests}/LeafRenderTests.swift (99%) rename Tests/PennyTests/{ => Tests}/OtherTests.swift (99%) diff --git a/Lambdas/AutoFaqs/S3AutoFaqsRepository.swift b/Lambdas/AutoFaqs/S3AutoFaqsRepository.swift index 28cce6ce..f34b3d3a 100644 --- a/Lambdas/AutoFaqs/S3AutoFaqsRepository.swift +++ b/Lambdas/AutoFaqs/S3AutoFaqsRepository.swift @@ -2,7 +2,7 @@ import SotoS3 import Foundation import Models -public struct S3AutoFaqsRepository { +package struct S3AutoFaqsRepository { let s3: S3 let logger: Logger @@ -12,12 +12,12 @@ public struct S3AutoFaqsRepository { let decoder = JSONDecoder() let encoder = JSONEncoder() - public init(awsClient: AWSClient, logger: Logger) { + package init(awsClient: AWSClient, logger: Logger) { self.s3 = S3(client: awsClient, region: .euwest1) self.logger = logger } - public func insert(expression: String, value: String) async throws -> [String: String] { + package func insert(expression: String, value: String) async throws -> [String: String] { var all = try await self.getAll() if all[expression] != value { all[expression] = value @@ -26,7 +26,7 @@ public struct S3AutoFaqsRepository { return all } - public func remove(expression: String) async throws -> [String: String] { + package func remove(expression: String) async throws -> [String: String] { var all = try await self.getAll() if all.removeValue(forKey: expression) != nil { try await self.save(items: all) @@ -34,7 +34,7 @@ public struct S3AutoFaqsRepository { return all } - public func getAll() async throws -> [String: String] { + package func getAll() async throws -> [String: String] { let response: S3.GetObjectOutput do { @@ -61,7 +61,7 @@ public struct S3AutoFaqsRepository { } } - public func save(items: [String: String]) async throws { + package func save(items: [String: String]) async throws { let data = try encoder.encode(items) let putObjectRequest = S3.PutObjectRequest( acl: .private, diff --git a/Lambdas/AutoPings/S3AutoPingsRepository.swift b/Lambdas/AutoPings/S3AutoPingsRepository.swift index 726ab1cf..c4148ad1 100644 --- a/Lambdas/AutoPings/S3AutoPingsRepository.swift +++ b/Lambdas/AutoPings/S3AutoPingsRepository.swift @@ -2,7 +2,7 @@ import SotoS3 import Foundation import Models -public struct S3AutoPingsRepository { +package struct S3AutoPingsRepository { let s3: S3 let logger: Logger @@ -12,12 +12,12 @@ public struct S3AutoPingsRepository { let decoder = JSONDecoder() let encoder = JSONEncoder() - public init(awsClient: AWSClient, logger: Logger) { + package init(awsClient: AWSClient, logger: Logger) { self.s3 = S3(client: awsClient, region: .euwest1) self.logger = logger } - public func insert( + package func insert( expressions: [S3AutoPingItems.Expression], forDiscordID id: UserSnowflake ) async throws -> S3AutoPingItems { @@ -29,7 +29,7 @@ public struct S3AutoPingsRepository { return all } - public func remove( + package func remove( expressions: [S3AutoPingItems.Expression], forDiscordID id: UserSnowflake ) async throws -> S3AutoPingItems { @@ -44,7 +44,7 @@ public struct S3AutoPingsRepository { return all } - public func getAll() async throws -> S3AutoPingItems { + package func getAll() async throws -> S3AutoPingItems { let response: S3.GetObjectOutput do { @@ -71,7 +71,7 @@ public struct S3AutoPingsRepository { } } - public func save(items: S3AutoPingItems) async throws { + package func save(items: S3AutoPingItems) async throws { let data = try encoder.encode(items) let putObjectRequest = S3.PutObjectRequest( acl: .private, diff --git a/Lambdas/Faqs/S3FaqsRepository.swift b/Lambdas/Faqs/S3FaqsRepository.swift index f4aac10d..27c107ee 100644 --- a/Lambdas/Faqs/S3FaqsRepository.swift +++ b/Lambdas/Faqs/S3FaqsRepository.swift @@ -2,7 +2,7 @@ import SotoS3 import Foundation import Models -public struct S3FaqsRepository { +package struct S3FaqsRepository { let s3: S3 let logger: Logger @@ -12,12 +12,12 @@ public struct S3FaqsRepository { let decoder = JSONDecoder() let encoder = JSONEncoder() - public init(awsClient: AWSClient, logger: Logger) { + package init(awsClient: AWSClient, logger: Logger) { self.s3 = S3(client: awsClient, region: .euwest1) self.logger = logger } - public func insert(name: String, value: String) async throws -> [String: String] { + package func insert(name: String, value: String) async throws -> [String: String] { var all = try await self.getAll() if all[name] != value { all[name] = value @@ -26,7 +26,7 @@ public struct S3FaqsRepository { return all } - public func remove(name: String) async throws -> [String: String] { + package func remove(name: String) async throws -> [String: String] { var all = try await self.getAll() if all.removeValue(forKey: name) != nil { try await self.save(items: all) @@ -34,7 +34,7 @@ public struct S3FaqsRepository { return all } - public func getAll() async throws -> [String: String] { + package func getAll() async throws -> [String: String] { let response: S3.GetObjectOutput do { @@ -61,7 +61,7 @@ public struct S3FaqsRepository { } } - public func save(items: [String: String]) async throws { + package func save(items: [String: String]) async throws { let data = try encoder.encode(items) let putObjectRequest = S3.PutObjectRequest( acl: .private, diff --git a/Lambdas/GHOAuth/Models/GHOAuthPayload.swift b/Lambdas/GHOAuth/Models/GHOAuthPayload.swift index de08f637..50c9d813 100644 --- a/Lambdas/GHOAuth/Models/GHOAuthPayload.swift +++ b/Lambdas/GHOAuth/Models/GHOAuthPayload.swift @@ -3,21 +3,21 @@ import JWTKit /// This Payload will get sent along with the OAuth redirect to the GitHub OAuth page, /// specifically inside the `state` query parameter. -public struct GHOAuthPayload: JWTPayload { +package struct GHOAuthPayload: JWTPayload { /// Used to verify the user's identity when they come back from GitHub. - public let discordID: UserSnowflake + package let discordID: UserSnowflake /// The interaction token to respond back to user on Discord with and notify of the result. - public let interactionToken: String + package let interactionToken: String /// Expiration time of the token. - public let expiration: ExpirationClaim + package let expiration: ExpirationClaim - public init(discordID: UserSnowflake, interactionToken: String) { + package init(discordID: UserSnowflake, interactionToken: String) { self.discordID = discordID self.interactionToken = interactionToken self.expiration = .init(value: Date().addingTimeInterval(10 * 60)) // 10 minutes } - public func verify(using signer: JWTSigner) throws { + package func verify(using signer: JWTSigner) throws { try self.expiration.verifyNotExpired() } } diff --git a/Lambdas/LambdasShared/+APIGatewayV2.swift b/Lambdas/LambdasShared/+APIGatewayV2.swift index 3c3269c4..8ba074be 100644 --- a/Lambdas/LambdasShared/+APIGatewayV2.swift +++ b/Lambdas/LambdasShared/+APIGatewayV2.swift @@ -12,7 +12,7 @@ private let jsonEncoder = JSONEncoder() extension APIGatewayV2Request { - public func decode(as type: D.Type = D.self) throws -> D { + package func decode(as type: D.Type = D.self) throws -> D { guard let body = self.body else { throw APIGatewayErrors.emptyBody(self) } @@ -20,7 +20,7 @@ extension APIGatewayV2Request { return try jsonDecoder.decode(D.self, from: data) } - public func decodeWithISO8601(as type: D.Type = D.self) throws -> D { + package func decodeWithISO8601(as type: D.Type = D.self) throws -> D { guard let body = self.body else { throw APIGatewayErrors.emptyBody(self) } @@ -30,7 +30,7 @@ extension APIGatewayV2Request { } extension APIGatewayV2Response { - public init(status: HTTPResponseStatus, content: some Encodable) { + package init(status: HTTPResponseStatus, content: some Encodable) { do { let data = try jsonEncoder.encode(content) let string = String(data: data, encoding: .utf8) @@ -46,18 +46,18 @@ extension APIGatewayV2Response { } } -public struct GatewayFailure: Encodable { +package struct GatewayFailure: Encodable { var reason: String - public init(reason: String) { + package init(reason: String) { self.reason = reason } } -public enum APIGatewayErrors: Error, CustomStringConvertible { +package enum APIGatewayErrors: Error, CustomStringConvertible { case emptyBody(APIGatewayV2Request) - public var description: String { + package var description: String { switch self { case let .emptyBody(request): return "emptyBody(\(request))" diff --git a/Lambdas/LambdasShared/SecretsRetriever.swift b/Lambdas/LambdasShared/SecretsRetriever.swift index c4cd41bc..90f9273c 100644 --- a/Lambdas/LambdasShared/SecretsRetriever.swift +++ b/Lambdas/LambdasShared/SecretsRetriever.swift @@ -4,7 +4,7 @@ import Logging import Shared import Foundation -public actor SecretsRetriever { +package actor SecretsRetriever { enum Errors: Error, CustomStringConvertible { case secretNotFound(arn: String) @@ -24,12 +24,12 @@ public actor SecretsRetriever { private let queue = SerialProcessor() - public init(awsClient: AWSClient, logger: Logger) { + package init(awsClient: AWSClient, logger: Logger) { self.secretsManager = SecretsManager(client: awsClient) self.logger = logger } - public func getSecret(arnEnvVarKey: String) async throws -> String { + package func getSecret(arnEnvVarKey: String) async throws -> String { logger.trace("Get secret start", metadata: [ "arnEnvVarKey": .string(arnEnvVarKey) ]) diff --git a/Lambdas/LambdasShared/Utilities.swift b/Lambdas/LambdasShared/Utilities.swift index 6aa09f41..9e7b6e5d 100644 --- a/Lambdas/LambdasShared/Utilities.swift +++ b/Lambdas/LambdasShared/Utilities.swift @@ -1,14 +1,14 @@ import Foundation -public struct NoEnvVarError: Error, CustomStringConvertible { +package struct NoEnvVarError: Error, CustomStringConvertible { let key: String - public var description: String { + package var description: String { "NoEnvVarError(key.debugDescription: \(key.debugDescription))" } } -public func requireEnvVar(_ key: String) throws -> String { +package func requireEnvVar(_ key: String) throws -> String { if let value = ProcessInfo.processInfo.environment[key] { return value } else { diff --git a/Lambdas/Sponsors/GithubWebhookPayload.swift b/Lambdas/Sponsors/GithubWebhookPayload.swift index 680e5a87..4ba68ea7 100644 --- a/Lambdas/Sponsors/GithubWebhookPayload.swift +++ b/Lambdas/Sponsors/GithubWebhookPayload.swift @@ -1,6 +1,6 @@ import Foundation -public struct GitHubWebhookPayload: Codable { +package struct GitHubWebhookPayload: Codable { let action: String let sponsorship: Sponsorship let sender: Sender diff --git a/Lambdas/Sponsors/SponsorType.swift b/Lambdas/Sponsors/SponsorType.swift index 9890b531..52def7af 100644 --- a/Lambdas/Sponsors/SponsorType.swift +++ b/Lambdas/Sponsors/SponsorType.swift @@ -26,7 +26,7 @@ enum SponsorType: String { } } - public static func `for`(sponsorshipAmount: Int) throws -> SponsorType { + package static func `for`(sponsorshipAmount: Int) throws -> SponsorType { switch sponsorshipAmount { case 500...9900: return .backer case 10000...: return .sponsor diff --git a/Lambdas/Users/InternalUsersService.swift b/Lambdas/Users/InternalUsersService.swift index 1e733381..1eb2d55d 100644 --- a/Lambdas/Users/InternalUsersService.swift +++ b/Lambdas/Users/InternalUsersService.swift @@ -2,12 +2,12 @@ import SotoDynamoDB import Foundation import Models -public struct InternalUsersService { +package struct InternalUsersService { private let userRepo: DynamoUserRepository private let coinEntryRepo: DynamoCoinEntryRepository let logger: Logger - public init(awsClient: AWSClient, logger: Logger) { + package init(awsClient: AWSClient, logger: Logger) { let euWest = Region(awsRegionName: "eu-west-1") let dynamoDB = DynamoDB(client: awsClient, region: euWest) self.userRepo = DynamoUserRepository( @@ -22,7 +22,7 @@ public struct InternalUsersService { } /// `freshUser` must be a fresh user you just got from the db. - public func addCoinEntry( + package func addCoinEntry( _ coinEntry: CoinEntry, freshUser user: DynamoDBUser ) async throws -> DynamoDBUser { @@ -40,7 +40,7 @@ public struct InternalUsersService { try await userRepo.getUser(discordID: discordID) } - public func getOrCreateUser(discordID: UserSnowflake) async throws -> DynamoDBUser { + package func getOrCreateUser(discordID: UserSnowflake) async throws -> DynamoDBUser { if let existing = try await self.getUser(discordID: discordID) { return existing } else { @@ -51,18 +51,18 @@ public struct InternalUsersService { } /// Returns nil if user does not exist. - public func getUser(githubID: String) async throws -> DynamoDBUser? { + package func getUser(githubID: String) async throws -> DynamoDBUser? { try await userRepo.getUser(githubID: githubID) } - public func linkGithubID(discordID: UserSnowflake, githubID: String) async throws { + package func linkGithubID(discordID: UserSnowflake, githubID: String) async throws { var user = try await self.getOrCreateUser(discordID: discordID) user.githubID = githubID try await userRepo.updateUser(user) } - public func unlinkGithubID(discordID: UserSnowflake) async throws { + package func unlinkGithubID(discordID: UserSnowflake) async throws { var user = try await self.getOrCreateUser(discordID: discordID) user.githubID = nil diff --git a/Package.swift b/Package.swift index 3bb994db..d6d53cc1 100644 --- a/Package.swift +++ b/Package.swift @@ -258,32 +258,6 @@ let package = Package( ], swiftSettings: targetsSwiftSettings ), - .target( - name: "Fake", - dependencies: [ - .product(name: "SotoDynamoDB", package: "soto"), - .product(name: "SotoS3", package: "soto"), - .product(name: "SotoCore", package: "soto-core"), - .product(name: "DiscordBM", package: "DiscordBM"), - .product(name: "LeafKit", package: "leaf-kit"), - .product(name: "Markdown", package: "swift-markdown"), - .product(name: "SwiftSemver", package: "swift-semver"), - .product(name: "DiscordLogger", package: "DiscordLogger"), - .product(name: "JWTKit", package: "jwt-kit"), - .product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime"), - .product(name: "AWSLambdaEvents", package: "swift-aws-lambda-events"), - .product(name: "OpenAPIRuntime", package: "swift-openapi-runtime"), - .target(name: "GitHubAPI"), - .target(name: "LambdasShared"), - .target(name: "Shared"), - .target(name: "Rendering"), - .target(name: "Models"), - .target(name: "Penny"), - .target(name: "GHHooksLambda"), - ], - path: "./Tests/Fake", - swiftSettings: testsSwiftSettings - ), .testTarget( name: "PennyTests", dependencies: [ @@ -304,7 +278,6 @@ let package = Package( .target(name: "Models"), .target(name: "Penny"), .target(name: "GHHooksLambda"), - .target(name: "Fake"), ], swiftSettings: testsSwiftSettings ), diff --git a/Sources/Models/AccountLinkRequest.swift b/Sources/Models/AccountLinkRequest.swift index 7504b94f..896a8852 100644 --- a/Sources/Models/AccountLinkRequest.swift +++ b/Sources/Models/AccountLinkRequest.swift @@ -1,6 +1,6 @@ import Foundation -public struct AccountLinkRequest: Codable { +package struct AccountLinkRequest: Codable { let id: UUID let createdAt: Date let initiationSource: String @@ -8,4 +8,4 @@ public struct AccountLinkRequest: Codable { let requestedSource: String let requestedId: String let reference: String -} \ No newline at end of file +} diff --git a/Sources/Models/AutoFaqsRequest.swift b/Sources/Models/AutoFaqsRequest.swift index 0aa614ee..0ea3a23b 100644 --- a/Sources/Models/AutoFaqsRequest.swift +++ b/Sources/Models/AutoFaqsRequest.swift @@ -1,5 +1,5 @@ -public enum AutoFaqsRequest: Codable { +package enum AutoFaqsRequest: Codable { case all case add(expression: String, value: String) case remove(expression: String) diff --git a/Sources/Models/AutoPingsRequest.swift b/Sources/Models/AutoPingsRequest.swift index 39f5ce1f..7262c6f3 100644 --- a/Sources/Models/AutoPingsRequest.swift +++ b/Sources/Models/AutoPingsRequest.swift @@ -1,9 +1,9 @@ -public struct AutoPingsRequest: Codable { - public let discordID: UserSnowflake - public let expressions: [S3AutoPingItems.Expression] +package struct AutoPingsRequest: Codable { + package let discordID: UserSnowflake + package let expressions: [S3AutoPingItems.Expression] - public init( + package init( discordID: UserSnowflake, expressions: [S3AutoPingItems.Expression] ) { diff --git a/Sources/Models/CoinEntry.swift b/Sources/Models/CoinEntry.swift index f3023668..d047b600 100644 --- a/Sources/Models/CoinEntry.swift +++ b/Sources/Models/CoinEntry.swift @@ -4,15 +4,15 @@ import Foundation @preconcurrency import Foundation #endif -public struct CoinEntry: Sendable, Codable { +package struct CoinEntry: Sendable, Codable { - public enum Source: String, Sendable, Codable { + package enum Source: String, Sendable, Codable { case discord case github case penny } - public enum Reason: String, Sendable, Codable { + package enum Reason: String, Sendable, Codable { case userProvided case automationProvided case prSubmittedAndClosed @@ -23,15 +23,15 @@ public struct CoinEntry: Sendable, Codable { case linkedProfile } - public let id: UUID - public let fromUserID: UUID - public let toUserID: UUID - public let createdAt: Date - public let amount: Int - public let source: Source - public let reason: Reason + package let id: UUID + package let fromUserID: UUID + package let toUserID: UUID + package let createdAt: Date + package let amount: Int + package let source: Source + package let reason: Reason - public init( + package init( id: UUID = UUID(), fromUserID: UUID, toUserID: UUID, diff --git a/Sources/Models/CoinResponse.swift b/Sources/Models/CoinResponse.swift index 152b5acf..c02298c7 100644 --- a/Sources/Models/CoinResponse.swift +++ b/Sources/Models/CoinResponse.swift @@ -1,10 +1,10 @@ -public struct CoinResponse: Sendable, Codable { - public let sender: UserSnowflake - public let receiver: UserSnowflake - public let newCoinCount: Int +package struct CoinResponse: Sendable, Codable { + package let sender: UserSnowflake + package let receiver: UserSnowflake + package let newCoinCount: Int - public init(sender: UserSnowflake, receiver: UserSnowflake, newCoinCount: Int) { + package init(sender: UserSnowflake, receiver: UserSnowflake, newCoinCount: Int) { self.sender = sender self.receiver = receiver self.newCoinCount = newCoinCount diff --git a/Sources/Models/DynamoDBUser.swift b/Sources/Models/DynamoDBUser.swift index a7c5311f..577d408d 100644 --- a/Sources/Models/DynamoDBUser.swift +++ b/Sources/Models/DynamoDBUser.swift @@ -4,21 +4,21 @@ import Foundation @preconcurrency import Foundation #endif -public struct DynamoDBUser: Sendable, Codable { - public let id: UUID - public var discordID: UserSnowflake - public var githubID: String? - public var coinCount: Int - public let createdAt: Date +package struct DynamoDBUser: Sendable, Codable { + package let id: UUID + package var discordID: UserSnowflake + package var githubID: String? + package var coinCount: Int + package let createdAt: Date - public enum CodingKeys: String, CodingKey { + package enum CodingKeys: String, CodingKey { case id case discordID case githubID case coinCount case createdAt - public var description: String { + package var description: String { self.rawValue } } @@ -37,7 +37,7 @@ public struct DynamoDBUser: Sendable, Codable { self.createdAt = createdAt } - public static func createNew(forDiscordID discordID: UserSnowflake) -> Self { + package static func createNew(forDiscordID discordID: UserSnowflake) -> Self { DynamoDBUser( id: UUID(), discordID: discordID, diff --git a/Sources/Models/FaqsRequest.swift b/Sources/Models/FaqsRequest.swift index c84737c3..2cbd1dc1 100644 --- a/Sources/Models/FaqsRequest.swift +++ b/Sources/Models/FaqsRequest.swift @@ -1,5 +1,5 @@ -public enum FaqsRequest: Codable { +package enum FaqsRequest: Codable { case all case add(name: String, value: String) case remove(name: String) diff --git a/Sources/Models/GitHubIDResponse.swift b/Sources/Models/GitHubIDResponse.swift index 937e377d..72834e5e 100644 --- a/Sources/Models/GitHubIDResponse.swift +++ b/Sources/Models/GitHubIDResponse.swift @@ -1,4 +1,4 @@ -public enum GitHubIDResponse: Sendable, Codable { +package enum GitHubIDResponse: Sendable, Codable { case notLinked case id(String) } diff --git a/Sources/Models/S3AutoPingItems.swift b/Sources/Models/S3AutoPingItems.swift index 2aaeef97..e630ed10 100644 --- a/Sources/Models/S3AutoPingItems.swift +++ b/Sources/Models/S3AutoPingItems.swift @@ -1,15 +1,15 @@ -public struct S3AutoPingItems: Sendable, Codable { +package struct S3AutoPingItems: Sendable, Codable { - public enum Expression: Sendable, Codable, RawRepresentable, Hashable { + package enum Expression: Sendable, Codable, RawRepresentable, Hashable { - public enum Kind: String, CaseIterable { + package enum Kind: String, CaseIterable { case containment case exactMatch - public static let `default`: Kind = .containment + package static let `default`: Kind = .containment - public var UIDescription: String { + package var UIDescription: String { switch self { case .containment: return "Containment" @@ -18,7 +18,7 @@ public struct S3AutoPingItems: Sendable, Codable { } } - public var priority: Int { + package var priority: Int { switch self { case .containment: return 2 @@ -33,14 +33,14 @@ public struct S3AutoPingItems: Sendable, Codable { /// Exact match (with some insensitivity, such as case-insensitivity) case matches(String) - public var kind: Kind { + package var kind: Kind { switch self { case .contains: return .containment case .matches: return .exactMatch } } - public var innerValue: String { + package var innerValue: String { switch self { case let .contains(contain): return contain @@ -51,7 +51,7 @@ public struct S3AutoPingItems: Sendable, Codable { /// Important for the Codable conformance. /// Changing the implementation might result in breaking the repository. - public var rawValue: String { + package var rawValue: String { switch self { case let .contains(contain): return "C-\(contain)" @@ -62,7 +62,7 @@ public struct S3AutoPingItems: Sendable, Codable { /// Important for the Codable conformance. /// Changing the implementation might result in breaking the repository. - public init? (rawValue: String) { + package init? (rawValue: String) { if rawValue.hasPrefix("C-") { self = .contains(String(rawValue.dropFirst(2))) } else if rawValue.hasPrefix("T-") { @@ -73,9 +73,9 @@ public struct S3AutoPingItems: Sendable, Codable { } } - public var items: [Expression: Set] + package var items: [Expression: Set] - public init(items: [Expression: Set] = [:]) { + package init(items: [Expression: Set] = [:]) { self.items = items } } diff --git a/Sources/Models/UserRequest.swift b/Sources/Models/UserRequest.swift index 07370088..6a16d7da 100644 --- a/Sources/Models/UserRequest.swift +++ b/Sources/Models/UserRequest.swift @@ -1,19 +1,19 @@ -public enum UserRequest: Sendable, Codable { +package enum UserRequest: Sendable, Codable { case addCoin(CoinEntryRequest) case getOrCreateUser(discordID: UserSnowflake) case getUser(githubID: String) case linkGitHubID(discordID: UserSnowflake, toGitHubID: String) case unlinkGitHubID(discordID: UserSnowflake) - public struct CoinEntryRequest: Sendable, Codable { - public let amount: Int - public let fromDiscordID: UserSnowflake - public let toDiscordID: UserSnowflake - public let source: CoinEntry.Source - public let reason: CoinEntry.Reason + package struct CoinEntryRequest: Sendable, Codable { + package let amount: Int + package let fromDiscordID: UserSnowflake + package let toDiscordID: UserSnowflake + package let source: CoinEntry.Source + package let reason: CoinEntry.Reason - public init( + package init( amount: Int, fromDiscordID: UserSnowflake, toDiscordID: UserSnowflake, diff --git a/Sources/Penny/BotStateManager.swift b/Sources/Penny/BotStateManager.swift index beb0dce4..c882e5ce 100644 --- a/Sources/Penny/BotStateManager.swift +++ b/Sources/Penny/BotStateManager.swift @@ -121,11 +121,9 @@ actor BotStateManager { "\(text) \(id)" } -#if DEBUG func _tests_didShutdownSignalEventContent() -> String { makeSignalMessage(text: StateManagerSignal.didShutdown.rawValue, id: self.id - 10) } -#endif } enum StateManagerSignal: String { diff --git a/Sources/Penny/Services/DiscordService/DiscordService.swift b/Sources/Penny/Services/DiscordService/DiscordService.swift index 748f503b..992a422a 100644 --- a/Sources/Penny/Services/DiscordService/DiscordService.swift +++ b/Sources/Penny/Services/DiscordService/DiscordService.swift @@ -388,14 +388,4 @@ actor DiscordService { .intersection(Constants.Roles.elevatedRestrictedCommandsAccessSet) .isEmpty } - -#if DEBUG - func _tests_addToMessageCache( - channelId: ChannelSnowflake, - messageId: MessageSnowflake, - message: DiscordChannel.Message - ) { - self.cachedMessages[[AnySnowflake(channelId), AnySnowflake(messageId)]] = message - } -#endif } diff --git a/Sources/Rendering/+LeafRenderer.swift b/Sources/Rendering/+LeafRenderer.swift index cfc8b7d3..276bbc79 100644 --- a/Sources/Rendering/+LeafRenderer.swift +++ b/Sources/Rendering/+LeafRenderer.swift @@ -11,7 +11,7 @@ private let leafRendererThreadPool: NIOThreadPool = { }() extension LeafRenderer { - public convenience init( + package convenience init( subDirectory: String, httpClient: HTTPClient, extraSources: [any LeafSource] = [], diff --git a/Sources/Rendering/RenderClient.swift b/Sources/Rendering/RenderClient.swift index e8b62eae..d5d4e5ae 100644 --- a/Sources/Rendering/RenderClient.swift +++ b/Sources/Rendering/RenderClient.swift @@ -1,19 +1,19 @@ @preconcurrency import LeafKit -public struct RenderClient: Sendable { +package struct RenderClient: Sendable { let renderer: LeafRenderer let encoder = LeafEncoder() - public init(renderer: LeafRenderer) { + package init(renderer: LeafRenderer) { self.renderer = renderer } - public func render(path: String, context: [String: LeafData]) async throws -> String { + package func render(path: String, context: [String: LeafData]) async throws -> String { let buffer = try await renderer.render(path: "\(path).leaf", context: context).get() return String(buffer: buffer) } - public func render( + package func render( path: String, context: Context ) async throws -> String { diff --git a/Sources/Shared/+String.swift b/Sources/Shared/+String.swift index 75d9bf90..a3caf0a4 100644 --- a/Sources/Shared/+String.swift +++ b/Sources/Shared/+String.swift @@ -1,13 +1,13 @@ extension String { - public func urlPathEncoded() -> String { + package func urlPathEncoded() -> String { self.addingPercentEncoding( withAllowedCharacters: .urlPathAllowed ) ?? self } @_disfavoredOverload - public func unicodesPrefix(_ maxUnicodeScalars: Int) -> (remaining: Int, result: String) { + package func unicodesPrefix(_ maxUnicodeScalars: Int) -> (remaining: Int, result: String) { /// Well, I mean, you _can_, but you won't like the resulting infinite loop! assert(maxUnicodeScalars > 0, "Can't request a non-positive maximum.") @@ -36,7 +36,7 @@ extension String { return (0, String(trimmed)) } - public func unicodesPrefix(_ maxUnicodeScalars: Int) -> String { + package func unicodesPrefix(_ maxUnicodeScalars: Int) -> String { unicodesPrefix(maxUnicodeScalars).result } } diff --git a/Sources/Shared/SerialProcessor.swift b/Sources/Shared/SerialProcessor.swift index 464144ae..3d6f33ea 100644 --- a/Sources/Shared/SerialProcessor.swift +++ b/Sources/Shared/SerialProcessor.swift @@ -1,6 +1,6 @@ import Collections -public actor SerialProcessor { +package actor SerialProcessor { enum Errors: Error, CustomStringConvertible { case overloaded(limit: Int) @@ -19,11 +19,11 @@ public actor SerialProcessor { private var queue: [String: Deque>] = [:] private let limit: Int - public init(queueLimit: Int = 10) { + package init(queueLimit: Int = 10) { self.limit = queueLimit } - public func process( + package func process( queueKey: String, block: @Sendable () async throws -> T ) async throws -> T { diff --git a/Sources/Shared/ServiceFactory.swift b/Sources/Shared/ServiceFactory.swift index 7cc0012b..6e99737e 100644 --- a/Sources/Shared/ServiceFactory.swift +++ b/Sources/Shared/ServiceFactory.swift @@ -1,7 +1,7 @@ import AsyncHTTPClient -public enum ServiceFactory { - public static func makeUsersService(httpClient: HTTPClient, apiBaseURL: String) -> any UsersService { +package enum ServiceFactory { + package static func makeUsersService(httpClient: HTTPClient, apiBaseURL: String) -> any UsersService { DefaultUsersService(httpClient: httpClient, apiBaseURL: apiBaseURL) } } diff --git a/Sources/Shared/UsersService/GitHubUserResponse.swift b/Sources/Shared/UsersService/GitHubUserResponse.swift index b9cb8ee0..052b0162 100644 --- a/Sources/Shared/UsersService/GitHubUserResponse.swift +++ b/Sources/Shared/UsersService/GitHubUserResponse.swift @@ -1,4 +1,4 @@ -public enum GitHubUserResponse { +package enum GitHubUserResponse { case notLinked case userName(String) } diff --git a/Sources/Shared/UsersService/UsersService.swift b/Sources/Shared/UsersService/UsersService.swift index aefa3939..7f43842a 100644 --- a/Sources/Shared/UsersService/UsersService.swift +++ b/Sources/Shared/UsersService/UsersService.swift @@ -1,7 +1,7 @@ import DiscordModels import Models -public protocol UsersService: Sendable { +package protocol UsersService: Sendable { func getUser(githubID: String) async throws -> DynamoDBUser? func postCoin(with coinRequest: UserRequest.CoinEntryRequest) async throws -> CoinResponse func getCoinCount(of discordID: UserSnowflake) async throws -> Int diff --git a/Tests/Fake/AnyBox.swift b/Tests/Fake/AnyBox.swift deleted file mode 100644 index edba56a2..00000000 --- a/Tests/Fake/AnyBox.swift +++ /dev/null @@ -1,9 +0,0 @@ - -/// A box to treat `Any` as a Sendable type. -public class AnyBox: @unchecked Sendable { - public let value: Any - - public init(_ value: Any) { - self.value = value - } -} diff --git a/Tests/Fake/FakeAutoFaqsService.swift b/Tests/Fake/FakeAutoFaqsService.swift deleted file mode 100644 index 90f3aacb..00000000 --- a/Tests/Fake/FakeAutoFaqsService.swift +++ /dev/null @@ -1,49 +0,0 @@ -@testable import Penny -import Models -import AsyncHTTPClient - -public actor FakeAutoFaqsService: AutoFaqsService { - - public typealias ResponseRateLimiter = DefaultAutoFaqsService.ResponseRateLimiter - - public init() { } - - private let all = ["PostgresNIO.PSQLError": "Update your PostgresNIO!"] - - var responseRateLimiter = ResponseRateLimiter() - - public func insert(expression: String, value: String) async throws { } - - public func remove(expression: String) async throws { } - - public func get(expression: String) async throws -> String? { - self.all[expression] - } - - public func getName(hash: Int) async throws -> String? { - self.all.first(where: { $0.key.hash == hash })?.key - } - - public func getAll() async throws -> [String: String] { - self.all - } - - public func getAllFolded() async throws -> [String: String] { - Dictionary(uniqueKeysWithValues: self.all.map({ ($0.key.superHeavyFolded(), $0.value) })) - } - - public func canRespond(receiverID: UserSnowflake, faqHash: Int) async -> Bool { - responseRateLimiter.canRespond(to: .init( - receiverID: receiverID, - faqHash: faqHash - )) - } - - public func consumeCachesStorageData(_ storage: ResponseRateLimiter) async { - self.responseRateLimiter = storage - } - - public func getCachedDataForCachesStorage() async -> ResponseRateLimiter { - return self.responseRateLimiter - } -} diff --git a/Tests/Fake/FakeFaqsService.swift b/Tests/Fake/FakeFaqsService.swift deleted file mode 100644 index 3f6a5e94..00000000 --- a/Tests/Fake/FakeFaqsService.swift +++ /dev/null @@ -1,26 +0,0 @@ -@testable import Penny -import Models -import AsyncHTTPClient - -public struct FakeFaqsService: FaqsService { - - public init() { } - - private let all = ["Working Directory": "Test working directory help"] - - public func insert(name: String, value: String) async throws { } - - public func remove(name: String) async throws { } - - public func get(name: String) async throws -> String? { - self.all[name] - } - - public func getName(hash: Int) async throws -> String? { - self.all.first(where: { $0.key.hash == hash })?.key - } - - public func getAll() async throws -> [String: String] { - self.all - } -} diff --git a/Tests/Fake/FakeMessageLookupRepo.swift b/Tests/Fake/FakeMessageLookupRepo.swift deleted file mode 100644 index 3e4b8311..00000000 --- a/Tests/Fake/FakeMessageLookupRepo.swift +++ /dev/null @@ -1,17 +0,0 @@ -@testable import GHHooksLambda -import DiscordModels - -public struct FakeMessageLookupRepo: MessageLookupRepo { - - public static let randomMessageID: MessageSnowflake = try! .makeFake() - - public init() { } - - public func getMessageID(repoID: Int, number: Int) async throws -> String { - Self.randomMessageID.rawValue - } - - public func markAsUnavailable(repoID: Int, number: Int) async throws { } - - public func saveMessageID(messageID: String, repoID: Int, number: Int) async throws { } -} diff --git a/Tests/Fake/FakeProposalsService.swift b/Tests/Fake/FakeProposalsService.swift deleted file mode 100644 index f64d3713..00000000 --- a/Tests/Fake/FakeProposalsService.swift +++ /dev/null @@ -1,15 +0,0 @@ -@testable import Penny -import Models - -public struct FakeEvolutionService: EvolutionService { - - public init() { } - - public func list() async throws -> [Proposal] { - TestData.proposalsUpdated - } - - public func getProposalContent(link: String) async throws -> String { - TestData.proposalContent - } -} diff --git a/Tests/Fake/FakeUsersService.swift b/Tests/Fake/FakeUsersService.swift deleted file mode 100644 index f4079444..00000000 --- a/Tests/Fake/FakeUsersService.swift +++ /dev/null @@ -1,35 +0,0 @@ -@testable import Penny -@testable import Models -import DiscordModels -import Shared - -public struct FakeUsersService: UsersService { - - public init() { } - - public func postCoin(with coinRequest: UserRequest.CoinEntryRequest) async throws -> CoinResponse { - CoinResponse( - sender: coinRequest.fromDiscordID, - receiver: coinRequest.toDiscordID, - newCoinCount: coinRequest.amount + .random(in: 0..<10_000) - ) - } - - public func getCoinCount(of discordID: UserSnowflake) async throws -> Int { - 2591 - } - - public func linkGitHubID(discordID: UserSnowflake, toGitHubID githubID: String) async throws { } - - public func unlinkGitHubID(discordID: UserSnowflake) async throws { } - - public func getGitHubName(of discordID: UserSnowflake) async throws -> GitHubUserResponse { - .userName("fake-username") - } - - public func getUser(githubID: String) async throws -> DynamoDBUser? { - var new = DynamoDBUser.createNew(forDiscordID: "1134810480968204288") - new.githubID = githubID - return new - } -} diff --git a/Tests/Fake/+Endpoint.swift b/Tests/PennyTests/Fake/+Endpoint.swift similarity index 100% rename from Tests/Fake/+Endpoint.swift rename to Tests/PennyTests/Fake/+Endpoint.swift diff --git a/Tests/PennyTests/Fake/AnyBox.swift b/Tests/PennyTests/Fake/AnyBox.swift new file mode 100644 index 00000000..edf60b25 --- /dev/null +++ b/Tests/PennyTests/Fake/AnyBox.swift @@ -0,0 +1,9 @@ + +/// A box to treat `Any` as a Sendable type. +class AnyBox: @unchecked Sendable { + let value: Any + + init(_ value: Any) { + self.value = value + } +} diff --git a/Tests/Fake/EventKey.swift b/Tests/PennyTests/Fake/EventKey.swift similarity index 99% rename from Tests/Fake/EventKey.swift rename to Tests/PennyTests/Fake/EventKey.swift index 862d5fc6..24f07455 100644 --- a/Tests/Fake/EventKey.swift +++ b/Tests/PennyTests/Fake/EventKey.swift @@ -1,7 +1,7 @@ import DiscordBM @testable import Penny -public enum EventKey: String, Sendable { +enum EventKey: String, Sendable { case thanksMessage case thanksMessage2 case linkInteraction @@ -28,7 +28,7 @@ public enum EventKey: String, Sendable { case autoFaqsTrigger /// The endpoints from which the bot will send a response, after receiving each event. - public var responseEndpoints: [APIEndpoint] { + var responseEndpoints: [APIEndpoint] { switch self { case .thanksMessage: return [.createMessage(channelId: "519613337638797315")] diff --git a/Tests/PennyTests/Fake/FakeAutoFaqsService.swift b/Tests/PennyTests/Fake/FakeAutoFaqsService.swift new file mode 100644 index 00000000..174d4cde --- /dev/null +++ b/Tests/PennyTests/Fake/FakeAutoFaqsService.swift @@ -0,0 +1,49 @@ +@testable import Penny +import Models +import AsyncHTTPClient + +actor FakeAutoFaqsService: AutoFaqsService { + + typealias ResponseRateLimiter = DefaultAutoFaqsService.ResponseRateLimiter + + init() { } + + private let all = ["PostgresNIO.PSQLError": "Update your PostgresNIO!"] + + var responseRateLimiter = ResponseRateLimiter() + + func insert(expression: String, value: String) async throws { } + + func remove(expression: String) async throws { } + + func get(expression: String) async throws -> String? { + self.all[expression] + } + + func getName(hash: Int) async throws -> String? { + self.all.first(where: { $0.key.hash == hash })?.key + } + + func getAll() async throws -> [String: String] { + self.all + } + + func getAllFolded() async throws -> [String: String] { + Dictionary(uniqueKeysWithValues: self.all.map({ ($0.key.superHeavyFolded(), $0.value) })) + } + + func canRespond(receiverID: UserSnowflake, faqHash: Int) async -> Bool { + responseRateLimiter.canRespond(to: .init( + receiverID: receiverID, + faqHash: faqHash + )) + } + + func consumeCachesStorageData(_ storage: ResponseRateLimiter) async { + self.responseRateLimiter = storage + } + + func getCachedDataForCachesStorage() async -> ResponseRateLimiter { + return self.responseRateLimiter + } +} diff --git a/Tests/Fake/FakeCacheService.swift b/Tests/PennyTests/Fake/FakeCacheService.swift similarity index 60% rename from Tests/Fake/FakeCacheService.swift rename to Tests/PennyTests/Fake/FakeCacheService.swift index f18b3045..e4144c15 100644 --- a/Tests/Fake/FakeCacheService.swift +++ b/Tests/PennyTests/Fake/FakeCacheService.swift @@ -1,13 +1,13 @@ @testable import Penny -public struct FakeCachesService: CachesService { +struct FakeCachesService: CachesService { let context: CachesStorage.Context - public init(context: CachesStorage.Context) { + init(context: CachesStorage.Context) { self.context = context } - public func getCachedInfoFromRepositoryAndPopulateServices() async { + func getCachedInfoFromRepositoryAndPopulateServices() async { var storage = CachesStorage() storage.evolutionCheckerData = .init( previousProposals: TestData.proposals, @@ -16,5 +16,5 @@ public struct FakeCachesService: CachesService { await storage.populateServicesAndReport(context: context) } - public func gatherCachedInfoAndSaveToRepository() async { } + func gatherCachedInfoAndSaveToRepository() async { } } diff --git a/Tests/Fake/FakeClientTransport.swift b/Tests/PennyTests/Fake/FakeClientTransport.swift similarity index 88% rename from Tests/Fake/FakeClientTransport.swift rename to Tests/PennyTests/Fake/FakeClientTransport.swift index 6bd9bbc2..e9d67d9d 100644 --- a/Tests/Fake/FakeClientTransport.swift +++ b/Tests/PennyTests/Fake/FakeClientTransport.swift @@ -2,11 +2,11 @@ import OpenAPIRuntime import HTTPTypes import Foundation -public struct FakeClientTransport: ClientTransport { +struct FakeClientTransport: ClientTransport { - public init() { } + init() { } - public func send( + func send( _ request: HTTPRequest, body: HTTPBody?, baseURL: URL, diff --git a/Tests/Fake/FakeDiscordClient.swift b/Tests/PennyTests/Fake/FakeDiscordClient.swift similarity index 84% rename from Tests/Fake/FakeDiscordClient.swift rename to Tests/PennyTests/Fake/FakeDiscordClient.swift index 910afd93..7949c67b 100644 --- a/Tests/Fake/FakeDiscordClient.swift +++ b/Tests/PennyTests/Fake/FakeDiscordClient.swift @@ -2,12 +2,12 @@ import NIOHTTP1 import XCTest -public struct FakeDiscordClient: DiscordClient { - public var appId: ApplicationSnowflake? = "11111111" +struct FakeDiscordClient: DiscordClient { + var appId: ApplicationSnowflake? = "11111111" - public init() { } + init() { } - public func send(request: DiscordHTTPRequest) async throws -> DiscordHTTPResponse { + func send(request: DiscordHTTPRequest) async throws -> DiscordHTTPResponse { await FakeResponseStorage.shared.respond( to: request.endpoint, with: AnyBox(Optional.none as Any) @@ -24,7 +24,7 @@ public struct FakeDiscordClient: DiscordClient { ) } - public func send( + func send( request: DiscordHTTPRequest, payload: E ) async throws -> DiscordHTTPResponse { @@ -45,7 +45,7 @@ public struct FakeDiscordClient: DiscordClient { ) } - public func sendMultipart( + func sendMultipart( request: DiscordHTTPRequest, payload: E ) async throws -> DiscordHTTPResponse { diff --git a/Tests/PennyTests/Fake/FakeFaqsService.swift b/Tests/PennyTests/Fake/FakeFaqsService.swift new file mode 100644 index 00000000..f8889bcd --- /dev/null +++ b/Tests/PennyTests/Fake/FakeFaqsService.swift @@ -0,0 +1,26 @@ +@testable import Penny +import Models +import AsyncHTTPClient + +struct FakeFaqsService: FaqsService { + + init() { } + + private let all = ["Working Directory": "Test working directory help"] + + func insert(name: String, value: String) async throws { } + + func remove(name: String) async throws { } + + func get(name: String) async throws -> String? { + self.all[name] + } + + func getName(hash: Int) async throws -> String? { + self.all.first(where: { $0.key.hash == hash })?.key + } + + func getAll() async throws -> [String: String] { + self.all + } +} diff --git a/Tests/Fake/FakeMainService.swift b/Tests/PennyTests/Fake/FakeMainService.swift similarity index 89% rename from Tests/Fake/FakeMainService.swift rename to Tests/PennyTests/Fake/FakeMainService.swift index a60d899b..297bfe96 100644 --- a/Tests/Fake/FakeMainService.swift +++ b/Tests/PennyTests/Fake/FakeMainService.swift @@ -8,16 +8,16 @@ import SotoCore import AsyncHTTPClient import XCTest -public actor FakeMainService: MainService { - public let manager: FakeManager - public let cache: DiscordCache - public let httpClient: HTTPClient - public let context: HandlerContext +actor FakeMainService: MainService { + let manager: FakeManager + let cache: DiscordCache + let httpClient: HTTPClient + let context: HandlerContext var botStateManager: BotStateManager { context.botStateManager } - public init(manager: FakeManager) async throws { + init(manager: FakeManager) async throws { self.manager = manager var cacheStorage = DiscordCache.Storage() cacheStorage.guilds[TestData.vaporGuild.id] = TestData.vaporGuild @@ -39,20 +39,20 @@ public actor FakeMainService: MainService { try! httpClient.syncShutdown() } - public func bootstrapLoggingSystem(httpClient: HTTPClient) async throws { } + func bootstrapLoggingSystem(httpClient: HTTPClient) async throws { } - public func makeBot( + func makeBot( eventLoopGroup: any EventLoopGroup, httpClient: HTTPClient ) async throws -> any GatewayManager { return manager } - public func makeCache(bot: any GatewayManager) async throws -> DiscordCache { + func makeCache(bot: any GatewayManager) async throws -> DiscordCache { return cache } - public func beforeConnectCall( + func beforeConnectCall( bot: any GatewayManager, cache: DiscordCache, httpClient: HTTPClient, @@ -62,7 +62,7 @@ public actor FakeMainService: MainService { return context } - public func afterConnectCall(context: HandlerContext) async throws { } + func afterConnectCall(context: HandlerContext) async throws { } static func makeContext( manager: any GatewayManager, @@ -116,7 +116,7 @@ public actor FakeMainService: MainService { ) } - public func waitForStateManagerShutdownAndDidShutdownSignals() async { + func waitForStateManagerShutdownAndDidShutdownSignals() async { /// Wait for the shutdown signal, then send a `didShutdown` signal. /// in practice, the `didShutdown` signal is sent by another Penny that is online. while let possibleSignal = await FakeResponseStorage.shared.awaitResponse( diff --git a/Tests/Fake/FakeManager.swift b/Tests/PennyTests/Fake/FakeManager.swift similarity index 69% rename from Tests/Fake/FakeManager.swift rename to Tests/PennyTests/Fake/FakeManager.swift index 5fcfc9a4..ae7e2b2e 100644 --- a/Tests/Fake/FakeManager.swift +++ b/Tests/PennyTests/Fake/FakeManager.swift @@ -4,36 +4,36 @@ import Atomics import struct NIOCore.ByteBuffer import XCTest -public actor FakeManager: GatewayManager { - public nonisolated let client: any DiscordClient = FakeDiscordClient() - public nonisolated let id: UInt = 0 - public nonisolated let identifyPayload: Gateway.Identify = .init(token: "", intents: []) +actor FakeManager: GatewayManager { + nonisolated let client: any DiscordClient = FakeDiscordClient() + nonisolated let id: UInt = 0 + nonisolated let identifyPayload: Gateway.Identify = .init(token: "", intents: []) var eventContinuations = [AsyncStream.Continuation]() - public init() { } + init() { } - public func connect() async { } + func connect() async { } - public func requestGuildMembersChunk(payload: Gateway.RequestGuildMembers) async { } - public func updatePresence(payload: Gateway.Identify.Presence) async { } - public func updateVoiceState(payload: VoiceStateUpdate) async { } - public func makeEventsStream() async -> AsyncStream { + func requestGuildMembersChunk(payload: Gateway.RequestGuildMembers) async { } + func updatePresence(payload: Gateway.Identify.Presence) async { } + func updateVoiceState(payload: VoiceStateUpdate) async { } + func makeEventsStream() async -> AsyncStream { AsyncStream { continuation in eventContinuations.append(continuation) } } - public func makeEventsParseFailureStream() async -> AsyncStream<(any Error, ByteBuffer)> { + func makeEventsParseFailureStream() async -> AsyncStream<(any Error, ByteBuffer)> { AsyncStream { _ in } } - public func disconnect() { } + func disconnect() { } - public func send(event: Gateway.Event) { + func send(event: Gateway.Event) { for continuation in eventContinuations { continuation.yield(event) } } - public func send(key: EventKey) { + func send(key: EventKey) { let data = TestData.for(gatewayEventKey: key.rawValue)! let decoder = JSONDecoder() let event: Gateway.Event @@ -48,7 +48,7 @@ public actor FakeManager: GatewayManager { } @_disfavoredOverload - public func sendAndAwaitResponse( + func sendAndAwaitResponse( key: EventKey, endpoint: APIEndpoint? = nil, as type: T.Type = T.self, @@ -64,7 +64,7 @@ public actor FakeManager: GatewayManager { ) } - public func sendAndAwaitResponse( + func sendAndAwaitResponse( key: EventKey, endpoint: AnyEndpoint? = nil, as type: T.Type = T.self, diff --git a/Tests/PennyTests/Fake/FakeMessageLookupRepo.swift b/Tests/PennyTests/Fake/FakeMessageLookupRepo.swift new file mode 100644 index 00000000..4cd07f04 --- /dev/null +++ b/Tests/PennyTests/Fake/FakeMessageLookupRepo.swift @@ -0,0 +1,17 @@ +@testable import GHHooksLambda +import DiscordModels + +struct FakeMessageLookupRepo: MessageLookupRepo { + + static let randomMessageID: MessageSnowflake = try! .makeFake() + + init() { } + + func getMessageID(repoID: Int, number: Int) async throws -> String { + Self.randomMessageID.rawValue + } + + func markAsUnavailable(repoID: Int, number: Int) async throws { } + + func saveMessageID(messageID: String, repoID: Int, number: Int) async throws { } +} diff --git a/Tests/Fake/FakePingsService.swift b/Tests/PennyTests/Fake/FakePingsService.swift similarity index 75% rename from Tests/Fake/FakePingsService.swift rename to Tests/PennyTests/Fake/FakePingsService.swift index e6b6da6f..9f0d03b7 100644 --- a/Tests/Fake/FakePingsService.swift +++ b/Tests/PennyTests/Fake/FakePingsService.swift @@ -3,9 +3,9 @@ import Models import DiscordModels import AsyncHTTPClient -public struct FakePingsService: AutoPingsService { +struct FakePingsService: AutoPingsService { - public init() { } + init() { } private let all = S3AutoPingItems(items: [ .matches("mongodb driver"): ["432065887202181142", "950695294906007573"], @@ -18,32 +18,32 @@ public struct FakePingsService: AutoPingsService { .contains("cord"): ["432065887202181142"], ]) - public func exists( + func exists( expression: Expression, forDiscordID id: UserSnowflake ) async throws -> Bool { false } - public func insert( + func insert( _ expressions: [Expression], forDiscordID id: UserSnowflake ) async throws { } - public func remove( + func remove( _ expressions: [Expression], forDiscordID id: UserSnowflake ) async throws { } - public func get(discordID id: UserSnowflake) async throws -> [Expression] { + func get(discordID id: UserSnowflake) async throws -> [Expression] { self.all.items.filter({ $0.value.contains(id) }).map(\.key) } - public func getExpression(hash: Int) async throws -> Expression? { + func getExpression(hash: Int) async throws -> Expression? { self.all.items.first(where: { $0.key.hashValue == hash })?.key } - public func getAll() async throws -> S3AutoPingItems { + func getAll() async throws -> S3AutoPingItems { self.all } } diff --git a/Tests/PennyTests/Fake/FakeProposalsService.swift b/Tests/PennyTests/Fake/FakeProposalsService.swift new file mode 100644 index 00000000..682a3e5d --- /dev/null +++ b/Tests/PennyTests/Fake/FakeProposalsService.swift @@ -0,0 +1,15 @@ +@testable import Penny +import Models + +struct FakeEvolutionService: EvolutionService { + + init() { } + + func list() async throws -> [Proposal] { + TestData.proposalsUpdated + } + + func getProposalContent(link: String) async throws -> String { + TestData.proposalContent + } +} diff --git a/Tests/Fake/FakeResponseStorage.swift b/Tests/PennyTests/Fake/FakeResponseStorage.swift similarity index 97% rename from Tests/Fake/FakeResponseStorage.swift rename to Tests/PennyTests/Fake/FakeResponseStorage.swift index b2d8785c..521aa4f2 100644 --- a/Tests/Fake/FakeResponseStorage.swift +++ b/Tests/PennyTests/Fake/FakeResponseStorage.swift @@ -2,17 +2,17 @@ import Atomics import XCTest -public actor FakeResponseStorage { +actor FakeResponseStorage { private var continuations = Continuations() private var unhandledResponses = UnhandledResponses() - public init() { } - public static var shared = FakeResponseStorage() + init() { } + static var shared = FakeResponseStorage() private static let idGenerator = ManagedAtomic(UInt(0)) - public func awaitResponse( + func awaitResponse( at endpoint: APIEndpoint, expectFailure: Bool = false, file: StaticString = #filePath, @@ -29,7 +29,7 @@ public actor FakeResponseStorage { } } - public func awaitResponse( + func awaitResponse( at endpoint: AnyEndpoint, expectFailure: Bool = false, file: StaticString = #filePath, diff --git a/Tests/Fake/FakeSOService.swift b/Tests/PennyTests/Fake/FakeSOService.swift similarity index 100% rename from Tests/Fake/FakeSOService.swift rename to Tests/PennyTests/Fake/FakeSOService.swift diff --git a/Tests/PennyTests/Fake/FakeUsersService.swift b/Tests/PennyTests/Fake/FakeUsersService.swift new file mode 100644 index 00000000..7641a527 --- /dev/null +++ b/Tests/PennyTests/Fake/FakeUsersService.swift @@ -0,0 +1,35 @@ +@testable import Penny +@testable import Models +import DiscordModels +import Shared + +struct FakeUsersService: UsersService { + + init() { } + + func postCoin(with coinRequest: UserRequest.CoinEntryRequest) async throws -> CoinResponse { + CoinResponse( + sender: coinRequest.fromDiscordID, + receiver: coinRequest.toDiscordID, + newCoinCount: coinRequest.amount + .random(in: 0..<10_000) + ) + } + + func getCoinCount(of discordID: UserSnowflake) async throws -> Int { + 2591 + } + + func linkGitHubID(discordID: UserSnowflake, toGitHubID githubID: String) async throws { } + + func unlinkGitHubID(discordID: UserSnowflake) async throws { } + + func getGitHubName(of discordID: UserSnowflake) async throws -> GitHubUserResponse { + .userName("fake-username") + } + + func getUser(githubID: String) async throws -> DynamoDBUser? { + var new = DynamoDBUser.createNew(forDiscordID: "1134810480968204288") + new.githubID = githubID + return new + } +} diff --git a/Tests/Fake/TestData.swift b/Tests/PennyTests/Fake/TestData.swift similarity index 85% rename from Tests/Fake/TestData.swift rename to Tests/PennyTests/Fake/TestData.swift index 546d1a1e..a6e64e14 100644 --- a/Tests/Fake/TestData.swift +++ b/Tests/PennyTests/Fake/TestData.swift @@ -2,7 +2,7 @@ import Foundation import DiscordModels @testable import Penny -public enum TestData { +enum TestData { private static func resource(named name: String) -> Data { let fileManager = FileManager.default @@ -19,23 +19,23 @@ public enum TestData { return try! JSONDecoder().decode(D.self, from: data) } - public static let vaporGuild = resource( + static let vaporGuild = resource( named: "guild_create.json", as: Gateway.GuildCreate.self ) - public static let proposals = TestData.resource( + static let proposals = TestData.resource( named: "proposals.json", as: [Proposal].self ) - public static let proposalsUpdated = TestData.resource( + static let proposalsUpdated = TestData.resource( named: "proposals_updated.json", as: [Proposal].self ) - public static let proposalContent = String( + static let proposalContent = String( decoding: TestData.resource(named: "proposal_content.md"), as: UTF8.self ) - public static let soQuestions = TestData.resource( + static let soQuestions = TestData.resource( named: "soQuestions.json", as: SOQuestions.self ).items @@ -60,7 +60,7 @@ public enum TestData { return dataDict }() - public static func `for`(ghEventKey key: String) -> Data? { + static func `for`(ghEventKey key: String) -> Data? { return ghHooksEvents[key] } @@ -72,7 +72,7 @@ public enum TestData { return dataDict }() - public static func `for`(ghRequestID key: String) -> Data? { + static func `for`(ghRequestID key: String) -> Data? { return ghRestOperations[key] } } diff --git a/Tests/PennyTests/+XCTest.swift b/Tests/PennyTests/Tests/+XCTest.swift similarity index 100% rename from Tests/PennyTests/+XCTest.swift rename to Tests/PennyTests/Tests/+XCTest.swift diff --git a/Tests/PennyTests/CoinHandlerTests.swift b/Tests/PennyTests/Tests/CoinHandlerTests.swift similarity index 100% rename from Tests/PennyTests/CoinHandlerTests.swift rename to Tests/PennyTests/Tests/CoinHandlerTests.swift diff --git a/Tests/PennyTests/GHHooksTests.swift b/Tests/PennyTests/Tests/GHHooksTests.swift similarity index 99% rename from Tests/PennyTests/GHHooksTests.swift rename to Tests/PennyTests/Tests/GHHooksTests.swift index 41711e8d..15e466ee 100644 --- a/Tests/PennyTests/GHHooksTests.swift +++ b/Tests/PennyTests/Tests/GHHooksTests.swift @@ -9,7 +9,6 @@ import Rendering import Logging import SwiftSemver import Markdown -import Fake import XCTest class GHHooksTests: XCTestCase { diff --git a/Tests/PennyTests/GatewayProcessingTests.swift b/Tests/PennyTests/Tests/GatewayProcessingTests.swift similarity index 99% rename from Tests/PennyTests/GatewayProcessingTests.swift rename to Tests/PennyTests/Tests/GatewayProcessingTests.swift index 68addbc0..5cfa906c 100644 --- a/Tests/PennyTests/GatewayProcessingTests.swift +++ b/Tests/PennyTests/Tests/GatewayProcessingTests.swift @@ -2,7 +2,6 @@ @testable import DiscordModels @testable import Logging import DiscordGateway -import Fake import Models import XCTest @@ -18,7 +17,7 @@ class GatewayProcessingTests: XCTestCase { // reset the storage FakeResponseStorage.shared = FakeResponseStorage() let fakeMainService = try await FakeMainService(manager: self.manager) - self.context = await fakeMainService.context + self.context = fakeMainService.context Task { try await Penny.start(mainService: fakeMainService) } diff --git a/Tests/PennyTests/LeafRenderTests.swift b/Tests/PennyTests/Tests/LeafRenderTests.swift similarity index 99% rename from Tests/PennyTests/LeafRenderTests.swift rename to Tests/PennyTests/Tests/LeafRenderTests.swift index cf7bfc3f..ca6afc9d 100644 --- a/Tests/PennyTests/LeafRenderTests.swift +++ b/Tests/PennyTests/Tests/LeafRenderTests.swift @@ -6,7 +6,6 @@ import Rendering import AsyncHTTPClient import GitHubAPI import Logging -import Fake import XCTest class LeafRenderTests: XCTestCase { diff --git a/Tests/PennyTests/OtherTests.swift b/Tests/PennyTests/Tests/OtherTests.swift similarity index 99% rename from Tests/PennyTests/OtherTests.swift rename to Tests/PennyTests/Tests/OtherTests.swift index ecdb3d64..f4d9be6d 100644 --- a/Tests/PennyTests/OtherTests.swift +++ b/Tests/PennyTests/Tests/OtherTests.swift @@ -1,6 +1,5 @@ @testable import Penny @testable import Models -import Fake import Markdown import XCTest