Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ let package = Package(
platforms: [.iOS(.v17), .macOS(.v14)],
products: [
.library(name: "GutenbergKit", targets: ["GutenbergKit"]),
.library(name: "GutenbergKitHTTP", targets: ["GutenbergKitHTTP"]),
.library(name: "GutenbergKitResources", targets: ["GutenbergKitResources"]),
],
dependencies: [
Expand All @@ -31,6 +32,17 @@ let package = Package(
exclude: ["Gutenberg"],
packageAccess: false
),
.target(
name: "GutenbergKitHTTP",
path: "ios/Sources/GutenbergKitHTTP",
exclude: ["README.md"]
),
.executableTarget(
name: "GutenbergKitDebugServer",
dependencies: ["GutenbergKitHTTP"],
path: "ios/Sources/GutenbergKitDebugServer",
exclude: ["README.md"]
),
gutenbergKitResources,
.testTarget(
name: "GutenbergKitTests",
Expand All @@ -40,7 +52,15 @@ let package = Package(
resources: [
.process("Resources")
]
)
),
.testTarget(
name: "GutenbergKitHTTPTests",
dependencies: ["GutenbergKitHTTP"],
path: "ios/Tests/GutenbergKitHTTPTests",
resources: [
.copy("../../../test-fixtures/http")
]
),
]
)

Expand Down
15 changes: 15 additions & 0 deletions android/Gutenberg/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,23 @@ android {
jvmTarget = "1.8"
}

sourceSets {
getByName("androidTest") {
// Make shared test fixtures available as assets for instrumented tests.
assets.srcDir(rootProject.file("../test-fixtures"))
}
}

testOptions {
unitTests {
isReturnDefaultValues = true
all {
// Make the shared test fixtures available to fixture-driven tests.
val fixturesDir = rootProject.file("../test-fixtures/http")
it.systemProperty("test.fixtures.dir", fixturesDir.absolutePath)
// Track fixture files as task inputs so changes trigger re-runs.
it.inputs.dir(fixturesDir)
}
}
}
}
Expand All @@ -64,6 +78,7 @@ dependencies {
implementation(libs.okhttp)

testImplementation(libs.junit)
testImplementation(kotlin("test"))
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.mockito.core)
testImplementation(libs.mockito.kotlin)
Expand Down
37 changes: 36 additions & 1 deletion android/Gutenberg/detekt-baseline.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
<?xml version="1.0" ?>
<SmellBaseline>
<ManuallySuppressedIssues></ManuallySuppressedIssues>
<ManuallySuppressedIssues/>
<CurrentIssues>
<ID>ComplexCondition:FixtureTests.kt$FixtureTests$expected.has("isComplete") &amp;&amp; !expected.get("isComplete").asBoolean &amp;&amp; expected.has("hasHeaders") &amp;&amp; !expected.get("hasHeaders").asBoolean</ID>
<ID>CyclomaticComplexMethod:EditorConfiguration.kt$EditorConfiguration$override fun equals(other: Any?): Boolean</ID>
<ID>CyclomaticComplexMethod:FixtureTests.kt$FixtureTests$@Test fun `request parsing - all incremental cases pass`()</ID>
<ID>CyclomaticComplexMethod:HTTPRequestSerializer.kt$HTTPRequestSerializer$fun parseHeaders(data: ByteArray): HeaderParseResult</ID>
<ID>CyclomaticComplexMethod:HttpServer.kt$HttpServer$private suspend fun handleRequest(socket: Socket)</ID>
<ID>CyclomaticComplexMethod:MultipartPart.kt$MultipartPart.Companion$fun parseChunked( source: RequestBody.FileBacked, boundary: String ): List&lt;MultipartPart&gt;</ID>
<ID>ExplicitItLambdaParameter:EditorAssetsLibrary.kt$EditorAssetsLibrary${ str, it -&gt; str + "%02x".format(it) }</ID>
<ID>FunctionNaming:EditorURLCache.kt$EditorURLCache$private fun __store( response: EditorURLResponse, url: String, httpMethod: EditorHttpMethod, currentDate: Date )</ID>
<ID>LongMethod:FixtureTests.kt$FixtureTests$@Test fun `request parsing - all basic cases pass`()</ID>
<ID>LongMethod:FixtureTests.kt$FixtureTests$@Test fun `request parsing - all incremental cases pass`()</ID>
<ID>LongMethod:HTTPRequestParser.kt$HTTPRequestParser$fun append(data: ByteArray): Unit</ID>
<ID>LongMethod:HTTPRequestSerializer.kt$HTTPRequestSerializer$fun parseHeaders(data: ByteArray): HeaderParseResult</ID>
<ID>LongMethod:HttpServer.kt$HttpServer$private suspend fun handleRequest(socket: Socket)</ID>
<ID>LongMethod:MultipartPart.kt$MultipartPart.Companion$fun parse( source: RequestBody, bodyData: ReadOnlyBytes, bodyFileOffset: Long, boundary: String ): List&lt;MultipartPart&gt;</ID>
<ID>LongMethod:MultipartPart.kt$MultipartPart.Companion$fun parseChunked( source: RequestBody.FileBacked, boundary: String ): List&lt;MultipartPart&gt;</ID>
<ID>LongParameterList:EditorService.kt$EditorService.Companion$( context: Context, configuration: EditorConfiguration, httpClient: EditorHTTPClientProtocol? = null, cachePolicy: EditorCachePolicy = EditorCachePolicy.Always, coroutineScope: CoroutineScope, storageRoot: File? = null, tempStorageRoot: File? = null, cacheRoot: File? = null )</ID>
<ID>LongParameterList:HttpServer.kt$HttpServer$( val name: String, private val requestedPort: Int = 0, private val externallyAccessible: Boolean, private val requiresAuthentication: Boolean = true, private val maxConnections: Int = DEFAULT_MAX_CONNECTIONS, private val maxBodySize: Long = DEFAULT_MAX_BODY_SIZE, private val readTimeoutMs: Int = DEFAULT_READ_TIMEOUT_MS, private val idleTimeoutMs: Int = DEFAULT_IDLE_TIMEOUT_MS, private val cacheDir: File? = null, private val handler: suspend (HttpRequest) -&gt; HttpResponse )</ID>
<ID>LoopWithTooManyJumpStatements:HTTPRequestParser.kt$HTTPRequestParser$for</ID>
<ID>LoopWithTooManyJumpStatements:HTTPRequestSerializer.kt$HTTPRequestSerializer$for</ID>
<ID>LoopWithTooManyJumpStatements:HeaderValue.kt$HeaderValue$while</ID>
<ID>LoopWithTooManyJumpStatements:HttpServer.kt$HttpServer$while</ID>
<ID>LoopWithTooManyJumpStatements:HttpServer.kt$HttpServer.Companion$for</ID>
<ID>LoopWithTooManyJumpStatements:MultipartPart.kt$MultipartPart.Companion$for</ID>
<ID>LoopWithTooManyJumpStatements:MultipartPart.kt$MultipartPart.Companion$while</ID>
<ID>MaxLineLength:EditorConfiguration.kt$EditorConfiguration.Builder$fun setNamespaceExcludedPaths(namespaceExcludedPaths: Array&lt;String&gt;)</ID>
<ID>MaxLineLength:EditorConfiguration.kt$EditorConfiguration.Companion$fun</ID>
<ID>MaxLineLength:EditorHTTPClientTest.kt$EditorHTTPClientTest$val wpErrorJson = """{"code": "rest_invalid_param", "message": "Invalid parameter(s): title", "data": {"status": 400, "params": {"title": "Title is required."}}}"""</ID>
Expand All @@ -14,19 +34,32 @@
<ID>MaxLineLength:EditorSettingsTest.kt$EditorSettingsTest$val jsonString = """{"styles": [{"css": "body { color: red; }", "isGlobalStyles": true}, {"css": "h1 { font-size: 2em; }", "isGlobalStyles": false}]}"""</ID>
<ID>MaxLineLength:EditorSettingsTest.kt$EditorSettingsTest$val jsonString = """{"styles": [{"css": null, "isGlobalStyles": true}, {"css": "h1 { font-size: 2em; }", "isGlobalStyles": false}]}"""</ID>
<ID>MaxLineLength:GutenbergView.kt$GutenbergView$constructor</ID>
<ID>MaxLineLength:HttpServerAuthenticationTests.kt$HttpServerAuthenticationTests$val raw = "GET /test HTTP/1.1\r\nHost: 127.0.0.1\r\nProxy-Authorization: Bearer ${server.token}\r\nRelay-Authorization: Bearer wrong\r\n\r\n"</ID>
<ID>MaxLineLength:RESTAPIRepositoryTest.kt$RESTAPIRepositoryTest$val rawJSON = """{"styles":[{"css":".theme-style{color:blue}","isGlobalStyles":true},{"css":".another{margin:0}","isGlobalStyles":false}]}"""</ID>
<ID>MaxLineLength:RequestBody.kt$Buffer$internal</ID>
<ID>NestedBlockDepth:EditorAssetsLibrary.kt$EditorAssetsLibrary$private fun cleanupOldCache()</ID>
<ID>NestedBlockDepth:FileCache.kt$FileCache$fun copyToCache(context: Context, uri: Uri, maxSizeBytes: Long = DEFAULT_MAX_FILE_SIZE): Uri?</ID>
<ID>NestedBlockDepth:FileCache.kt$FileCache$private fun getFileSize(context: Context, uri: Uri): Long?</ID>
<ID>NestedBlockDepth:FixtureTests.kt$FixtureTests$@Test fun `multipart parsing - all cases pass`()</ID>
<ID>NestedBlockDepth:FixtureTests.kt$FixtureTests$@Test fun `request parsing - all incremental cases pass`()</ID>
<ID>NestedBlockDepth:MultipartPart.kt$MultipartPart.Companion$fun parseChunked( source: RequestBody.FileBacked, boundary: String ): List&lt;MultipartPart&gt;</ID>
<ID>PrintStackTrace:GutenbergView.kt$GutenbergView$e</ID>
<ID>ReturnCount:GutenbergView.kt$GutenbergView.&lt;no name provided&gt;$override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest): Boolean</ID>
<ID>ReturnCount:HTTPRequestSerializer.kt$HTTPRequestSerializer$fun parseHeaders(data: ByteArray): HeaderParseResult</ID>
<ID>ReturnCount:HttpServer.kt$HttpServer$private suspend fun handleRequest(socket: Socket)</ID>
<ID>ReturnCount:ParsedHTTPRequest.kt$ParsedHTTPRequest.Companion$private fun extractBoundary(contentType: String): String?</ID>
<ID>SwallowedException:EditorAssetsLibrary.kt$EditorAssetsLibrary$e: Exception</ID>
<ID>SwallowedException:EditorConfiguration.kt$EditorConfiguration$e: Exception</ID>
<ID>SwallowedException:EditorDependenciesSerializer.kt$EditorDependenciesSerializer$e: Exception</ID>
<ID>SwallowedException:EditorHTTPClient.kt$EditorHTTPClient$e: Exception</ID>
<ID>SwallowedException:EditorHTTPClient.kt$EditorHTTPClient$e: JsonSyntaxException</ID>
<ID>SwallowedException:EditorURLResponse.kt$EditorURLResponse$e: Exception</ID>
<ID>SwallowedException:LocalEditorAssetManifest.kt$LocalEditorAssetManifest$e: Exception</ID>
<ID>ThrowsCount:HTTPRequestSerializer.kt$HTTPRequestSerializer$internal fun validateContentLength(value: String, existing: Long?): Long</ID>
<ID>ThrowsCount:MultipartPart.kt$MultipartPart.Companion$fun parse( source: RequestBody, bodyData: ReadOnlyBytes, bodyFileOffset: Long, boundary: String ): List&lt;MultipartPart&gt;</ID>
<ID>ThrowsCount:MultipartPart.kt$MultipartPart.Companion$fun parseChunked( source: RequestBody.FileBacked, boundary: String ): List&lt;MultipartPart&gt;</ID>
<ID>ThrowsCount:MultipartPart.kt$MultipartPart.Companion$private fun parsePartHeaders(headerData: ByteArray, body: RequestBody): MultipartPart</ID>
<ID>ThrowsCount:ParsedHTTPRequest.kt$ParsedHTTPRequest$fun multipartParts(): List&lt;MultipartPart&gt;</ID>
<ID>TooGenericExceptionCaught:CachedAssetRequestInterceptor.kt$CachedAssetRequestInterceptor$e: Exception</ID>
<ID>TooGenericExceptionCaught:EditorAssetsLibrary.kt$EditorAssetsLibrary$e: Exception</ID>
<ID>TooGenericExceptionCaught:EditorConfiguration.kt$EditorConfiguration$e: Exception</ID>
Expand All @@ -35,6 +68,7 @@
<ID>TooGenericExceptionCaught:EditorURLResponse.kt$EditorURLResponse$e: Exception</ID>
<ID>TooGenericExceptionCaught:FileCache.kt$FileCache$e: Exception</ID>
<ID>TooGenericExceptionCaught:GutenbergView.kt$GutenbergView$e: Exception</ID>
<ID>TooGenericExceptionCaught:HttpServer.kt$HttpServer$e: Exception</ID>
<ID>TooGenericExceptionCaught:LocalEditorAssetManifest.kt$LocalEditorAssetManifest$e: Exception</ID>
<ID>TooGenericExceptionThrown:EditorAssetsLibrary.kt$EditorAssetsLibrary$throw Exception("Failed to fetch asset: $httpURL (${connection.responseCode})")</ID>
<ID>TooGenericExceptionThrown:EditorAssetsLibrary.kt$EditorAssetsLibrary$throw Exception("Failed to fetch manifest: ${connection.responseCode}")</ID>
Expand All @@ -44,5 +78,6 @@
<ID>UnusedPrivateProperty:GutenbergView.kt$GutenbergView.Companion$private const val ASSET_LOADING_TIMEOUT_MS = 5000L</ID>
<ID>UseCheckOrError:TestResources.kt$TestResources$throw IllegalStateException( "Could not find iOS test resources. Tried: ${possiblePaths.map { it.absolutePath }}" )</ID>
<ID>UseRequire:EditorAssetsLibrary.kt$EditorAssetsLibrary$throw IllegalArgumentException("Unsupported URL for caching: $httpURL")</ID>
<ID>VariableNaming:HttpServer.kt$HttpServer$private val TAG = "GutenbergKit.HTTP"</ID>
</CurrentIssues>
</SmellBaseline>
Loading
Loading