-
Notifications
You must be signed in to change notification settings - Fork 8
/
Generators.scala
124 lines (103 loc) · 4.34 KB
/
Generators.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package io.aiven.guardian.kafka.s3
import io.aiven.guardian.kafka.s3.configs.{S3 => S3Config}
import org.apache.pekko.stream.RestartSettings
import org.scalacheck.Gen
import scala.annotation.nowarn
import scala.concurrent.duration._
import scala.language.postfixOps
object Generators {
val MaxBucketLength: Int = 63
// See https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html for valid
// bucketnames
lazy val bucketLetterOrNumberCharGen: Gen[Char] = Gen.frequency(
(1, Gen.numChar),
(1, Gen.alphaLowerChar)
)
def bucketAllCharGen(useVirtualDotHost: Boolean): Gen[Char] = {
val base = List(
(10, Gen.alphaLowerChar),
(1, Gen.const('-')),
(1, Gen.numChar)
)
val frequency = if (useVirtualDotHost) (1, Gen.const('.')) +: base else base
Gen.frequency(frequency: _*)
}
@nowarn("msg=not.*?exhaustive")
private def checkInvalidDuplicateChars(chars: List[Char]): Boolean =
chars.sliding(2).forall { case Seq(before, after) =>
!(before == '.' && after == '.' || before == '-' && after == '.' || before == '.' && after == '-')
}
private def checkAlphaChar(c: Char): Boolean =
c >= 'a' && c <= 'z'
private def allCharCheck(useVirtualDotHost: Boolean, string: String): Boolean =
if (useVirtualDotHost) {
string.forall(char => Character.isDigit(char) || checkAlphaChar(char) || char == '-' || char == '.') &&
checkInvalidDuplicateChars(string.toList)
} else
string.forall(char => Character.isDigit(char) || checkAlphaChar(char) || char == '-')
def validatePrefix(useVirtualDotHost: Boolean, prefix: Option[String]): Option[String] = {
val withoutWhitespace = prefix match {
case Some(value) if value.trim == "" => None
case Some(value) => Some(value)
case None => None
}
withoutWhitespace match {
case Some(value) if !(Character.isDigit(value.head) || checkAlphaChar(value.head)) =>
throw new IllegalArgumentException(
s"Invalid starting digit for prefix $value, ${value.head} needs to be an alpha char or digit"
)
case Some(value) if value.length > 1 =>
if (!allCharCheck(useVirtualDotHost, value.drop(1)))
throw new IllegalArgumentException(
s"Prefix $value contains invalid characters"
)
case Some(value) if value.length > MaxBucketLength - 1 =>
throw new IllegalArgumentException(
s"Prefix is too long, it has size ${value.length} where as the max bucket size is $MaxBucketLength"
)
case _ => ()
}
withoutWhitespace
}
def bucketNameGen(useVirtualDotHost: Boolean, prefix: Option[String] = None): Gen[String] = {
val finalPrefix = validatePrefix(useVirtualDotHost, prefix)
for {
range <- {
val maxLength = finalPrefix match {
case Some(p) => MaxBucketLength - p.length
case None => MaxBucketLength
}
if (maxLength > 3)
Gen.choose(3, maxLength)
else
Gen.const(maxLength)
}
startString = finalPrefix.getOrElse("")
bucketName <- range match {
case 3 =>
for {
first <- bucketLetterOrNumberCharGen
second <- bucketAllCharGen(useVirtualDotHost)
third <- bucketLetterOrNumberCharGen
} yield startString ++ List(first, second, third).mkString
case _ =>
for {
first <- bucketLetterOrNumberCharGen
last <- bucketLetterOrNumberCharGen
middle <- {
val gen = Gen.listOfN(range - 2, bucketAllCharGen(useVirtualDotHost))
if (useVirtualDotHost) gen.filter(checkInvalidDuplicateChars) else gen
}
} yield startString ++ first.toString ++ middle.mkString ++ last.toString
}
} yield bucketName
}
val restartSetting: RestartSettings = RestartSettings(
5 millis,
10 seconds,
0.2
)
def s3ConfigGen(useVirtualDotHost: Boolean, prefix: Option[String] = None): Gen[S3Config] = for {
dataBucket <- bucketNameGen(useVirtualDotHost, prefix)
} yield S3Config(dataBucket, restartSetting)
}