From 95095ed870116ebcfb9759a3ab04d7679989f5c5 Mon Sep 17 00:00:00 2001 From: Koert Kuipers Date: Tue, 9 Jul 2019 13:24:19 -0400 Subject: [PATCH] fix unit tests by have lambdas implement concrete classes --- .../salesforce/op/dsl/RichDateFeature.scala | 12 ++- .../salesforce/op/dsl/RichTextFeature.scala | 53 ++++++++++-- .../impl/feature/ToOccurTransformer.scala | 14 ++-- .../op/OpWorkflowModelReaderWriterTest.scala | 12 ++- .../com/salesforce/op/stages/Lambdas.scala | 79 +++++++++++------ .../op/stages/OpPipelineStagesTest.scala | 6 +- .../DropIndicesByTransformerTest.scala | 6 +- .../base/binary/BinaryTransformerTest.scala | 6 +- .../QuaternaryTransformerTest.scala | 10 ++- .../BinarySequenceTransformerTest.scala | 8 +- .../sequence/SequenceTransformerTest.scala | 6 +- .../base/ternary/TernaryTransformerTest.scala | 8 +- .../base/unary/UnaryTransformerTest.scala | 6 +- .../op/test/PassengerFeaturesTest.scala | 84 +++++++++++++++---- 14 files changed, 239 insertions(+), 71 deletions(-) diff --git a/core/src/main/scala/com/salesforce/op/dsl/RichDateFeature.scala b/core/src/main/scala/com/salesforce/op/dsl/RichDateFeature.scala index ee8d1f1e20..55ea8e7a26 100644 --- a/core/src/main/scala/com/salesforce/op/dsl/RichDateFeature.scala +++ b/core/src/main/scala/com/salesforce/op/dsl/RichDateFeature.scala @@ -204,7 +204,15 @@ trait RichDateFeature { } object RichDateFeatureLambdas { - def toDateList: Date => DateList = (x: Date) => x.value.toSeq.toDateList + private class ToDateList extends Function1[Date, DateList] with Serializable { + def apply(x: Date): DateList = x.value.toSeq.toDateList + } + + private class ToDateTimeList extends Function1[DateTime, DateTimeList] with Serializable { + def apply(x: DateTime): DateTimeList = x.value.toSeq.toDateTimeList + } + + def toDateList: Date => DateList = new ToDateList - def toDateTimeList: DateTime => DateTimeList = (x: DateTime) => x.value.toSeq.toDateTimeList + def toDateTimeList: DateTime => DateTimeList = new ToDateTimeList } diff --git a/core/src/main/scala/com/salesforce/op/dsl/RichTextFeature.scala b/core/src/main/scala/com/salesforce/op/dsl/RichTextFeature.scala index fa175d8153..dd1f05ba2e 100644 --- a/core/src/main/scala/com/salesforce/op/dsl/RichTextFeature.scala +++ b/core/src/main/scala/com/salesforce/op/dsl/RichTextFeature.scala @@ -800,23 +800,58 @@ trait RichTextFeature { } object RichTextFeatureLambdas { + private class EmailToPickList extends Function1[Email, PickList] with Serializable { + def apply(v: Email): PickList = v.domain.toPickList + } + + private class EmailToPrefix extends Function1[Email, Text] with Serializable { + def apply(v: Email): Text = v.prefix.toText + } + + private class EmailToDomain extends Function1[Email, Text] with Serializable { + def apply(v: Email): Text = v.domain.toText + } + + private class UrlToPickList extends Function1[URL, PickList] with Serializable { + def apply(v: URL): PickList = if (v.isValid) v.domain.toPickList else PickList.empty + } + + private class UrlToDomain extends Function1[URL, Text] with Serializable { + def apply(v: URL): Text = v.domain.toText + } + + private class UrlToProtocol extends Function1[URL, Text] with Serializable { + def apply(v: URL): Text = v.protocol.toText + } + + private class UrlIsValid extends Function1[URL, Boolean] with Serializable { + def apply(v: URL): Boolean = v.isValid + } + + private class TextToPickList extends Function1[Text, PickList] with Serializable { + def apply(v: Text): PickList = v.value.toPickList + } + + private class TextToMultiPickList extends Function1[Text, MultiPickList] with Serializable { + def apply(v: Text): MultiPickList = v.value.toSet[String].toMultiPickList + } - def emailToPickList: Email => PickList = _.domain.toPickList + def emailToPickList: Email => PickList = new EmailToPickList - def emailToPrefix: Email => Text = _.prefix.toText + def emailToPrefix: Email => Text = new EmailToPrefix - def emailToDomain: Email => Text = _.domain.toText + def emailToDomain: Email => Text = new EmailToDomain - def urlToPickList: URL => PickList = (v: URL) => if (v.isValid) v.domain.toPickList else PickList.empty + def urlToPickList: URL => PickList = new UrlToPickList - def urlToDomain: URL => Text = _.domain.toText + def urlToDomain: URL => Text = new UrlToDomain - def urlToProtocol: URL => Text = _.protocol.toText + def urlToProtocol: URL => Text = new UrlToProtocol - def urlIsValid: URL => Boolean = _.isValid + def urlIsValid: URL => Boolean = new UrlIsValid - def textToPickList: Text => PickList = _.value.toPickList + def textToPickList: Text => PickList = new TextToPickList - def textToMultiPickList: Text => MultiPickList = _.value.toSet[String].toMultiPickList + def textToMultiPickList: Text => MultiPickList = new TextToMultiPickList } diff --git a/core/src/main/scala/com/salesforce/op/stages/impl/feature/ToOccurTransformer.scala b/core/src/main/scala/com/salesforce/op/stages/impl/feature/ToOccurTransformer.scala index 066e780a58..cbaffceb9d 100644 --- a/core/src/main/scala/com/salesforce/op/stages/impl/feature/ToOccurTransformer.scala +++ b/core/src/main/scala/com/salesforce/op/stages/impl/feature/ToOccurTransformer.scala @@ -59,12 +59,14 @@ class ToOccurTransformer[I <: FeatureType] object ToOccurTransformer { - - def defaultMatches[T <: FeatureType]: T => Boolean = { - case num: OPNumeric[_] if num.nonEmpty => num.toDouble.get > 0.0 - case text: Text if text.nonEmpty => text.value.get.length > 0 - case collection: OPCollection => collection.nonEmpty - case _ => false + private class DefaultMatches[T <: FeatureType] extends Function1[T, Boolean] with Serializable { + def apply(t: T): Boolean = t match { + case num: OPNumeric[_] if num.nonEmpty => num.toDouble.get > 0.0 + case text: Text if text.nonEmpty => text.value.get.length > 0 + case collection: OPCollection => collection.nonEmpty + case _ => false + } } + def defaultMatches[T <: FeatureType]: T => Boolean = new DefaultMatches[T] } diff --git a/core/src/test/scala/com/salesforce/op/OpWorkflowModelReaderWriterTest.scala b/core/src/test/scala/com/salesforce/op/OpWorkflowModelReaderWriterTest.scala index d65b5c2352..c4266a03b8 100644 --- a/core/src/test/scala/com/salesforce/op/OpWorkflowModelReaderWriterTest.scala +++ b/core/src/test/scala/com/salesforce/op/OpWorkflowModelReaderWriterTest.scala @@ -386,6 +386,14 @@ trait UIDReset { } object OpWorkflowModelReaderWriterTest { - def catHeadFn: OPVector => Real = v => Real(v.value.toArray.headOption) - def emptyVectorFn: Passenger => OPVector = _ => OPVector.empty + private class CatHeadFn extends Function1[OPVector, Real] with Serializable { + def apply(v: OPVector): Real = Real(v.value.toArray.headOption) + } + + private class EmptyVectorFn extends Function1[Passenger, OPVector] with Serializable { + def apply(p: Passenger): OPVector = OPVector.empty + } + + def catHeadFn: OPVector => Real = new CatHeadFn + def emptyVectorFn: Passenger => OPVector = new EmptyVectorFn } diff --git a/core/src/test/scala/com/salesforce/op/stages/Lambdas.scala b/core/src/test/scala/com/salesforce/op/stages/Lambdas.scala index 9ffb467bd8..129a94527f 100644 --- a/core/src/test/scala/com/salesforce/op/stages/Lambdas.scala +++ b/core/src/test/scala/com/salesforce/op/stages/Lambdas.scala @@ -34,38 +34,65 @@ import com.salesforce.op.features.types.Real import com.salesforce.op.features.types._ object Lambdas { - def fncUnary: Real => Real = (x: Real) => x.v.map(_ * 0.1234).toReal + private class FncUnary extends Function1[Real, Real] with Serializable { + def apply(x: Real): Real = x.v.map(_ * 0.1234).toReal + } + + private class FncSequence extends Function1[Seq[DateList], Real] with Serializable { + def apply(x: Seq[DateList]): Real = { + val v = x.foldLeft(0.0)((a, b) => a + b.value.sum) + Math.round(v / 1E6).toReal + } + } + + private class FncBinarySequence extends Function2[Real, Seq[DateList], Real] with Serializable { + def apply(y: Real, x: Seq[DateList]): Real = { + val v = x.foldLeft(0.0)((a, b) => a + b.value.sum) + (Math.round(v / 1E6) + y.value.getOrElse(0.0)).toReal + } + } - def fncSequence: Seq[DateList] => Real = (x: Seq[DateList]) => { - val v = x.foldLeft(0.0)((a, b) => a + b.value.sum) - Math.round(v / 1E6).toReal + private class FncBinary extends Function2[Real, Real, Real] with Serializable { + def apply(y: Real, x: Real): Real = { + ( + for { + yv <- y.value + xv <- x.value + } yield xv * yv + ).toReal + } } - def fncBinarySequence: (Real, Seq[DateList]) => Real = (y: Real, x: Seq[DateList]) => { - val v = x.foldLeft(0.0)((a, b) => a + b.value.sum) - (Math.round(v / 1E6) + y.value.getOrElse(0.0)).toReal + private class FncTernary extends Function3[Real, Real, Real, Real] with Serializable { + def apply(x: Real, y: Real, z: Real): Real = { + (for { + xv <- x.value + yv <- y.value + zv <- z.value + } yield xv * yv + zv).toReal + } } - def fncBinary: (Real, Real) => Real = (x: Real, y: Real) => ( - for { - yv <- y.value - xv <- x.value - } yield xv * yv - ).toReal + private class FncQuaternary extends Function4[Real, Real, Text, Real, Real] with Serializable { + def apply(x: Real, y: Real, t: Text, z: Real): Real = { + (for { + xv <- x.value + yv <- y.value + tv <- t.value + zv <- z.value + } yield xv * yv + zv * tv.length).toReal + } + } + + def fncUnary: Real => Real = new FncUnary + + def fncSequence: Seq[DateList] => Real = new FncSequence + + def fncBinarySequence: (Real, Seq[DateList]) => Real = new FncBinarySequence - def fncTernary: (Real, Real, Real) => Real = (x: Real, y: Real, z: Real) => - (for { - xv <- x.value - yv <- y.value - zv <- z.value - } yield xv * yv + zv).toReal + def fncBinary: (Real, Real) => Real = new FncBinary - def fncQuaternary: (Real, Real, Text, Real) => Real = (x: Real, y: Real, t: Text, z: Real) => - (for { - xv <- x.value - yv <- y.value - tv <- t.value - zv <- z.value - } yield xv * yv + zv * tv.length).toReal + def fncTernary: (Real, Real, Real) => Real = new FncTernary + def fncQuaternary: (Real, Real, Text, Real) => Real = new FncQuaternary } diff --git a/core/src/test/scala/com/salesforce/op/stages/OpPipelineStagesTest.scala b/core/src/test/scala/com/salesforce/op/stages/OpPipelineStagesTest.scala index 8e7c862f56..4a30de1f05 100644 --- a/core/src/test/scala/com/salesforce/op/stages/OpPipelineStagesTest.scala +++ b/core/src/test/scala/com/salesforce/op/stages/OpPipelineStagesTest.scala @@ -162,7 +162,11 @@ class OpPipelineStagesTest } object OpPipelineStagesTest { - def fnc0: Real => Real = x => x + private class Fnc0 extends Function1[Real, Real] with Serializable { + def apply(x: Real): Real = x + } + + def fnc0: Real => Real = new Fnc0 class TestStage(implicit val tto: TypeTag[RealNN], val ttov: TypeTag[RealNN#Value]) extends Pipeline with OpPipelineStage1[RealNN, RealNN] { diff --git a/core/src/test/scala/com/salesforce/op/stages/impl/feature/DropIndicesByTransformerTest.scala b/core/src/test/scala/com/salesforce/op/stages/impl/feature/DropIndicesByTransformerTest.scala index c0d0116630..387e6097ba 100644 --- a/core/src/test/scala/com/salesforce/op/stages/impl/feature/DropIndicesByTransformerTest.scala +++ b/core/src/test/scala/com/salesforce/op/stages/impl/feature/DropIndicesByTransformerTest.scala @@ -116,5 +116,9 @@ class DropIndicesByTransformerTest extends OpTransformerSpec[OPVector, DropIndic } object DropIndicesByTransformerTest { - def matchFn: OpVectorColumnMetadata => Boolean = _.isNullIndicator + private class MatchFn extends Function1[OpVectorColumnMetadata, Boolean] with Serializable { + def apply(x: OpVectorColumnMetadata): Boolean = x.isNullIndicator + } + + def matchFn: OpVectorColumnMetadata => Boolean = new MatchFn } diff --git a/features/src/test/scala/com/salesforce/op/stages/base/binary/BinaryTransformerTest.scala b/features/src/test/scala/com/salesforce/op/stages/base/binary/BinaryTransformerTest.scala index d92ef5641f..fa72d4fb31 100644 --- a/features/src/test/scala/com/salesforce/op/stages/base/binary/BinaryTransformerTest.scala +++ b/features/src/test/scala/com/salesforce/op/stages/base/binary/BinaryTransformerTest.scala @@ -51,5 +51,9 @@ class BinaryTransformerTest extends OpTransformerSpec[Real, BinaryTransformer[Re } object BinaryTransformerTest { - def fn: (Real, RealNN) => Real = (i1, i2) => new Real(for {v1 <- i1.value; v2 <- i2.value} yield v1 / (v2 * v2)) + private class Fn extends Function2[Real, RealNN, Real] with Serializable { + def apply(i1: Real, i2: RealNN): Real = new Real(for {v1 <- i1.value; v2 <- i2.value} yield v1 / (v2 * v2)) + } + + def fn: (Real, RealNN) => Real = new Fn } diff --git a/features/src/test/scala/com/salesforce/op/stages/base/quaternary/QuaternaryTransformerTest.scala b/features/src/test/scala/com/salesforce/op/stages/base/quaternary/QuaternaryTransformerTest.scala index 0e029e8d55..bb20d4b613 100644 --- a/features/src/test/scala/com/salesforce/op/stages/base/quaternary/QuaternaryTransformerTest.scala +++ b/features/src/test/scala/com/salesforce/op/stages/base/quaternary/QuaternaryTransformerTest.scala @@ -57,7 +57,11 @@ class QuaternaryTransformerTest } object QuaternaryTransformerTest { - def fn: (Real, Integral, Text, Binary) => Real = (r, i, t, b) => - (r.v.getOrElse(0.0) + i.toDouble.getOrElse(0.0) + b.toDouble.getOrElse(0.0) + - t.value.map(_.length.toDouble).getOrElse(0.0)).toReal + private class Fn extends Function4[Real, Integral, Text, Binary, Real] with Serializable { + def apply(r: Real, i: Integral, t: Text, b: Binary): Real = + (r.v.getOrElse(0.0) + i.toDouble.getOrElse(0.0) + b.toDouble.getOrElse(0.0) + + t.value.map(_.length.toDouble).getOrElse(0.0)).toReal + } + + def fn: (Real, Integral, Text, Binary) => Real = new Fn } diff --git a/features/src/test/scala/com/salesforce/op/stages/base/sequence/BinarySequenceTransformerTest.scala b/features/src/test/scala/com/salesforce/op/stages/base/sequence/BinarySequenceTransformerTest.scala index 6ec1bca0fc..6254e78bca 100644 --- a/features/src/test/scala/com/salesforce/op/stages/base/sequence/BinarySequenceTransformerTest.scala +++ b/features/src/test/scala/com/salesforce/op/stages/base/sequence/BinarySequenceTransformerTest.scala @@ -62,6 +62,10 @@ class BinarySequenceTransformerTest } object Lambda { - def fn: (Real, Seq[Text]) => MultiPickList = - (r, texts) => MultiPickList(texts.map(_.value.get).toSet + r.value.get.toString) + class Fn extends Function2[Real, Seq[Text], MultiPickList] with Serializable { + def apply(r: Real, texts: Seq[Text]): MultiPickList = + MultiPickList(texts.map(_.value.get).toSet + r.value.get.toString) + } + + def fn: (Real, Seq[Text]) => MultiPickList = new Fn } diff --git a/features/src/test/scala/com/salesforce/op/stages/base/sequence/SequenceTransformerTest.scala b/features/src/test/scala/com/salesforce/op/stages/base/sequence/SequenceTransformerTest.scala index a03e3b1ec3..aaf1a840f9 100644 --- a/features/src/test/scala/com/salesforce/op/stages/base/sequence/SequenceTransformerTest.scala +++ b/features/src/test/scala/com/salesforce/op/stages/base/sequence/SequenceTransformerTest.scala @@ -61,5 +61,9 @@ class SequenceTransformerTest extends OpTransformerSpec[MultiPickList, SequenceT } object SequenceTransformerTest { - def fn: Seq[Real] => MultiPickList = value => MultiPickList(value.flatMap(_.v.map(_.toString)).toSet) + private class Fn extends Function1[Seq[Real], MultiPickList] with Serializable { + def apply(value: Seq[Real]): MultiPickList = MultiPickList(value.flatMap(_.v.map(_.toString)).toSet) + } + + def fn: Seq[Real] => MultiPickList = new Fn } diff --git a/features/src/test/scala/com/salesforce/op/stages/base/ternary/TernaryTransformerTest.scala b/features/src/test/scala/com/salesforce/op/stages/base/ternary/TernaryTransformerTest.scala index 26bdd38533..551f289872 100644 --- a/features/src/test/scala/com/salesforce/op/stages/base/ternary/TernaryTransformerTest.scala +++ b/features/src/test/scala/com/salesforce/op/stages/base/ternary/TernaryTransformerTest.scala @@ -56,6 +56,10 @@ class TernaryTransformerTest extends OpTransformerSpec[Real, TernaryTransformer[ } object Lambda { - def fn: (Real, Integral, Binary) => Real = - (r, i, b) => (r.v.getOrElse(0.0) + i.toDouble.getOrElse(0.0) + b.toDouble.getOrElse(0.0)).toReal + private class Fn extends Function3[Real, Integral, Binary, Real] with Serializable { + def apply(r: Real, i: Integral, b: Binary): Real = + (r.v.getOrElse(0.0) + i.toDouble.getOrElse(0.0) + b.toDouble.getOrElse(0.0)).toReal + } + + def fn: (Real, Integral, Binary) => Real = new Fn } diff --git a/features/src/test/scala/com/salesforce/op/stages/base/unary/UnaryTransformerTest.scala b/features/src/test/scala/com/salesforce/op/stages/base/unary/UnaryTransformerTest.scala index d7cbbfcccc..814834b558 100644 --- a/features/src/test/scala/com/salesforce/op/stages/base/unary/UnaryTransformerTest.scala +++ b/features/src/test/scala/com/salesforce/op/stages/base/unary/UnaryTransformerTest.scala @@ -59,5 +59,9 @@ class UnaryTransformerTest extends OpTransformerSpec[Real, UnaryLambdaTransforme } object UnaryTransformerTest { - def fn: Real => Real = r => r.v.map(_ * 2.0).toReal + private class Fn extends Function1[Real, Real] with Serializable { + def apply(r: Real): Real = r.v.map(_ * 2.0).toReal + } + + def fn: Real => Real = new Fn } diff --git a/readers/src/main/scala/com/salesforce/op/test/PassengerFeaturesTest.scala b/readers/src/main/scala/com/salesforce/op/test/PassengerFeaturesTest.scala index 975bbf567a..76c65ed7ed 100644 --- a/readers/src/main/scala/com/salesforce/op/test/PassengerFeaturesTest.scala +++ b/readers/src/main/scala/com/salesforce/op/test/PassengerFeaturesTest.scala @@ -60,18 +60,74 @@ trait PassengerFeaturesTest { } object PassengerFeaturesTestLambdas { - def genderFn: Passenger => MultiPickList = p => Set(p.getGender).toMultiPickList - def genderPLFn: Passenger => PickList = p => p.getGender.toPickList - def heightFn: Passenger => RealNN = p => Option(p.getHeight).map(_.toDouble).toRealNN(0.0) - def heightToReal: Passenger => Real = _.getHeight.toReal - def weightToReal: Passenger => Real = _.getWeight.toReal - def descriptionFn: Passenger => Text = _.getDescription.toText - def boardedToDL: Passenger => DateList = p => Seq(p.getBoarded.toLong).toDateList - def stringMapFn: Passenger => TextMap = p => p.getStringMap.toTextMap - def numericMapFn: Passenger => RealMap = p => p.getNumericMap.toRealMap - def booleanMapFn: Passenger => BinaryMap = p => p.getBooleanMap.toBinaryMap - def survivedFn: Passenger => Binary = p => Option(p.getSurvived).map(_ == 1).toBinary - def boardedTimeFn: Passenger => Date = _.getBoarded.toLong.toDate - def boardedDTFn: Passenger => DateTime = _.getBoarded.toLong.toDateTime - def ageFn: Passenger => Real = _.getAge.toReal + private class GenderFn extends Function1[Passenger, MultiPickList] with Serializable { + def apply(p: Passenger): MultiPickList = Set(p.getGender).toMultiPickList + } + + private class GenderPLFn extends Function1[Passenger, PickList] with Serializable { + def apply(p: Passenger): PickList = p.getGender.toPickList + } + + private class HeightFn extends Function1[Passenger, RealNN] with Serializable { + def apply(p: Passenger): RealNN = Option(p.getHeight).map(_.toDouble).toRealNN(0.0) + } + + private class HeightToReal extends Function1[Passenger, Real] with Serializable { + def apply(p: Passenger): Real = p.getHeight.toReal + } + + private class WeightToReal extends Function1[Passenger, Real] with Serializable { + def apply(p: Passenger): Real = p.getWeight.toReal + } + + private class DescriptionFn extends Function1[Passenger, Text] with Serializable { + def apply(p: Passenger): Text = p.getDescription.toText + } + + private class BoardedToDL extends Function1[Passenger, DateList] with Serializable { + def apply(p: Passenger): DateList = Seq(p.getBoarded.toLong).toDateList + } + + private class StringMapFn extends Function1[Passenger, TextMap] with Serializable { + def apply(p: Passenger): TextMap = p.getStringMap.toTextMap + } + + private class NumericMapFn extends Function1[Passenger, RealMap] with Serializable { + def apply(p: Passenger): RealMap = p.getNumericMap.toRealMap + } + + private class BooleanMapFn extends Function1[Passenger, BinaryMap] with Serializable { + def apply(p: Passenger): BinaryMap = p.getBooleanMap.toBinaryMap + } + + private class SurvivedFn extends Function1[Passenger, Binary] with Serializable { + def apply(p: Passenger): Binary = Option(p.getSurvived).map(_ == 1).toBinary + } + + private class BoardedTimeFn extends Function1[Passenger, Date] with Serializable { + def apply(p: Passenger): Date = p.getBoarded.toLong.toDate + } + + private class BoardedDTFn extends Function1[Passenger, DateTime] with Serializable { + def apply(p: Passenger): DateTime = p.getBoarded.toLong.toDateTime + } + + private class AgeFn extends Function1[Passenger, Real] with Serializable { + def apply(p: Passenger): Real = p.getAge.toReal + } + + def genderFn: Passenger => MultiPickList = new GenderFn + def genderPLFn: Passenger => PickList = new GenderPLFn + def heightFn: Passenger => RealNN = new HeightFn + def heightToReal: Passenger => Real = new HeightToReal + def weightToReal: Passenger => Real = new WeightToReal + def descriptionFn: Passenger => Text = new DescriptionFn + def boardedToDL: Passenger => DateList = new BoardedToDL + def stringMapFn: Passenger => TextMap = new StringMapFn + def numericMapFn: Passenger => RealMap = new NumericMapFn + def booleanMapFn: Passenger => BinaryMap = new BooleanMapFn + def survivedFn: Passenger => Binary = new SurvivedFn + def boardedTimeFn: Passenger => Date = new BoardedTimeFn + def boardedDTFn: Passenger => DateTime = new BoardedDTFn + def ageFn: Passenger => Real = new AgeFn }