-
Notifications
You must be signed in to change notification settings - Fork 88
Add unit tests for DecodingErrorReporter and UnstructuredError #1409
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| // | ||
| // DecodingErrorReporterTests.swift | ||
| // OBAKitCoreTests | ||
| // | ||
| // Copyright © Open Transit Software Foundation | ||
| // This source code is licensed under the Apache 2.0 license found in the | ||
| // LICENSE file in the root directory of this source tree. | ||
| // | ||
|
|
||
| import Foundation | ||
| import Testing | ||
| @testable import OBAKitCore | ||
|
|
||
| struct DummyCodingKey: CodingKey { | ||
| var stringValue: String | ||
| var intValue: Int? | ||
| init(stringValue: String) { | ||
| self.stringValue = stringValue | ||
| } | ||
| init?(intValue: Int) { | ||
| self.stringValue = "\(intValue)" | ||
| self.intValue = intValue | ||
| } | ||
| } | ||
|
|
||
| @Suite(.serialized) | ||
| final class DecodingErrorReporterTests { | ||
|
|
||
| @Test func Message formatting for keyNotFound() { | ||
| let key = DummyCodingKey(stringValue: "missing_key") | ||
| let context = DecodingError.Context(codingPath: [], debugDescription: "Key was not found.") | ||
| let error = DecodingError.keyNotFound(key, context) | ||
|
|
||
| let message = DecodingErrorReporter.message(from: error) | ||
| #expect(message.contains("Missing key: 'missing_key'")) | ||
| #expect(message.contains("Path: root")) | ||
| #expect(message.contains("Context: Key was not found.")) | ||
| } | ||
|
|
||
| @Test func Message formatting for typeMismatch() { | ||
| let context = DecodingError.Context(codingPath: [DummyCodingKey(stringValue: "parent"), DummyCodingKey(stringValue: "child")], debugDescription: "Expected String but found Int.") | ||
| let error = DecodingError.typeMismatch(String.self, context) | ||
|
|
||
| let message = DecodingErrorReporter.message(from: error) | ||
| #expect(message.contains("Type mismatch (expected String)")) | ||
| #expect(message.contains("Path: parent → child")) | ||
| #expect(message.contains("Context: Expected String but found Int.")) | ||
| } | ||
|
|
||
| @Test func Message formatting for valueNotFound() { | ||
| let context = DecodingError.Context(codingPath: [DummyCodingKey(stringValue: "value")], debugDescription: "Null encountered.") | ||
| let error = DecodingError.valueNotFound(Int.self, context) | ||
|
|
||
| let message = DecodingErrorReporter.message(from: error) | ||
| #expect(message.contains("Missing value (expected Int)")) | ||
| #expect(message.contains("Path: value")) | ||
| #expect(message.contains("Context: Null encountered.")) | ||
| } | ||
|
|
||
| @Test func Message formatting for dataCorrupted() { | ||
| let context = DecodingError.Context(codingPath: [], debugDescription: "Invalid JSON.") | ||
| let error = DecodingError.dataCorrupted(context) | ||
|
|
||
| let message = DecodingErrorReporter.message(from: error) | ||
| #expect(message.contains("Data corrupted")) | ||
| #expect(message.contains("Path: root")) | ||
| #expect(message.contains("Context: Invalid JSON.")) | ||
| } | ||
|
|
||
| @Test func Report handler is called() { | ||
| let url = URL(string: "https://api.onebusaway.org/test")! | ||
| let httpMethod = "GET" | ||
| let context = DecodingError.Context(codingPath: [], debugDescription: "Test") | ||
| let error = DecodingError.dataCorrupted(context) | ||
|
|
||
| var handlerCalled = false | ||
| var reportedURL: URL? | ||
| var reportedMethod: String? | ||
| var reportedMessage: String? | ||
|
|
||
| DecodingErrorReporter.reportHandler = { err, u, m, msg in | ||
| handlerCalled = true | ||
| reportedURL = u | ||
| reportedMethod = m | ||
| reportedMessage = msg | ||
|
Comment on lines
+82
to
+85
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: #!/bin/bash
set -euo pipefail
# Locate repository-declared Swift language mode and concurrency settings.
fd -HI -t f 'Package\.swift|.*\.xcconfig|project\.pbxproj' . -x \
rg -n -C2 'swift-tools-version|swiftLanguageModes|SWIFT_VERSION|SWIFT_STRICT_CONCURRENCY|StrictConcurrency|enableUpcomingFeature' {}
# Then build this test target with the declared toolchain and confirm whether
# lines 82-85 emit a "mutation of captured var in concurrently-executing code"
# diagnostic.Repository: OneBusAway/onebusaway-ios Length of output: 163 🤖 get_repo_knowledge executed:
Length of output: 38902 🏁 Script executed: #!/bin/bash
set -u
printf '%s\n' '--- candidate configuration files ---'
git ls-files | grep -E '(^|/)(Package\.swift|[^/]+\.xcconfig|project\.pbxproj)$' || true
printf '%s\n' '--- relevant configuration declarations ---'
git ls-files | grep -E '(^|/)(Package\.swift|[^/]+\.xcconfig|project\.pbxproj)$' |
while IFS= read -r f; do
grep -n -E -C2 'swift-tools-version|SWIFT_VERSION|SWIFT_STRICT_CONCURRENCY|StrictConcurrency|enableUpcomingFeature|SWIFT_ACTIVE_COMPILATION_CONDITIONS' "$f" || true
done
printf '%s\n' '--- reviewed test and production declarations ---'
grep -n -E -C8 'reportHandler|handlerCalled|reportedURL|reportedMethod|reportedMessage|func [^()]+ ' \
OBAKitCoreTests/Utilities/DecodingErrorReporterTests.swift \
OBAKitCore/Utilities/DecodingErrorReporter.swift || trueRepository: OneBusAway/onebusaway-ios Length of output: 11498 🏁 Script executed: #!/bin/bash
set -u
printf '%s\n' '--- tracked Swift project/configuration files ---'
git ls-files | grep -E '\.(xcodeproj|xcworkspace|pbxproj|xcconfig|swift)$' | head -200
printf '%s\n' '--- test file ---'
cat -n OBAKitCoreTests/Utilities/DecodingErrorReporterTests.swift
printf '%s\n' '--- reporter implementation ---'
cat -n OBAKitCore/Utilities/DecodingErrorReporter.swiftRepository: OneBusAway/onebusaway-ios Length of output: 17649 🏁 Script executed: #!/bin/bash
set -u
for f in OBAKitCoreTests/Utilities/DecodingErrorReporterTests.swift OBAKitCore/Utilities/DecodingErrorReporter.swift; do
if [ -f "$f" ]; then
printf '%s\n' "--- $f ---"
cat -n "$f"
fi
done
printf '%s\n' '--- project settings ---'
find . -type f \( -name '*.pbxproj' -o -name '*.xcconfig' -o -name 'Package.swift' \) -print |
while IFS= read -r f; do
grep -n -E -C2 'SWIFT_VERSION|SWIFT_STRICT_CONCURRENCY|StrictConcurrency|enableUpcomingFeature|swiftLanguageModes|swift-tools-version' "$f" || true
doneRepository: OneBusAway/onebusaway-ios Length of output: 7805 🏁 Script executed: #!/bin/bash
set -u
printf '%s\n' '--- project-generation and CI configuration files ---'
git ls-files | grep -E '(^|/)(project\.yml|project\.yaml|.*\.yml|.*\.yaml|.*\.json|Makefile|README.*|CLAUDE\.md)$' |
grep -E '(^|/)(project\.yml|project\.yaml|.*\.yml|.*\.yaml|.*\.json|Makefile|README.*|CLAUDE\.md)$' |
head -200
printf '%s\n' '--- concurrency and OBAKitCoreTests settings ---'
rg -n -C3 'OBAKitCoreTests|SWIFT_VERSION|SWIFT_STRICT_CONCURRENCY|StrictConcurrency|SWIFT_ENABLE_EXPLICIT_MODULES|swiftLanguageModes|enableUpcomingFeature|strictConcurrency' \
--glob '*.yml' --glob '*.yaml' --glob '*.json' --glob '*.md' --glob 'Makefile' --glob '*.sh' . || trueRepository: OneBusAway/onebusaway-ios Length of output: 17941 🏁 Script executed: #!/bin/bash
set -u
printf '%s\n' '--- project-generation files ---'
git ls-files | grep -E '(^|/)(project\.(yml|yaml)|.*\.(yml|yaml)|.*\.json|Makefile|README.*|CLAUDE\.md)$' | head -200
printf '%s\n' '--- target and concurrency settings ---'
rg -n -C3 'OBAKitCoreTests|SWIFT_VERSION|SWIFT_STRICT_CONCURRENCY|StrictConcurrency|swiftLanguageModes|enableUpcomingFeature|strictConcurrency' \
--glob '*.yml' --glob '*.yaml' --glob '*.json' --glob '*.md' --glob 'Makefile' --glob '*.sh' . || trueRepository: OneBusAway/onebusaway-ios Length of output: 17911 🏁 Script executed: #!/bin/bash
set -u
for f in OBAKitCore/project.yml OBAKitTests/project.yml Apps/Shared/app_shared.yml; do
if [ -f "$f" ]; then
printf '%s\n' "--- $f ---"
cat -n "$f"
fi
done
printf '%s\n' '--- OBAKitCoreTests references ---'
rg -n -C4 'OBAKitCoreTests|OBAKitCore' OBAKitCore/project.yml OBAKitTests/project.yml Apps/Shared/app_shared.yml Apps/*/project.yml OBAKit/project.yml 2>/dev/null || trueRepository: OneBusAway/onebusaway-ios Length of output: 13672 Protect the callback state before assigning
🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| DecodingErrorReporter.report(error: error, url: url, httpMethod: httpMethod) | ||
|
|
||
| #expect(handlerCalled == true) | ||
| #expect(reportedURL == url) | ||
| #expect(reportedMethod == "GET") | ||
| #expect(reportedMessage?.contains("Data corrupted") == true) | ||
|
|
||
| // Cleanup | ||
| DecodingErrorReporter.reportHandler = nil | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| // | ||
| // UnstructuredErrorTests.swift | ||
| // OBAKitCoreTests | ||
| // | ||
| // Copyright © Open Transit Software Foundation | ||
| // This source code is licensed under the Apache 2.0 license found in the | ||
| // LICENSE file in the root directory of this source tree. | ||
| // | ||
|
|
||
| import Foundation | ||
| import Testing | ||
| @testable import OBAKitCore | ||
|
|
||
| @Suite(.serialized) | ||
| final class UnstructuredErrorTests { | ||
|
|
||
| @Test func Initialization sets properties correctly() { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win 🔎 Supported by static analysis🤖 get_repo_knowledge executed:
Length of output: 38897 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- changed file ---'
cat -n OBAKitCoreTests/Utilities/UnstructuredErrorTests.swift
printf '%s\n' '--- implementation ---'
cat -n OBAKitCore/Utilities/UnstructuredError.swift
printf '%s\n' '--- nearby Swift test declarations ---'
rg -n --glob '*.swift' '`@Test`|func [A-Za-z_][A-Za-z0-9_]*\(' OBAKitCoreTests/Utilities | head -120Repository: OneBusAway/onebusaway-ios Length of output: 2854 Use valid Swift function names. Both declarations are invalid Swift syntax, so the test target cannot compile. Use valid identifiers and preserve readable test names with Proposed fix- `@Test` func Initialization sets properties correctly() {
+ `@Test`("Initialization sets properties correctly")
+ func initializationSetsPropertiesCorrectly() {
...
- `@Test` func Initialization without recovery suggestion() {
+ `@Test`("Initialization without recovery suggestion")
+ func initializationWithoutRecoverySuggestion() {🤖 Prompt for AI Agents |
||
| let error = UnstructuredError("Something went wrong", recoverySuggestion: "Try again later") | ||
|
|
||
| #expect(error.errorDescription == "Something went wrong") | ||
| #expect(error.recoverySuggestion == "Try again later") | ||
| } | ||
|
|
||
| @Test func Initialization without recovery suggestion() { | ||
| let error = UnstructuredError("Only description") | ||
|
|
||
| #expect(error.errorDescription == "Only description") | ||
| #expect(error.recoverySuggestion == nil) | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win
Rename these test functions to valid Swift identifiers.
Swift function identifiers cannot contain unescaped spaces. The parser stops after
Message, so the test target does not compile. Use camelCase names or backticked identifiers.Proposed fix
Also applies to: 40-40, 50-50, 60-60, 70-70
🤖 Prompt for AI Agents