Skip to content

Commit

Permalink
Added more tests.
Browse files Browse the repository at this point in the history
Fixes #5.
  • Loading branch information
morazow committed Oct 26, 2020
1 parent a862122 commit 623c94e
Show file tree
Hide file tree
Showing 9 changed files with 179 additions and 3 deletions.
2 changes: 2 additions & 0 deletions doc/changes/changes_0.1.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
### Runtime Dependency Updates

* Updated `sbt.version` from `1.3.13` to `1.4.1`.
* Added `com.fasterxml.jackson.module:jackson-module-scala` version `2.11.3`.
* Updated `com.fasterxml.jackson.core:jackson-databind` from `2.11.2` to `2.11.3`.

### Test Dependency Updates
Expand All @@ -24,3 +25,4 @@

* Updated `com.github.cb372:sbt-explicit-dependencies` from `0.2.13` to `0.2.15`.
* Updated `org.wartremover:sbt-wartremover` from `2.4.10` to `2.4.11`.
* Updated `org.wartremover:sbt-wartremover-contib` from `1.3.8` to `1.3.9`.
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ addSbtPlugin("org.wartremover" % "sbt-wartremover" % "2.4.11")

// Adds Contrib Warts
// http://github.com/wartremover/wartremover-contrib/
addSbtPlugin("org.wartremover" % "sbt-wartremover-contrib" % "1.3.8")
addSbtPlugin("org.wartremover" % "sbt-wartremover-contrib" % "1.3.9")

// Adds most common doc api mappings
// https://github.com/ThoughtWorksInc/sbt-api-mappings
Expand Down
2 changes: 0 additions & 2 deletions src/main/scala/com/exasol/avro/AvroRow.scala
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ object AvroRow {
case Schema.Type.ARRAY => getArrayValue(value, field)
case Schema.Type.MAP => getMapValue(value, field)
case Schema.Type.RECORD => getRecordValue(value)
case field =>
throw new IllegalArgumentException(s"Avro ${field.getName} type is not supported!")
}
}

Expand Down
1 change: 1 addition & 0 deletions src/main/scala/com/exasol/common/Row.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ final case class Row(protected[data] val values: Seq[Any]) {
*
* If the value is null, null is returned.
*/
@throws[IndexOutOfBoundsException]("When index is out of bounds")
def get(index: Int): Any = values(index)

/** Returns the value at position {@code index} casted to the type. */
Expand Down
21 changes: 21 additions & 0 deletions src/test/scala/com/exasol/avro/AvroComplexTypesTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ class AvroComplexTypesTest extends AnyFunSuite {
assert(AvroRow(record) === Row(Seq(expected)))
}

test("throws unsupported array type") {
val schema = getArraySchema("""{"type":"map", "values":"int"}""")
val record = new GenericData.Record(schema)
record.put("value", JMap.of("k1", 1, "k2", 2, "k3", 3))
val thrown = intercept[IllegalArgumentException] {
AvroRow(record)
}
assert(thrown.getMessage.contains("Unsupported Avro Array type"))
}

test("parse avro map type") {
val schema = getMapSchema("\"int\"")
val record = new GenericData.Record(schema)
Expand Down Expand Up @@ -177,4 +187,15 @@ class AvroComplexTypesTest extends AnyFunSuite {
assert(row.getAs[String](1) === expected)
}

test("throws unsupported record type") {
val schema = getRecordSchema(s"""{"name":"address","type":$addressSchemaString}""")
val record = new GenericData.Record(schema)
record.put("id", 1)
record.put("address", "str")
val thrown = intercept[IllegalArgumentException] {
AvroRow(record)
}
assert(thrown.getMessage.contains("Unsupported Avro Record type"))
}

}
52 changes: 52 additions & 0 deletions src/test/scala/com/exasol/avro/AvroRowIteratorTest.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.exasol.common.avro

import java.io.File

import com.exasol.common.data.Row

import org.apache.avro.SchemaBuilder
import org.apache.avro.file.DataFileReader
import org.apache.avro.file.DataFileWriter
import org.apache.avro.generic._
import org.apache.avro.specific.SpecificDatumWriter
import org.scalatest.BeforeAndAfterEach
import org.scalatest.funsuite.AnyFunSuite

class AvroRowIteratorTest extends AnyFunSuite with BeforeAndAfterEach {

private[this] var record: GenericData.Record = _
private[this] val schema = SchemaBuilder
.record("record")
.fields()
.requiredString("name")
.endRecord()

override final def beforeEach(): Unit = {
record = new GenericData.Record(schema)
record.put("name", "John")
()
}

test("apply returns iterator") {
val file = File.createTempFile("record", "avro")
file.deleteOnExit()
write(file, record)
val reader = new DataFileReader(file, new GenericDatumReader[GenericRecord]())
val iterator = AvroRowIterator(reader)
assert(iterator.hasNext === true)
assert(iterator.next() === Row(Seq("John")))
assert(iterator.hasNext === false)
val thrown = intercept[NoSuchElementException] {
iterator.next()
}
assert(thrown.getMessage === "Avro reader called next on an empty iterator!")
}

private[this] def write[T <: GenericRecord](file: File, record: T): Unit = {
val writer = new DataFileWriter[T](new SpecificDatumWriter[T]())
writer.create(record.getSchema, file)
writer.append(record)
writer.close()
}

}
36 changes: 36 additions & 0 deletions src/test/scala/com/exasol/common/AbstractPropertiesTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,42 @@ class AbstractPropertiesTest extends AnyFunSuite with BeforeAndAfterEach with Mo
verify(metadata, times(1)).getConnection("connection_info")
}

test("parseConnectionInfo returns key value pairs from password") {
properties = Map("CONNECTION_NAME" -> "connection_info")
val metadata = mockMetadata("", "a=secret1;b=secret2")
val result = BaseProperties(properties)
.parseConnectionInfo("username", Option(metadata))
assert(result === Map("a" -> "secret1", "b" -> "secret2"))
verify(metadata, times(1)).getConnection("connection_info")
}

test("parseConnectionInfo returns key value pairs with updated username") {
properties = Map("CONNECTION_NAME" -> "connection_info")
val metadata = mockMetadata("John", "a=secret1;b=secret2")
val result = BaseProperties(properties)
.parseConnectionInfo("username", Option(metadata))
assert(result === Map("username" -> "John", "a" -> "secret1", "b" -> "secret2"))
verify(metadata, times(1)).getConnection("connection_info")
}

test("parseConnectionInfo throws if password does not contain key value pairs") {
properties = Map("CONNECTION_NAME" -> "connection_info")
val metadata = mockMetadata("John", "secret")
val thrown = intercept[IllegalArgumentException] {
BaseProperties(properties).parseConnectionInfo("username", Option(metadata))
}
val expected = "Connection object password does not contain key=value pairs!"
assert(thrown.getMessage === expected)
verify(metadata, times(1)).getConnection("connection_info")
}

private[this] def mockMetadata(username: String, password: String): ExaMetadata = {
val metadata = mock[ExaMetadata]
val connectionInfo = newConnectionInformation(username, password)
when(metadata.getConnection("connection_info")).thenReturn(connectionInfo)
metadata
}

final def newConnectionInformation(
username: String,
password: String
Expand Down
52 changes: 52 additions & 0 deletions src/test/scala/com/exasol/common/RowTest.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.exasol.common.data

import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers

class RowTest extends AnyFunSuite with Matchers {

private[this] val values: Seq[Any] = Seq("value1", 1, 3.14, null)
private[this] val row = Row(values)

test("getValues returns row values") {
assert(row.getValues() === values)
}

test("get value at index") {
assert(row.get(0).isInstanceOf[String])
assert(row.get(0) === "value1")
}

test("getAs[T] value at index") {
assert(row.getAs[String](0) === "value1")
assert(row.getAs[Double](2) === 3.14)
}

test("isNuallAt returns true if null") {
assert(row.isNullAt(3) === true)
assert(row.isNullAt(1) === false)
}

test("equalality check") {
val rowEqual = Row(Seq("value1", 1, 3.14, null))
val rowNotEqual = Row(Seq("value1", 2, 3.14, null))
row shouldEqual rowEqual
row should not equal rowNotEqual
}

test("throws class cast exception") {
val thrown = intercept[ClassCastException] {
row.getAs[Int](0)
}
val expected = "class java.lang.String cannot be cast to class java.lang.Integer"
assert(thrown.getMessage.contains(expected))
}

test("throws index out of bounds") {
val thrown = intercept[IndexOutOfBoundsException] {
row.get(5)
}
assert(thrown.getMessage === "5")
}

}
14 changes: 14 additions & 0 deletions src/test/scala/com/exasol/json/JsonMapperTest.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.exasol.common.json

import org.scalatest.funsuite.AnyFunSuite

class JsonMapperTest extends AnyFunSuite {

test("parse to and from json to internal data type") {
val jsonStr = """{"name":"John","age":30,"skills":["a","b","c"]}"""
val map = JsonMapper.parseJson[Map[String, Any]](jsonStr)
assert(map.get("skills") === Option(Seq("a", "b", "c")))
assert(JsonMapper.toJson(map) === jsonStr)
}

}

0 comments on commit 623c94e

Please sign in to comment.