32
32
import java .util .stream .Stream ;
33
33
34
34
import static org .junit .jupiter .api .Assertions .assertEquals ;
35
+ import static org .junit .jupiter .api .Assertions .assertNull ;
35
36
36
37
public class ShareCoordinatorOffsetsManagerTest {
37
38
@@ -48,16 +49,19 @@ public void setUp() {
48
49
49
50
@ Test
50
51
public void testUpdateStateAddsToInternalState () {
51
- manager .updateState (KEY1 , 0L );
52
+ manager .updateState (KEY1 , 0L , false );
52
53
assertEquals (Optional .empty (), manager .lastRedundantOffset ());
53
54
54
- manager .updateState (KEY1 , 10L );
55
+ manager .updateState (KEY1 , 10L , false );
55
56
assertEquals (Optional .of (10L ), manager .lastRedundantOffset ()); // [0-9] offsets are redundant.
56
57
57
- manager .updateState (KEY2 , 15L );
58
+ manager .updateState (KEY2 , 15L , false );
58
59
assertEquals (Optional .of (10L ), manager .lastRedundantOffset ()); // No update to last redundant after adding 15L so, still 10L.
59
60
60
- assertEquals (10L , manager .curState ().get (KEY1 ));
61
+ manager .updateState (KEY1 , 25L , true );
62
+ assertEquals (Optional .of (15L ), manager .lastRedundantOffset ()); // KEY1 deleted, no longer part of calculation.
63
+
64
+ assertNull (manager .curState ().get (KEY1 ));
61
65
assertEquals (15L , manager .curState ().get (KEY2 ));
62
66
}
63
67
@@ -66,15 +70,21 @@ static class TestTuple {
66
70
final SharePartitionKey key ;
67
71
final long offset ;
68
72
final Optional <Long > expectedOffset ;
73
+ final boolean isDelete ;
69
74
70
- private TestTuple (SharePartitionKey key , long offset , Optional <Long > expectedOffset ) {
75
+ private TestTuple (SharePartitionKey key , long offset , Optional <Long > expectedOffset , boolean isDelete ) {
71
76
this .key = key ;
72
77
this .offset = offset ;
73
78
this .expectedOffset = expectedOffset ;
79
+ this .isDelete = isDelete ;
74
80
}
75
81
76
82
static TestTuple instance (SharePartitionKey key , long offset , Optional <Long > expectedOffset ) {
77
- return new TestTuple (key , offset , expectedOffset );
83
+ return new TestTuple (key , offset , expectedOffset , false );
84
+ }
85
+
86
+ static TestTuple instance (SharePartitionKey key , long offset , Optional <Long > expectedOffset , boolean isDelete ) {
87
+ return new TestTuple (key , offset , expectedOffset , isDelete );
78
88
}
79
89
}
80
90
@@ -96,27 +106,43 @@ static TestTuple instance(SharePartitionKey key, long offset, Optional<Long> exp
96
106
static Stream <ShareOffsetTestHolder > generateNoRedundantStateCases () {
97
107
return Stream .of (
98
108
new ShareOffsetTestHolder (
99
- "no redundant state single key" ,
109
+ "no redundant state single key. " ,
100
110
List .of (
101
111
ShareOffsetTestHolder .TestTuple .instance (KEY1 , 10L , Optional .of (10L ))
102
112
)
103
113
),
104
114
105
115
new ShareOffsetTestHolder (
106
- "no redundant state multiple keys" ,
116
+ "no redundant state single key with delete." ,
117
+ List .of (
118
+ ShareOffsetTestHolder .TestTuple .instance (KEY1 , 10L , Optional .of (10L ), true )
119
+ )
120
+ ),
121
+
122
+ new ShareOffsetTestHolder (
123
+ "no redundant state multiple keys." ,
107
124
List .of (
108
125
ShareOffsetTestHolder .TestTuple .instance (KEY1 , 10L , Optional .of (10L )),
109
126
ShareOffsetTestHolder .TestTuple .instance (KEY4 , 11L , Optional .of (10L )),
110
127
ShareOffsetTestHolder .TestTuple .instance (KEY2 , 13L , Optional .of (10L ))
111
128
)
129
+ ),
130
+
131
+ new ShareOffsetTestHolder (
132
+ "no redundant state multiple keys with delete." ,
133
+ List .of (
134
+ ShareOffsetTestHolder .TestTuple .instance (KEY1 , 10L , Optional .of (10L ), true ),
135
+ ShareOffsetTestHolder .TestTuple .instance (KEY4 , 11L , Optional .of (11L ), true ),
136
+ ShareOffsetTestHolder .TestTuple .instance (KEY2 , 13L , Optional .of (13L ), true )
137
+ )
112
138
)
113
139
);
114
140
}
115
141
116
142
static Stream <ShareOffsetTestHolder > generateRedundantStateCases () {
117
143
return Stream .of (
118
144
new ShareOffsetTestHolder (
119
- "redundant state single key" ,
145
+ "redundant state single key. " ,
120
146
List .of (
121
147
ShareOffsetTestHolder .TestTuple .instance (KEY1 , 10L , Optional .of (10L )),
122
148
ShareOffsetTestHolder .TestTuple .instance (KEY1 , 11L , Optional .of (11L )),
@@ -125,7 +151,7 @@ static Stream<ShareOffsetTestHolder> generateRedundantStateCases() {
125
151
),
126
152
127
153
new ShareOffsetTestHolder (
128
- "redundant state multiple keys" ,
154
+ "redundant state multiple keys. " ,
129
155
// KEY1: 10 17
130
156
// KEY2: 11 16
131
157
// KEY3: 15
@@ -136,6 +162,20 @@ static Stream<ShareOffsetTestHolder> generateRedundantStateCases() {
136
162
ShareOffsetTestHolder .TestTuple .instance (KEY2 , 16L , Optional .of (10L )), // KEY2 11 redundant but should not be returned
137
163
ShareOffsetTestHolder .TestTuple .instance (KEY1 , 17L , Optional .of (15L ))
138
164
)
165
+ ),
166
+
167
+ new ShareOffsetTestHolder (
168
+ "redundant state multiple keys with delete." ,
169
+ // KEY1: 10 17
170
+ // KEY2: 11 16
171
+ // KEY3: 15
172
+ List .of (
173
+ ShareOffsetTestHolder .TestTuple .instance (KEY1 , 10L , Optional .of (10L )),
174
+ ShareOffsetTestHolder .TestTuple .instance (KEY2 , 11L , Optional .of (10L )),
175
+ ShareOffsetTestHolder .TestTuple .instance (KEY3 , 15L , Optional .of (10L ), true ),
176
+ ShareOffsetTestHolder .TestTuple .instance (KEY2 , 16L , Optional .of (10L )), // KEY2 11 redundant but should not be returned
177
+ ShareOffsetTestHolder .TestTuple .instance (KEY1 , 17L , Optional .of (16L )) // Because we have removed KEY3 from calculation
178
+ )
139
179
)
140
180
);
141
181
@@ -144,7 +184,7 @@ static Stream<ShareOffsetTestHolder> generateRedundantStateCases() {
144
184
static Stream <ShareOffsetTestHolder > generateComplexCases () {
145
185
return Stream .of (
146
186
new ShareOffsetTestHolder (
147
- "redundant state reverse key order" ,
187
+ "redundant state reverse key order. " ,
148
188
// Requests come in order KEY1, KEY2, KEY3, KEY3, KEY2, KEY1.
149
189
List .of (
150
190
ShareOffsetTestHolder .TestTuple .instance (KEY1 , 10L , Optional .of (10L )),
@@ -156,6 +196,18 @@ static Stream<ShareOffsetTestHolder> generateComplexCases() {
156
196
)
157
197
),
158
198
199
+ new ShareOffsetTestHolder (
200
+ "redundant state reverse key order with delete." ,
201
+ List .of (
202
+ ShareOffsetTestHolder .TestTuple .instance (KEY1 , 10L , Optional .of (10L )),
203
+ ShareOffsetTestHolder .TestTuple .instance (KEY2 , 11L , Optional .of (10L )),
204
+ ShareOffsetTestHolder .TestTuple .instance (KEY3 , 15L , Optional .of (10L )),
205
+ ShareOffsetTestHolder .TestTuple .instance (KEY3 , 18L , Optional .of (10L ), true ),
206
+ ShareOffsetTestHolder .TestTuple .instance (KEY2 , 20L , Optional .of (10L ), true ),
207
+ ShareOffsetTestHolder .TestTuple .instance (KEY1 , 25L , Optional .of (25L )) // Because KEY2 and KEY3 are gone.
208
+ )
209
+ ),
210
+
159
211
new ShareOffsetTestHolder (
160
212
"redundant state infrequently written partition." ,
161
213
List .of (
@@ -170,6 +222,20 @@ static Stream<ShareOffsetTestHolder> generateComplexCases() {
170
222
ShareOffsetTestHolder .TestTuple .instance (KEY3 , 28L , Optional .of (10L )),
171
223
ShareOffsetTestHolder .TestTuple .instance (KEY1 , 30L , Optional .of (27L ))
172
224
)
225
+ ),
226
+
227
+ new ShareOffsetTestHolder (
228
+ "redundant state infrequently written partition with delete." ,
229
+ List .of (
230
+ ShareOffsetTestHolder .TestTuple .instance (KEY1 , 10L , Optional .of (10L )),
231
+ ShareOffsetTestHolder .TestTuple .instance (KEY2 , 11L , Optional .of (10L )),
232
+ ShareOffsetTestHolder .TestTuple .instance (KEY3 , 15L , Optional .of (10L )),
233
+ ShareOffsetTestHolder .TestTuple .instance (KEY2 , 18L , Optional .of (10L )),
234
+ ShareOffsetTestHolder .TestTuple .instance (KEY3 , 20L , Optional .of (10L ), true ), //KEY3 no longer party to calculation
235
+ ShareOffsetTestHolder .TestTuple .instance (KEY2 , 22L , Optional .of (10L )),
236
+ ShareOffsetTestHolder .TestTuple .instance (KEY2 , 27L , Optional .of (10L ), true ), //KEY2 no longer party to calculation
237
+ ShareOffsetTestHolder .TestTuple .instance (KEY1 , 30L , Optional .of (30L ))
238
+ )
173
239
)
174
240
);
175
241
}
@@ -179,7 +245,7 @@ static Stream<ShareOffsetTestHolder> generateComplexCases() {
179
245
public void testUpdateStateNoRedundantState (ShareOffsetTestHolder holder ) {
180
246
if (holder .shouldRun ) {
181
247
holder .tuples .forEach (tuple -> {
182
- manager .updateState (tuple .key , tuple .offset );
248
+ manager .updateState (tuple .key , tuple .offset , tuple . isDelete );
183
249
assertEquals (tuple .expectedOffset , manager .lastRedundantOffset (), holder .testName );
184
250
});
185
251
}
@@ -190,7 +256,7 @@ public void testUpdateStateNoRedundantState(ShareOffsetTestHolder holder) {
190
256
public void testUpdateStateRedundantState (ShareOffsetTestHolder holder ) {
191
257
if (holder .shouldRun ) {
192
258
holder .tuples .forEach (tuple -> {
193
- manager .updateState (tuple .key , tuple .offset );
259
+ manager .updateState (tuple .key , tuple .offset , tuple . isDelete );
194
260
assertEquals (tuple .expectedOffset , manager .lastRedundantOffset (), holder .testName );
195
261
});
196
262
}
@@ -201,9 +267,9 @@ public void testUpdateStateRedundantState(ShareOffsetTestHolder holder) {
201
267
public void testUpdateStateComplexCases (ShareOffsetTestHolder holder ) {
202
268
if (holder .shouldRun ) {
203
269
holder .tuples .forEach (tuple -> {
204
- manager .updateState (tuple .key , tuple .offset );
270
+ manager .updateState (tuple .key , tuple .offset , tuple . isDelete );
205
271
assertEquals (tuple .expectedOffset , manager .lastRedundantOffset (), holder .testName );
206
272
});
207
273
}
208
274
}
209
- }
275
+ }
0 commit comments