private def avroValueOf()

in ratatool-scalacheck/src/main/scala/com/spotify/ratatool/scalacheck/AvroGenerator.scala [137:288]


  private def avroValueOf(schema: Schema)(implicit
    data: GenericData,
    stringableGens: Map[Class[_], Gen[_]] = Map.empty
  ): Gen[Any] = {
    import scala.jdk.CollectionConverters._

    val conversion = for {
      logicalType <- Option(schema.getLogicalType)
      conversion <- Option(data.getConversionFor(logicalType))
    } yield conversion

    schema.getType match {
      case Schema.Type.RECORD =>
        val recordData = data match {
          case specificData: SpecificData => dataForClass(specificData.getClass(schema))
          case _                          => data
        }

        val record = for {
          fields <- Gen.sequence[List[(Int, Any)], (Int, Any)](schema.getFields.asScala.map { f =>
            avroValueOf(f.schema())(recordData, stringableGens).map(v => f.pos() -> v)
          })
        } yield fields.foldLeft(recordData.newRecord(null, schema).asInstanceOf[IndexedRecord]) {
          case (r, (idx, v)) =>
            r.put(idx, v)
            r
        }
        conversion match {
          case Some(c) => record.map(r => c.fromRecord(r, schema, schema.getLogicalType))
          case None    => record
        }

      case Schema.Type.UNION =>
        val types = schema.getTypes.asScala
        for {
          i <- Gen.choose(0, types.size - 1)
          t <- avroValueOf(types(i))
        } yield t

      case Schema.Type.ARRAY =>
        import org.scalacheck.util.Buildable._
        implicit val tt: util.ArrayList[Any] => Traversable[Any] = _.asScala
        val array = Gen.containerOf[util.ArrayList, Any](avroValueOf(schema.getElementType))
        conversion match {
          case Some(c) => array.map(a => c.fromArray(a, schema, schema.getLogicalType))
          case None    => array
        }

      case Schema.Type.ENUM =>
        for {
          symbol <- Gen.oneOf(schema.getEnumSymbols.asScala)
        } yield conversion match {
          case Some(c) =>
            val enumSymbol = new GenericData.EnumSymbol(schema, symbol)
            c.fromEnumSymbol(enumSymbol, schema, schema.getLogicalType)
          case None =>
            data.createEnum(symbol, schema)
        }

      case Schema.Type.MAP =>
        import HashMapBuildable._
        Option(schema.getProp(SpecificData.KEY_CLASS_PROP)) match {
          case Some(cls) =>
            Gen.buildableOf[util.HashMap[Any, Any], (Any, Any)](
              (genStringable(cls), avroValueOf(schema.getValueType)).tupled
            )
          case None =>
            val map = Gen.buildableOf[util.HashMap[CharSequence, Any], (CharSequence, Any)](
              (genAvroString(schema), avroValueOf(schema.getValueType)).tupled
            )
            conversion match {
              case Some(c) => map.map(m => c.fromMap(m, schema, schema.getLogicalType))
              case None    => map
            }
        }

      case Schema.Type.FIXED =>
        for {
          bytes <- Gen.listOfN(schema.getFixedSize, Arbitrary.arbByte.arbitrary).map(_.toArray)
        } yield conversion match {
          case Some(c) =>
            val fixed = new GenericData.Fixed(schema, bytes)
            c.fromFixed(fixed, schema, schema.getLogicalType)
          case None => data.createFixed(null, bytes, schema)
        }

      case Schema.Type.STRING =>
        Option(schema.getProp(SpecificData.CLASS_PROP)) match {
          case Some(cls) => genStringable(cls)
          case None =>
            val str = genAvroString(schema)
            conversion match {
              case Some(c) => str.map(cs => c.fromCharSequence(cs, schema, schema.getLogicalType))
              case None    => str
            }
        }

      case Schema.Type.BYTES =>
        val bytes = for {
          n <- boundedLengthGen
          bs <- Gen.listOfN(n, Arbitrary.arbByte.arbitrary)
        } yield ByteBuffer.wrap(bs.toArray)
        conversion match {
          case Some(c) =>
            val bs = schema.getLogicalType match {
              case dt: LogicalTypes.Decimal =>
                // we can't convert random bytes
                val max = BigInt(10).pow(dt.getPrecision) - 1
                Gen.choose(-max, max).map(bs => ByteBuffer.wrap(bs.toByteArray))
              case _ =>
                bytes
            }
            bs.map(b => c.asInstanceOf[Conversion[Any]].fromBytes(b, schema, schema.getLogicalType))
          case None => bytes
        }

      case Schema.Type.INT =>
        val int = Arbitrary.arbInt.arbitrary
        conversion match {
          case Some(c) => int.map(i => c.fromInt(i, schema, schema.getLogicalType))
          case None    => int
        }
      case Schema.Type.LONG =>
        val long = Arbitrary.arbLong.arbitrary
        conversion match {
          case Some(c) => long.map(l => c.fromLong(l, schema, schema.getLogicalType))
          case None    => long
        }

      case Schema.Type.FLOAT =>
        val float = Arbitrary.arbFloat.arbitrary
        conversion match {
          case Some(c) => float.map(f => c.fromFloat(f, schema, schema.getLogicalType))
          case None    => float
        }

      case Schema.Type.DOUBLE =>
        val double = Arbitrary.arbDouble.arbitrary
        conversion match {
          case Some(c) => double.map(d => c.fromDouble(d, schema, schema.getLogicalType))
          case None    => double
        }

      case Schema.Type.BOOLEAN =>
        val bool = Arbitrary.arbBool.arbitrary
        conversion match {
          case Some(c) => bool.map(b => c.fromBoolean(b, schema, schema.getLogicalType))
          case None    => bool
        }

      case Schema.Type.NULL => Gen.const(null)
    }