Skip to content

Commit 7a56d8a

Browse files
fix: make RoktOptions properties immutable by copying input collections and Added test cases
1 parent 4a57cd6 commit 7a56d8a

2 files changed

Lines changed: 195 additions & 3 deletions

File tree

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package com.mparticle.rokt
22

33
class RoktOptions @JvmOverloads constructor(
4-
val fontFilePathMap: Map<String, String> = emptyMap(),
5-
val fontPostScriptNames: Set<String> = emptySet()
6-
)
4+
fontFilePathMap: Map<String, String> = emptyMap(),
5+
fontPostScriptNames: Set<String> = emptySet()
6+
) {
7+
val fontFilePathMap: Map<String, String> = fontFilePathMap.toMap()
8+
val fontPostScriptNames: Set<String> = fontPostScriptNames.toSet()
9+
}
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
package com.mparticle.rokt
2+
3+
import org.junit.Assert.assertEquals
4+
import org.junit.Assert.assertFalse
5+
import org.junit.Assert.assertNotEquals
6+
import org.junit.Assert.assertNull
7+
import org.junit.Assert.assertTrue
8+
import org.junit.Test
9+
10+
class RoktOptionsTest {
11+
12+
@Test
13+
fun testDefaultConstructor_shouldCreateEmptyOptions() {
14+
val roktOptions = RoktOptions()
15+
16+
assertTrue("fontFilePathMap should be empty", roktOptions.fontFilePathMap.isEmpty())
17+
assertTrue("fontPostScriptNames should be empty", roktOptions.fontPostScriptNames.isEmpty())
18+
}
19+
20+
@Test
21+
fun testConstructorWithFontFilePathMap_shouldSetCorrectValues() {
22+
val fontMap = mapOf(
23+
"font1" to "/path/to/font1.ttf",
24+
"font2" to "/path/to/font2.otf"
25+
)
26+
27+
val roktOptions = RoktOptions(fontFilePathMap = fontMap)
28+
29+
assertEquals("fontFilePathMap should match", fontMap, roktOptions.fontFilePathMap)
30+
assertTrue("fontPostScriptNames should be empty", roktOptions.fontPostScriptNames.isEmpty())
31+
assertEquals("Should have 2 font files", 2, roktOptions.fontFilePathMap.size)
32+
assertEquals("Should contain font1 path", "/path/to/font1.ttf", roktOptions.fontFilePathMap["font1"])
33+
assertEquals("Should contain font2 path", "/path/to/font2.otf", roktOptions.fontFilePathMap["font2"])
34+
}
35+
36+
@Test
37+
fun testConstructorWithFontPostScriptNames_shouldSetCorrectValues() {
38+
val fontNames = setOf(
39+
"Arial-Bold",
40+
"Helvetica-Light",
41+
"CustomFont-Regular"
42+
)
43+
44+
val roktOptions = RoktOptions(fontPostScriptNames = fontNames)
45+
46+
assertTrue("fontFilePathMap should be empty", roktOptions.fontFilePathMap.isEmpty())
47+
assertEquals("fontPostScriptNames should match", fontNames, roktOptions.fontPostScriptNames)
48+
assertEquals("Should have 3 font names", 3, roktOptions.fontPostScriptNames.size)
49+
assertTrue("Should contain Arial-Bold", roktOptions.fontPostScriptNames.contains("Arial-Bold"))
50+
assertTrue("Should contain Helvetica-Light", roktOptions.fontPostScriptNames.contains("Helvetica-Light"))
51+
assertTrue("Should contain CustomFont-Regular", roktOptions.fontPostScriptNames.contains("CustomFont-Regular"))
52+
}
53+
54+
@Test
55+
fun testConstructorWithBothParameters_shouldSetBothValues() {
56+
val fontMap = mapOf("font1" to "/path/to/font1.ttf")
57+
val fontNames = setOf("Arial-Bold")
58+
59+
val roktOptions = RoktOptions(
60+
fontFilePathMap = fontMap,
61+
fontPostScriptNames = fontNames
62+
)
63+
64+
assertEquals("fontFilePathMap should match", fontMap, roktOptions.fontFilePathMap)
65+
assertEquals("fontPostScriptNames should match", fontNames, roktOptions.fontPostScriptNames)
66+
assertEquals("Should have 1 font file", 1, roktOptions.fontFilePathMap.size)
67+
assertEquals("Should have 1 font name", 1, roktOptions.fontPostScriptNames.size)
68+
}
69+
70+
@Test
71+
fun testConstructorWithEmptyCollections_shouldCreateEmptyOptions() {
72+
val roktOptions = RoktOptions(
73+
fontFilePathMap = emptyMap(),
74+
fontPostScriptNames = emptySet()
75+
)
76+
77+
assertTrue("fontFilePathMap should be empty", roktOptions.fontFilePathMap.isEmpty())
78+
assertTrue("fontPostScriptNames should be empty", roktOptions.fontPostScriptNames.isEmpty())
79+
}
80+
81+
@Test
82+
fun testFontFilePathMapImmutability_shouldNotAllowModification() {
83+
val mutableMap = mutableMapOf("font1" to "/path/to/font1.ttf")
84+
val roktOptions = RoktOptions(fontFilePathMap = mutableMap)
85+
86+
// Modify the original map
87+
mutableMap["font2"] = "/path/to/font2.ttf"
88+
89+
// The RoktOptions should not be affected if the implementation is correct
90+
assertEquals("RoktOptions should have 1 font file", 1, roktOptions.fontFilePathMap.size)
91+
assertFalse("RoktOptions should not contain font2", roktOptions.fontFilePathMap.containsKey("font2"))
92+
}
93+
94+
@Test
95+
fun testFontPostScriptNamesImmutability_shouldNotAllowModification() {
96+
val mutableSet = mutableSetOf("Arial-Bold")
97+
val roktOptions = RoktOptions(fontPostScriptNames = mutableSet)
98+
99+
// Modify the original set
100+
mutableSet.add("Helvetica-Light")
101+
102+
// The RoktOptions should not be affected if the implementation is correct
103+
assertEquals("RoktOptions should have 1 font name", 1, roktOptions.fontPostScriptNames.size)
104+
assertFalse("RoktOptions should not contain Helvetica-Light", roktOptions.fontPostScriptNames.contains("Helvetica-Light"))
105+
}
106+
107+
@Test
108+
fun testMultipleInstances_shouldBeIndependent() {
109+
val fontMap1 = mapOf("font1" to "/path1")
110+
val fontMap2 = mapOf("font2" to "/path2")
111+
112+
val roktOptions1 = RoktOptions(fontFilePathMap = fontMap1)
113+
val roktOptions2 = RoktOptions(fontFilePathMap = fontMap2)
114+
115+
assertNotEquals("Instances should be different", roktOptions1.fontFilePathMap, roktOptions2.fontFilePathMap)
116+
assertEquals("First instance should have font1", "/path1", roktOptions1.fontFilePathMap["font1"])
117+
assertEquals("Second instance should have font2", "/path2", roktOptions2.fontFilePathMap["font2"])
118+
assertNull("First instance should not have font2", roktOptions1.fontFilePathMap["font2"])
119+
assertNull("Second instance should not have font1", roktOptions2.fontFilePathMap["font1"])
120+
}
121+
122+
@Test
123+
fun testLargeCollections_shouldHandleCorrectly() {
124+
val largeFontMap = (1..100).associate { "font$it" to "/path/to/font$it.ttf" }
125+
val largeFontNames = (1..100).map { "Font-$it" }.toSet()
126+
127+
val roktOptions = RoktOptions(
128+
fontFilePathMap = largeFontMap,
129+
fontPostScriptNames = largeFontNames
130+
)
131+
132+
assertEquals("Should have 100 font files", 100, roktOptions.fontFilePathMap.size)
133+
assertEquals("Should have 100 font names", 100, roktOptions.fontPostScriptNames.size)
134+
assertEquals("Should contain first font file", "/path/to/font1.ttf", roktOptions.fontFilePathMap["font1"])
135+
assertEquals("Should contain last font file", "/path/to/font100.ttf", roktOptions.fontFilePathMap["font100"])
136+
assertTrue("Should contain first font name", roktOptions.fontPostScriptNames.contains("Font-1"))
137+
assertTrue("Should contain last font name", roktOptions.fontPostScriptNames.contains("Font-100"))
138+
}
139+
140+
@Test
141+
fun testEquality_sameParameters_shouldBeEqual() {
142+
val fontMap = mapOf("font1" to "/path1")
143+
val fontNames = setOf("Arial-Bold")
144+
145+
val roktOptions1 = RoktOptions(fontFilePathMap = fontMap, fontPostScriptNames = fontNames)
146+
val roktOptions2 = RoktOptions(fontFilePathMap = fontMap, fontPostScriptNames = fontNames)
147+
148+
// Note: Kotlin data classes would provide equals() automatically, but since RoktOptions
149+
// is not a data class, we test the property values individually
150+
assertEquals("fontFilePathMap should be equal", roktOptions1.fontFilePathMap, roktOptions2.fontFilePathMap)
151+
assertEquals("fontPostScriptNames should be equal", roktOptions1.fontPostScriptNames, roktOptions2.fontPostScriptNames)
152+
}
153+
154+
@Test
155+
fun testSpecialCharactersInPaths_shouldHandleCorrectly() {
156+
val fontMap = mapOf(
157+
"font with spaces" to "/path with spaces/font file.ttf",
158+
"font-with-dashes" to "/path-with-dashes/font-file.ttf",
159+
"font_with_underscores" to "/path_with_underscores/font_file.ttf",
160+
"fontWithUnicode" to "/path/with/unicode/字体.ttf"
161+
)
162+
163+
val roktOptions = RoktOptions(fontFilePathMap = fontMap)
164+
165+
assertEquals("Should handle spaces", "/path with spaces/font file.ttf", roktOptions.fontFilePathMap["font with spaces"])
166+
assertEquals("Should handle dashes", "/path-with-dashes/font-file.ttf", roktOptions.fontFilePathMap["font-with-dashes"])
167+
assertEquals("Should handle underscores", "/path_with_underscores/font_file.ttf", roktOptions.fontFilePathMap["font_with_underscores"])
168+
assertEquals("Should handle unicode", "/path/with/unicode/字体.ttf", roktOptions.fontFilePathMap["fontWithUnicode"])
169+
}
170+
171+
@Test
172+
fun testSpecialCharactersInFontNames_shouldHandleCorrectly() {
173+
val fontNames = setOf(
174+
"Arial-Bold",
175+
"Helvetica_Light",
176+
"Font With Spaces",
177+
"Font.With.Dots",
178+
"字体名称" // Unicode font name
179+
)
180+
181+
val roktOptions = RoktOptions(fontPostScriptNames = fontNames)
182+
183+
assertTrue("Should contain Arial-Bold", roktOptions.fontPostScriptNames.contains("Arial-Bold"))
184+
assertTrue("Should contain Helvetica_Light", roktOptions.fontPostScriptNames.contains("Helvetica_Light"))
185+
assertTrue("Should contain Font With Spaces", roktOptions.fontPostScriptNames.contains("Font With Spaces"))
186+
assertTrue("Should contain Font.With.Dots", roktOptions.fontPostScriptNames.contains("Font.With.Dots"))
187+
assertTrue("Should contain unicode font name", roktOptions.fontPostScriptNames.contains("字体名称"))
188+
}
189+
}

0 commit comments

Comments
 (0)