Skip to content

Commit f5b6388

Browse files
authored
Merge pull request #55 from bennesp/add-tests
Add tests
2 parents 575bc68 + 310f8ae commit f5b6388

File tree

15 files changed

+451
-39
lines changed

15 files changed

+451
-39
lines changed

.github/workflows/tests.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: Run tests
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
branches: [master]
9+
workflow_dispatch: {}
10+
11+
jobs:
12+
tests:
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- name: Checkout repository
17+
uses: actions/checkout@v2
18+
19+
- name: Run tests
20+
run: ./gradlew test

build.gradle.kts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import org.gradle.api.tasks.testing.logging.TestLogEvent
2+
13
plugins {
24
kotlin("jvm") version "1.9.0"
35
}
@@ -13,6 +15,7 @@ repositories {
1315
dependencies {
1416
@Suppress("LocalVariableName")
1517
val ktor_version = "2.3.3"
18+
1619
@Suppress("LocalVariableName")
1720
val logback_version = "1.4.11"
1821

@@ -59,6 +62,11 @@ configurations.all {
5962

6063
tasks.test {
6164
useJUnitPlatform()
65+
maxParallelForks = 4
66+
67+
testLogging {
68+
events(TestLogEvent.PASSED, TestLogEvent.SKIPPED, TestLogEvent.FAILED)
69+
}
6270
}
6371

6472
tasks.jar {

src/main/kotlin/it/bennes/jsonSchemaGenerator/Routes.kt

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ package it.bennes.jsonSchemaGenerator
33
import it.bennes.jsonSchemaGenerator.encoding.Encoding
44
import it.bennes.jsonSchemaGenerator.exceptions.BadRequestException
55
import it.bennes.jsonSchemaGenerator.formats.Format
6-
import io.ktor.client.request.*
76
import io.ktor.client.statement.*
87
import io.ktor.server.application.*
98
import io.ktor.server.response.*
109
import io.ktor.server.routing.*
10+
import it.bennes.jsonSchemaGenerator.model.JsonSchemaInferrer
1111
import it.bennes.jsonSchemaGenerator.model.Request
1212

1313
fun Route.main() {
@@ -25,42 +25,55 @@ fun Route.main() {
2525
HttpClient.get(url).bodyAsText()
2626
} else data ?: throw BadRequestException("No url or data provided")
2727

28-
// Decode data
29-
val encoder = Encoding.fromString(encoding)
30-
val decodedContent = try {
31-
encoder.decoder.decode(content)
32-
} catch (e: Exception) {
33-
throw BadRequestException("error during decoding: ${e.message}")
34-
}
35-
3628
// Generate schema
37-
// 1. Parse data
38-
val schemaService = SchemaService(Format.fromString(inputFormat), Format.fromString(outputFormat))
39-
val parsedContent = schemaService.parse(decodedContent)
29+
val schemaAsString = generateSchemaAsString(encoding, content, inputFormat, outputFormat, selector, generate)
4030

41-
// 2. Select data, if selector is provided
42-
val selectedContent = if (selector != null) {
43-
val node = parsedContent.at(selector)
44-
if (node.isMissingNode) {
45-
throw BadRequestException("selector did not match any node")
46-
}
47-
node
48-
} else {
49-
parsedContent
50-
}
31+
// Respond with the schema to the client
32+
call.respond(schemaAsString)
5133

52-
// 3. Generate schema, if generate is true
53-
val schema = if (generate) {
54-
schemaService.generate(selectedContent)
55-
} else {
56-
selectedContent
57-
}
34+
}
35+
}
5836

59-
// 4. Encode schema
60-
val schemaAsString = schemaService.toString(schema)
37+
private fun generateSchemaAsString(
38+
encoding: String,
39+
content: String,
40+
inputFormat: String,
41+
outputFormat: String,
42+
selector: String?,
43+
generate: Boolean,
44+
): String {
45+
// Generate schema
46+
// 1. Decode data
47+
val encoder = Encoding.fromString(encoding)
48+
val decodedContent = try {
49+
encoder.decoder.decode(content)
50+
} catch (e: Exception) {
51+
throw BadRequestException("error during decoding: ${e.message}")
52+
}
6153

62-
// 5. Respond with the schema to the client
63-
call.respond(schemaAsString)
54+
// 2. Parse data
55+
val inferrer = JsonSchemaInferrer()
56+
val schemaService = SchemaService(inferrer, Format.fromString(inputFormat), Format.fromString(outputFormat))
57+
val parsedContent = schemaService.parse(decodedContent)
58+
59+
// 3. Select data, if selector is provided
60+
val selectedContent = if (selector != null) {
61+
val node = parsedContent.at(selector)
62+
if (node.isMissingNode) {
63+
throw BadRequestException("selector did not match any node")
64+
}
65+
node
66+
} else {
67+
parsedContent
68+
}
6469

70+
// 4. Generate schema, if generate is true
71+
val schema = if (generate) {
72+
schemaService.generate(selectedContent)
73+
} else {
74+
selectedContent
6575
}
76+
77+
// 5. Encode schema
78+
return schemaService.toString(schema)
6679
}

src/main/kotlin/it/bennes/jsonSchemaGenerator/SchemaService.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ package it.bennes.jsonSchemaGenerator
22

33
import com.fasterxml.jackson.databind.JsonNode
44
import com.fasterxml.jackson.databind.ObjectMapper
5-
import com.saasquatch.jsonschemainferrer.JsonSchemaInferrer
65
import it.bennes.jsonSchemaGenerator.formats.Format
6+
import it.bennes.jsonSchemaGenerator.model.JsonSchemaInferrer
77

8-
class SchemaService(inputFormat: Format, outputFormat: Format) {
8+
class SchemaService(private val inferrer: JsonSchemaInferrer, inputFormat: Format, outputFormat: Format) {
99
private var inputMapper = ObjectMapper(inputFormat.factory)
1010
private var outputMapper = ObjectMapper(outputFormat.factory)
11-
private val inferrer = JsonSchemaInferrer.newBuilder().build()
1211

1312
fun parse(input: String): JsonNode = inputMapper.readTree(input)
1413

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package it.bennes.jsonSchemaGenerator.model
2+
3+
import com.fasterxml.jackson.databind.JsonNode
4+
import com.saasquatch.jsonschemainferrer.JsonSchemaInferrer
5+
6+
interface IJsonSchemaInferrer {
7+
fun inferForSample(content: JsonNode): JsonNode
8+
}
9+
10+
class JsonSchemaInferrer : IJsonSchemaInferrer {
11+
private val inferrer: JsonSchemaInferrer = JsonSchemaInferrer.newBuilder().build()
12+
override fun inferForSample(content: JsonNode): JsonNode {
13+
return inferrer.inferForSample(content)
14+
}
15+
}

src/main/kotlin/it/bennes/jsonSchemaGenerator/model/Request.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ data class Request(
4040
|| address.isSiteLocalAddress
4141
|| address.isMulticastAddress
4242
) {
43-
throw BadRequestException("url must not be localhost")
43+
throw BadRequestException("url must not be local")
4444
}
4545
uri.toString()
4646
} else null
@@ -54,19 +54,19 @@ data class Request(
5454
val inputFormat = if ("input" in p) {
5555
p["input"]!!
5656
} else {
57-
Format.Yaml.name
57+
Format.Yaml.name.lowercase()
5858
}
5959

6060
val outputFormat = if ("output" in p) {
6161
p["output"]!!
6262
} else {
63-
Format.Json.name
63+
Format.Json.name.lowercase()
6464
}
6565

6666
val encoding = if ("encoding" in p) {
6767
p["encoding"]!!
6868
} else {
69-
Encoding.Nop.name
69+
Encoding.Nop.name.lowercase()
7070
}
7171

7272
val generate = if ("generate" in p) {
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package it.bennes.jsonSchemaGenerator
2+
3+
import com.fasterxml.jackson.core.JsonParseException
4+
import it.bennes.jsonSchemaGenerator.formats.Format
5+
import it.bennes.jsonSchemaGenerator.model.JsonSchemaInferrer
6+
import kotlin.test.Test
7+
import kotlin.test.assertEquals
8+
import kotlin.test.assertFailsWith
9+
10+
11+
class SchemaServiceTest {
12+
13+
@Test
14+
fun `valid parse`() {
15+
val schemaService = SchemaService(JsonSchemaInferrer(), Format.Json, Format.Json)
16+
val expected = """{"a":1}"""
17+
val actual = schemaService.parse(expected)
18+
19+
assertEquals(expected, actual.toString())
20+
}
21+
22+
@Test
23+
fun `invalid parse`() {
24+
val schemaService = SchemaService(JsonSchemaInferrer(), Format.Json, Format.Json)
25+
val expected = """{"a":1"""
26+
assertFailsWith<JsonParseException> {
27+
schemaService.parse(expected)
28+
}
29+
}
30+
31+
@Test
32+
fun `valid simple generate`() {
33+
val schemaService = SchemaService(JsonSchemaInferrer(), Format.Json, Format.Json)
34+
val input = """{"a":1}"""
35+
val expected = """{"${"$"}schema":"http://json-schema.org/draft-04/schema#","type":"object","properties":{"a":{"type":"integer"}}}"""
36+
val actual = schemaService.generate(schemaService.parse(input))
37+
38+
assertEquals(expected, actual.toString())
39+
}
40+
41+
@Test
42+
fun `invalid generate`() {
43+
val schemaService = SchemaService(JsonSchemaInferrer(), Format.Json, Format.Json)
44+
val input = """{"a":1"""
45+
assertFailsWith<JsonParseException> {
46+
schemaService.generate(schemaService.parse(input))
47+
}
48+
}
49+
50+
@Test
51+
fun `test parse and toString to be reversible`() {
52+
val schemaService = SchemaService(JsonSchemaInferrer(), Format.Json, Format.Json)
53+
val input = """{"a":1}"""
54+
val expected = """{"a":1}"""
55+
val actual = schemaService.toString(schemaService.parse(input))
56+
57+
assertEquals(expected, actual)
58+
}
59+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package it.bennes.jsonSchemaGenerator.encoding
2+
3+
import kotlin.test.Test
4+
import kotlin.test.assertEquals
5+
import kotlin.test.assertFailsWith
6+
7+
class Base64DecoderTest {
8+
9+
@Test
10+
fun `test decode with valid input`() {
11+
val decoder = Base64Decoder()
12+
assertEquals("This is a test", decoder.decode("VGhpcyBpcyBhIHRlc3Q="))
13+
}
14+
15+
@Test
16+
fun `test decode with invalid input`() {
17+
val decoder = Base64Decoder()
18+
assertFailsWith<IllegalArgumentException> {
19+
decoder.decode("This is a test")
20+
}
21+
}
22+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package it.bennes.jsonSchemaGenerator.encoding
2+
3+
import kotlin.test.assertEquals
4+
import kotlin.test.assertFailsWith
5+
import kotlin.test.Test
6+
7+
class EncodingTest {
8+
9+
@Test
10+
fun `test fromString with valid input`() {
11+
assertEquals(Encoding.Nop, Encoding.fromString("nop"))
12+
assertEquals(Encoding.Base64, Encoding.fromString("base64"))
13+
assertEquals(Encoding.Hex, Encoding.fromString("hex"))
14+
}
15+
16+
@Test
17+
fun `test fromString with invalid input`() {
18+
assertFailsWith<IllegalArgumentException> {
19+
Encoding.fromString("invalid")
20+
}
21+
}
22+
23+
@Test
24+
fun `test decoder instances`() {
25+
assertEquals(NopDecoder::class, Encoding.Nop.decoder::class)
26+
assertEquals(Base64Decoder::class, Encoding.Base64.decoder::class)
27+
assertEquals(HexDecoder::class, Encoding.Hex.decoder::class)
28+
}
29+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package it.bennes.jsonSchemaGenerator.encoding
2+
3+
4+
import java.lang.IllegalArgumentException
5+
import kotlin.test.assertEquals
6+
import kotlin.test.Test
7+
import kotlin.test.assertFailsWith
8+
9+
class HexDecoderTest {
10+
11+
@Test
12+
fun `test decode with valid input`() {
13+
val decoder = HexDecoder()
14+
assertEquals("This is a test", decoder.decode("5468697320697320612074657374"))
15+
}
16+
17+
@Test
18+
fun `test decode with invalid input`() {
19+
val decoder = HexDecoder()
20+
assertFailsWith<IllegalArgumentException> {
21+
decoder.decode("This is a test")
22+
}
23+
}
24+
}

0 commit comments

Comments
 (0)