Skip to content
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

Moves to 2.10.x as the default and to scalatest #176

Merged
merged 10 commits into from
Aug 29, 2014
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
language: scala
scala:
- 2.10.4
- 2.9.3
- 2.11.2
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import org.apache.avro.generic.{ GenericDatumReader, GenericDatumWriter, Generic
import org.apache.avro.Schema
import org.apache.avro.io.{ DecoderFactory, DatumReader, EncoderFactory, DatumWriter }
import Injection.utf8
import scala.reflect._

/**
* Factory providing various avro injections.
Expand All @@ -37,8 +38,8 @@ object SpecificAvroCodecs {
* @tparam T compiled Avro record
* @return Injection
*/
def apply[T <: SpecificRecordBase: Manifest]: Injection[T, Array[Byte]] = {
val klass = manifest[T].erasure.asInstanceOf[Class[T]]
def apply[T <: SpecificRecordBase: ClassTag]: Injection[T, Array[Byte]] = {
val klass = classTag[T].runtimeClass.asInstanceOf[Class[T]]
new SpecificAvroCodec[T](klass)
}

Expand All @@ -49,8 +50,8 @@ object SpecificAvroCodecs {
* @tparam T compiled Avro record
* @return Injection
*/
def withCompression[T <: SpecificRecordBase: Manifest](codecFactory: CodecFactory): Injection[T, Array[Byte]] = {
val klass = manifest[T].erasure.asInstanceOf[Class[T]]
def withCompression[T <: SpecificRecordBase: ClassTag](codecFactory: CodecFactory): Injection[T, Array[Byte]] = {
val klass = classTag[T].runtimeClass.asInstanceOf[Class[T]]
new SpecificAvroCodec[T](klass, Some(codecFactory))
}

Expand All @@ -60,7 +61,7 @@ object SpecificAvroCodecs {
* @tparam T compiled Avro record
* @return Injection
*/
def withBzip2Compression[T <: SpecificRecordBase: Manifest]: Injection[T, Array[Byte]] =
def withBzip2Compression[T <: SpecificRecordBase: ClassTag]: Injection[T, Array[Byte]] =
withCompression(CodecFactory.bzip2Codec())

/**
Expand All @@ -71,7 +72,7 @@ object SpecificAvroCodecs {
* @tparam T compiled Avro record
* @return Injection
*/
def withDeflateCompression[T <: SpecificRecordBase: Manifest](compressionLevel: Int): Injection[T, Array[Byte]] = {
def withDeflateCompression[T <: SpecificRecordBase: ClassTag](compressionLevel: Int): Injection[T, Array[Byte]] = {
require(1 <= compressionLevel && compressionLevel <= 9, "Compression level should be between 1 and 9, inclusive")
withCompression(CodecFactory.deflateCodec(compressionLevel))
}
Expand All @@ -84,24 +85,24 @@ object SpecificAvroCodecs {
*/
// Allows to create deflate-compressing Injection's without requiring parentheses similar to `apply`,
// `withSnappyCompression`, etc. to achieve API consistency.
def withDeflateCompression[T <: SpecificRecordBase: Manifest]: Injection[T, Array[Byte]] = withDeflateCompression(5)
def withDeflateCompression[T <: SpecificRecordBase: ClassTag]: Injection[T, Array[Byte]] = withDeflateCompression(5)

/**
* Returns Injection capable of serializing and deserializing a compiled Avro record using SpecificDatumWriter and
* SpecificDatumReader. Data is compressed with the Snappy codec.
* @tparam T compiled Avro record
* @return Injection
*/
def withSnappyCompression[T <: SpecificRecordBase: Manifest]: Injection[T, Array[Byte]] =
def withSnappyCompression[T <: SpecificRecordBase: ClassTag]: Injection[T, Array[Byte]] =
withCompression(CodecFactory.snappyCodec())

/**
* Returns Injection capable of serializing and deserializing a compiled avro record using org.apache.avro.io.BinaryEncoder
* @tparam T compiled Avro record
* @return Injection
*/
def toBinary[T <: SpecificRecordBase: Manifest]: Injection[T, Array[Byte]] = {
val klass = manifest[T].erasure.asInstanceOf[Class[T]]
def toBinary[T <: SpecificRecordBase: ClassTag]: Injection[T, Array[Byte]] = {
val klass = classTag[T].runtimeClass.asInstanceOf[Class[T]]
val writer = new SpecificDatumWriter[T](klass)
val reader = new SpecificDatumReader[T](klass)
new BinaryAvroCodec[T](writer, reader)
Expand All @@ -113,8 +114,8 @@ object SpecificAvroCodecs {
* @tparam T compiled Avro record
* @return Injection
*/
def toJson[T <: SpecificRecordBase: Manifest](schema: Schema): Injection[T, String] = {
val klass = manifest[T].erasure.asInstanceOf[Class[T]]
def toJson[T <: SpecificRecordBase: ClassTag](schema: Schema): Injection[T, String] = {
val klass = classTag[T].runtimeClass.asInstanceOf[Class[T]]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we want to just have a method in the package which is the following:

def klass[T](implicit ct: ClassTag[T]): Class[T] = ct.runtimeClass.asInstanceOf[Class[T]]

Not a big deal at all but could get rid of the boilerplate at least.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good to me.

val writer = new SpecificDatumWriter[T](klass)
val reader = new SpecificDatumReader[T](klass)
new JsonAvroCodec[T](schema, writer, reader)
Expand All @@ -139,7 +140,7 @@ object GenericAvroCodecs {
* @tparam T generic record
* @return Injection
*/
def withCompression[T <: GenericRecord: Manifest](schema: Schema, codecFactory: CodecFactory): Injection[T, Array[Byte]] =
def withCompression[T <: GenericRecord: ClassTag](schema: Schema, codecFactory: CodecFactory): Injection[T, Array[Byte]] =
new GenericAvroCodec[T](schema, Some(codecFactory))

/**
Expand All @@ -148,7 +149,7 @@ object GenericAvroCodecs {
* @tparam T generic record
* @return Injection
*/
def withBzip2Compression[T <: GenericRecord: Manifest](schema: Schema): Injection[T, Array[Byte]] =
def withBzip2Compression[T <: GenericRecord: ClassTag](schema: Schema): Injection[T, Array[Byte]] =
withCompression(schema, CodecFactory.bzip2Codec())

/**
Expand All @@ -159,7 +160,7 @@ object GenericAvroCodecs {
* @tparam T generic record
* @return Injection
*/
def withDeflateCompression[T <: GenericRecord: Manifest](schema: Schema, compressionLevel: Int = 5): Injection[T, Array[Byte]] = {
def withDeflateCompression[T <: GenericRecord: ClassTag](schema: Schema, compressionLevel: Int = 5): Injection[T, Array[Byte]] = {
require(1 <= compressionLevel && compressionLevel <= 9, "Compression level should be between 1 and 9, inclusive")
withCompression(schema, CodecFactory.deflateCodec(compressionLevel))
}
Expand All @@ -170,7 +171,7 @@ object GenericAvroCodecs {
* @tparam T generic record
* @return Injection
*/
def withSnappyCompression[T <: GenericRecord: Manifest](schema: Schema): Injection[T, Array[Byte]] =
def withSnappyCompression[T <: GenericRecord: ClassTag](schema: Schema): Injection[T, Array[Byte]] =
withCompression(schema, CodecFactory.snappyCodec())

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@ package com.twitter.bijection.avro

import com.twitter.bijection.{ BaseProperties, Injection }

import org.scalacheck.Properties
import org.scalatest.PropSpec
import org.scalatest.prop.PropertyChecks

import org.apache.avro.generic.{ GenericRecord, GenericData }
import org.apache.avro.Schema

/**
* @author Muhammad Ashraf
* @since 7/5/13
*/
object GenericAvroCodecLaws extends Properties("GenericAvroCodecs") with BaseProperties {
class GenericAvroCodecLaws extends PropSpec with PropertyChecks with BaseProperties {
val testSchema = new Schema.Parser().parse("""{
"type":"record",
"name":"FiscalRecord",
Expand Down Expand Up @@ -71,13 +73,16 @@ object GenericAvroCodecLaws extends Properties("GenericAvroCodecs") with BasePro
isLooseInjection[GenericRecord, String]
}

property("round trips Generic Record -> Array[Byte]") =
property("round trips Generic Record -> Array[Byte]") {
roundTripsGenericRecord(GenericAvroCodecs[GenericRecord](testSchema))
}

property("round trips Generic Record -> Array[Byte] using Binary Encoder/Decoder") =
property("round trips Generic Record -> Array[Byte] using Binary Encoder/Decoder") {
roundTripsGenericRecord(GenericAvroCodecs.toBinary[GenericRecord](testSchema))
}

property("round trips Generic Record -> String using Json Encoder/Decoder") =
property("round trips Generic Record -> String using Json Encoder/Decoder") {
roundTripsGenericRecordToJson(GenericAvroCodecs.toJson[GenericRecord](testSchema))
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ limitations under the License.
*/
package com.twitter.bijection.avro

import org.specs.Specification
import org.scalatest._
import com.twitter.bijection.{ Injection, BaseProperties }
import org.apache.avro.Schema
import avro.FiscalRecord
Expand All @@ -24,7 +24,7 @@ import org.apache.avro.generic.{ GenericData, GenericRecord }
* @author Muhammad Ashraf
* @since 7/6/13
*/
object GenericAvroCodecsSpecification extends Specification with BaseProperties {
object GenericAvroCodecsSpecification extends WordSpec with Matchers with BaseProperties {
val testSchema = new Schema.Parser().parse("""{
"type":"record",
"name":"FiscalRecord",
Expand Down Expand Up @@ -58,63 +58,63 @@ object GenericAvroCodecsSpecification extends Specification with BaseProperties
val testRecord = buildGenericAvroRecord(("2012-01-01", 1, 12))
val bytes = Injection[GenericRecord, Array[Byte]](testRecord)
val attempt = Injection.invert[GenericRecord, Array[Byte]](bytes)
attempt.get must_== testRecord
assert(attempt.get == testRecord)
}

"Round trip generic record using Generic Injection with Bzip2 compression" in {
implicit val genericInjection = GenericAvroCodecs.withBzip2Compression[GenericRecord](testSchema)
val testRecord = buildGenericAvroRecord(("2012-01-01", 1, 12))
val bytes = Injection[GenericRecord, Array[Byte]](testRecord)
val attempt = Injection.invert[GenericRecord, Array[Byte]](bytes)
attempt.get must_== testRecord
assert(attempt.get == testRecord)
}

"Round trip generic record using Generic Injection with Deflate compression (default compression level)" in {
implicit val genericInjection = GenericAvroCodecs.withDeflateCompression[GenericRecord](testSchema)
val testRecord = buildGenericAvroRecord(("2012-01-01", 1, 12))
val bytes = Injection[GenericRecord, Array[Byte]](testRecord)
val attempt = Injection.invert[GenericRecord, Array[Byte]](bytes)
attempt.get must_== testRecord
assert(attempt.get == testRecord)
}

"Round trip generic record using Generic Injection with Deflate compression (custom compression level)" in {
implicit val genericInjection = GenericAvroCodecs.withDeflateCompression[GenericRecord](testSchema, 9)
val testRecord = buildGenericAvroRecord(("2012-01-01", 1, 12))
val bytes = Injection[GenericRecord, Array[Byte]](testRecord)
val attempt = Injection.invert[GenericRecord, Array[Byte]](bytes)
attempt.get must_== testRecord
assert(attempt.get == testRecord)
}

"Cannot create Generic Injection with Deflate compression if compression level is set too low" in {
GenericAvroCodecs.withDeflateCompression[FiscalRecord](testSchema, 0) must throwA[IllegalArgumentException]
an[IllegalArgumentException] should be thrownBy GenericAvroCodecs.withDeflateCompression[FiscalRecord](testSchema, 0)
}

"Cannot create Generic Injection with Deflate compression if compression level is set too high" in {
GenericAvroCodecs.withDeflateCompression[FiscalRecord](testSchema, 10) must throwA[IllegalArgumentException]
an[IllegalArgumentException] should be thrownBy GenericAvroCodecs.withDeflateCompression[FiscalRecord](testSchema, 10)
}

"Round trip generic record using Generic Injection with Snappy compression" in {
implicit val genericInjection = GenericAvroCodecs.withSnappyCompression[GenericRecord](testSchema)
val testRecord = buildGenericAvroRecord(("2012-01-01", 1, 12))
val bytes = Injection[GenericRecord, Array[Byte]](testRecord)
val attempt = Injection.invert[GenericRecord, Array[Byte]](bytes)
attempt.get must_== testRecord
assert(attempt.get == testRecord)
}

"Round trip generic record using Binary Injection" in {
implicit val genericBinaryInjection = GenericAvroCodecs.toBinary[GenericRecord](testSchema)
val testRecord = buildGenericAvroRecord(("2012-01-01", 1, 12))
val bytes = Injection[GenericRecord, Array[Byte]](testRecord)
val attempt = Injection.invert[GenericRecord, Array[Byte]](bytes)
attempt.get must_== testRecord
assert(attempt.get == testRecord)
}

"Round trip generic record using Json Injection" in {
implicit val genericJsonInjection = GenericAvroCodecs.toJson[GenericRecord](testSchema)
val testRecord = buildGenericAvroRecord(("2012-01-01", 1, 12))
val jsonString = Injection[GenericRecord, String](testRecord)
val attempt = Injection.invert[GenericRecord, String](jsonString)
attempt.get must_== testRecord
assert(attempt.get == testRecord)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.twitter.bijection.avro

import org.scalacheck.Properties
import org.scalatest.{ PropSpec, MustMatchers }
import org.scalatest.prop.PropertyChecks
import com.twitter.bijection.{ Injection, BaseProperties }
import org.apache.avro.Schema
import avro.FiscalRecord
Expand All @@ -9,7 +10,7 @@ import avro.FiscalRecord
* @author Muhammad Ashraf
* @since 10/5/13
*/
object SpecificAvroCodecLaws extends Properties("SpecificAvroCodecs") with BaseProperties {
class SpecificAvroCodecLaws extends PropSpec with PropertyChecks with MustMatchers with BaseProperties {
val testSchema = new Schema.Parser().parse("""{
"type":"record",
"name":"FiscalRecord",
Expand Down Expand Up @@ -56,14 +57,17 @@ object SpecificAvroCodecLaws extends Properties("SpecificAvroCodecs") with BaseP
isLooseInjection[FiscalRecord, String]
}

property("round trips Specific Record -> Array[Byte]") =
property("round trips Specific Record -> Array[Byte]") {
roundTripsSpecificRecord(SpecificAvroCodecs[FiscalRecord])
}

property("round trips Specific Record -> Array[Byte] using Binary Encoder/Decoder") =
property("round trips Specific Record -> Array[Byte] using Binary Encoder/Decoder") {
roundTripsSpecificRecord(SpecificAvroCodecs.toBinary[FiscalRecord])
}

property("round trips Specific Record -> String using Json Encoder/Decoder") =
property("round trips Specific Record -> String using Json Encoder/Decoder") {
roundTripsSpecificRecordToJson(SpecificAvroCodecs.toJson[FiscalRecord](testSchema))
}

}

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.twitter.bijection.avro

import org.specs.Specification
import org.scalatest._
import com.twitter.bijection.{ Injection, BaseProperties }
import org.apache.avro.Schema
import avro.FiscalRecord
Expand All @@ -9,7 +9,7 @@ import avro.FiscalRecord
* @author Muhammad Ashraf
* @since 10/5/13
*/
object SpecificAvroCodecsSpecification extends Specification with BaseProperties {
object SpecificAvroCodecsSpecification extends WordSpec with Matchers with BaseProperties {
val testSchema = new Schema.Parser().parse("""{
"type":"record",
"name":"FiscalRecord",
Expand Down Expand Up @@ -43,63 +43,63 @@ object SpecificAvroCodecsSpecification extends Specification with BaseProperties
val testRecord = buildSpecificAvroRecord(("2012-01-01", 1, 12))
val bytes = Injection[FiscalRecord, Array[Byte]](testRecord)
val attempt = Injection.invert[FiscalRecord, Array[Byte]](bytes)
attempt.get must_== testRecord
assert(attempt.get == testRecord)
}

"Round trip specific record using Specific Injection with Bzip2 compression" in {
implicit val specificInjection = SpecificAvroCodecs.withBzip2Compression[FiscalRecord]
val testRecord = buildSpecificAvroRecord(("2012-01-01", 1, 12))
val bytes = Injection[FiscalRecord, Array[Byte]](testRecord)
val attempt = Injection.invert[FiscalRecord, Array[Byte]](bytes)
attempt.get must_== testRecord
assert(attempt.get == testRecord)
}

"Round trip specific record using Specific Injection with Deflate compression (default compression level)" in {
implicit val specificInjection = SpecificAvroCodecs.withDeflateCompression[FiscalRecord]
val testRecord = buildSpecificAvroRecord(("2012-01-01", 1, 12))
val bytes = Injection[FiscalRecord, Array[Byte]](testRecord)
val attempt = Injection.invert[FiscalRecord, Array[Byte]](bytes)
attempt.get must_== testRecord
assert(attempt.get == testRecord)
}

"Round trip specific record using Specific Injection with Deflate compression (custom compression level)" in {
implicit val specificInjection = SpecificAvroCodecs.withDeflateCompression[FiscalRecord](9)
val testRecord = buildSpecificAvroRecord(("2012-01-01", 1, 12))
val bytes = Injection[FiscalRecord, Array[Byte]](testRecord)
val attempt = Injection.invert[FiscalRecord, Array[Byte]](bytes)
attempt.get must_== testRecord
assert(attempt.get == testRecord)
}

"Cannot create Specific Injection with Deflate compression if compression level is set too low" in {
SpecificAvroCodecs.withDeflateCompression[FiscalRecord](0) must throwA[IllegalArgumentException]
an[IllegalArgumentException] should be thrownBy SpecificAvroCodecs.withDeflateCompression[FiscalRecord](0)
}

"Cannot create Specific Injection with Deflate compression if compression level is set too high" in {
SpecificAvroCodecs.withDeflateCompression[FiscalRecord](10) must throwA[IllegalArgumentException]
an[IllegalArgumentException] should be thrownBy SpecificAvroCodecs.withDeflateCompression[FiscalRecord](10)
}

"Round trip specific record using Specific Injection with Snappy compression" in {
implicit val specificInjection = SpecificAvroCodecs.withSnappyCompression[FiscalRecord]
val testRecord = buildSpecificAvroRecord(("2012-01-01", 1, 12))
val bytes = Injection[FiscalRecord, Array[Byte]](testRecord)
val attempt = Injection.invert[FiscalRecord, Array[Byte]](bytes)
attempt.get must_== testRecord
assert(attempt.get == testRecord)
}

"Round trip specific record using Binary Injection" in {
implicit val specificBinaryInjection = SpecificAvroCodecs.toBinary[FiscalRecord]
val testRecord = buildSpecificAvroRecord(("2012-01-01", 1, 12))
val bytes = Injection[FiscalRecord, Array[Byte]](testRecord)
val attempt = Injection.invert[FiscalRecord, Array[Byte]](bytes)
attempt.get must_== testRecord
assert(attempt.get == testRecord)
}

"Round trip specific record using Json Injection" in {
implicit val specificJsonInjection = SpecificAvroCodecs.toJson[FiscalRecord](testSchema)
val testRecord = buildSpecificAvroRecord(("2012-01-01", 1, 12))
val jsonString = Injection[FiscalRecord, String](testRecord)
val attempt = Injection.invert[FiscalRecord, String](jsonString)
attempt.get must_== testRecord
assert(attempt.get == testRecord)
}
}

Expand Down
Loading