|
23 | 23 | import org.elasticsearch.client.internal.support.AbstractClient; |
24 | 24 | import org.elasticsearch.common.BackoffPolicy; |
25 | 25 | import org.elasticsearch.common.bytes.BytesArray; |
| 26 | +import org.elasticsearch.common.bytes.BytesReference; |
| 27 | +import org.elasticsearch.common.document.DocumentField; |
26 | 28 | import org.elasticsearch.common.settings.Settings; |
27 | 29 | import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException; |
| 30 | +import org.elasticsearch.common.xcontent.XContentHelper; |
28 | 31 | import org.elasticsearch.core.TimeValue; |
29 | 32 | import org.elasticsearch.index.reindex.ClientScrollableHitSource; |
30 | 33 | import org.elasticsearch.index.reindex.ScrollableHitSource; |
|
38 | 41 | import org.junit.After; |
39 | 42 | import org.junit.Before; |
40 | 43 |
|
| 44 | +import java.util.HashMap; |
41 | 45 | import java.util.List; |
| 46 | +import java.util.Map; |
42 | 47 | import java.util.concurrent.ArrayBlockingQueue; |
43 | 48 | import java.util.concurrent.BlockingQueue; |
44 | 49 | import java.util.concurrent.TimeUnit; |
@@ -159,6 +164,129 @@ public void testScrollKeepAlive() { |
159 | 164 | client.validateRequest(TransportSearchScrollAction.TYPE, (SearchScrollRequest r) -> assertEquals(r.scroll().seconds(), 110)); |
160 | 165 | } |
161 | 166 |
|
| 167 | + public void testGenerateSourceWithFields() { |
| 168 | + // Test case: source exists and fields should be merged |
| 169 | + SearchHit hit = SearchHit.unpooled(0, "id"); |
| 170 | + hit.sourceRef(new BytesArray("{\"existing_field\":\"existing_value\"}")); |
| 171 | + |
| 172 | + Map<String, DocumentField> fields = new HashMap<>(); |
| 173 | + fields.put("single_value_field", new DocumentField("single_value_field", List.of("single_value"))); |
| 174 | + fields.put("multi_value_field", new DocumentField("multi_value_field", List.of("value1", "value2"))); |
| 175 | + fields.put("existing_field", new DocumentField("existing_field", List.of("new_value"))); |
| 176 | + hit.addDocumentFields(fields, new HashMap<>()); |
| 177 | + |
| 178 | + BytesReference result = ClientScrollableHitSource.generateSource(hit); |
| 179 | + Map<String, Object> resultSource = XContentHelper.convertToMap(result, false, XContentHelper.xContentType(result)).v2(); |
| 180 | + |
| 181 | + // Verify source contains all expected fields |
| 182 | + assertEquals("existing_value", resultSource.get("existing_field")); // existing field should not be overwritten |
| 183 | + assertEquals("single_value", resultSource.get("single_value_field")); |
| 184 | + assertEquals(List.of("value1", "value2"), resultSource.get("multi_value_field")); |
| 185 | + } |
| 186 | + |
| 187 | + public void testGenerateSourceWithEmptyFields() { |
| 188 | + // Test case: fields is empty |
| 189 | + SearchHit hit = SearchHit.unpooled(0, "id"); |
| 190 | + hit.sourceRef(new BytesArray("{\"field1\":\"value1\",\"field2\":\"value2\"}")); |
| 191 | + hit.addDocumentFields(new HashMap<>(), new HashMap<>()); |
| 192 | + |
| 193 | + BytesReference result = ClientScrollableHitSource.generateSource(hit); |
| 194 | + Map<String, Object> resultSource = XContentHelper.convertToMap(result, false, XContentHelper.xContentType(result)).v2(); |
| 195 | + |
| 196 | + // Source should remain unchanged |
| 197 | + assertEquals("value1", resultSource.get("field1")); |
| 198 | + assertEquals("value2", resultSource.get("field2")); |
| 199 | + } |
| 200 | + |
| 201 | + public void testGenerateSourceWithEmptySource() { |
| 202 | + // Test case: source is empty, fields exist |
| 203 | + SearchHit hit = SearchHit.unpooled(0, "id"); |
| 204 | + hit.sourceRef(new BytesArray("{}")); |
| 205 | + |
| 206 | + Map<String, DocumentField> fields = new HashMap<>(); |
| 207 | + fields.put("field1", new DocumentField("field1", List.of("value1"))); |
| 208 | + fields.put("field2", new DocumentField("field2", List.of("value2", "value3"))); |
| 209 | + hit.addDocumentFields(fields, new HashMap<>()); |
| 210 | + |
| 211 | + BytesReference result = ClientScrollableHitSource.generateSource(hit); |
| 212 | + Map<String, Object> resultSource = XContentHelper.convertToMap(result, false, XContentHelper.xContentType(result)).v2(); |
| 213 | + |
| 214 | + assertEquals("value1", resultSource.get("field1")); |
| 215 | + assertEquals(List.of("value2", "value3"), resultSource.get("field2")); |
| 216 | + } |
| 217 | + |
| 218 | + public void testGenerateSourceWithBothEmpty() { |
| 219 | + // Test case: both source and fields are empty |
| 220 | + SearchHit hit = SearchHit.unpooled(0, "id"); |
| 221 | + hit.sourceRef(new BytesArray("{}")); |
| 222 | + hit.addDocumentFields(new HashMap<>(), new HashMap<>()); |
| 223 | + |
| 224 | + BytesReference result = ClientScrollableHitSource.generateSource(hit); |
| 225 | + Map<String, Object> resultSource = XContentHelper.convertToMap(result, false, XContentHelper.xContentType(result)).v2(); |
| 226 | + |
| 227 | + assertTrue(resultSource.isEmpty()); |
| 228 | + } |
| 229 | + |
| 230 | + public void testGenerateSourceWithComplexSource() { |
| 231 | + // Test case: complex source with nested objects |
| 232 | + SearchHit hit = SearchHit.unpooled(0, "id"); |
| 233 | + hit.sourceRef(new BytesArray("{\"nested\":{\"field1\":\"value1\"}}")); |
| 234 | + |
| 235 | + Map<String, DocumentField> fields = new HashMap<>(); |
| 236 | + fields.put("new_field", new DocumentField("new_field", List.of("value2"))); |
| 237 | + hit.addDocumentFields(fields, new HashMap<>()); |
| 238 | + |
| 239 | + BytesReference result = ClientScrollableHitSource.generateSource(hit); |
| 240 | + Map<String, Object> resultSource = XContentHelper.convertToMap(result, false, XContentHelper.xContentType(result)).v2(); |
| 241 | + |
| 242 | + @SuppressWarnings("unchecked") |
| 243 | + Map<String, Object> nested = (Map<String, Object>) resultSource.get("nested"); |
| 244 | + assertEquals("value1", nested.get("field1")); |
| 245 | + assertEquals("value2", resultSource.get("new_field")); |
| 246 | + } |
| 247 | + |
| 248 | + public void testGenerateSourceWithNoSource() { |
| 249 | + // Test case: no source, only fields |
| 250 | + SearchHit hit = SearchHit.unpooled(0, "id"); |
| 251 | + hit.sourceRef(null); |
| 252 | + |
| 253 | + Map<String, DocumentField> fields = new HashMap<>(); |
| 254 | + fields.put("field1", new DocumentField("field1", List.of("value1"))); |
| 255 | + hit.addDocumentFields(fields, new HashMap<>()); |
| 256 | + |
| 257 | + BytesReference result = ClientScrollableHitSource.generateSource(hit); |
| 258 | + Map<String, Object> resultSource = XContentHelper.convertToMap(result, false, XContentHelper.xContentType(result)).v2(); |
| 259 | + |
| 260 | + // Source value should be preserved |
| 261 | + assertEquals("value1", resultSource.get("field1")); |
| 262 | + } |
| 263 | + |
| 264 | + public void testGenerateSourceWithNoSourceAndNoFields() { |
| 265 | + // Test case: no source and no fields |
| 266 | + SearchHit hit = SearchHit.unpooled(0, "id"); |
| 267 | + hit.sourceRef(null); |
| 268 | + hit.addDocumentFields(new HashMap<>(), new HashMap<>()); |
| 269 | + |
| 270 | + BytesReference result = ClientScrollableHitSource.generateSource(hit); |
| 271 | + assertNull(result); |
| 272 | + } |
| 273 | + |
| 274 | + public void testGenerateSourceWithExistingFieldInSource() { |
| 275 | + // Test case: field already exists in source |
| 276 | + SearchHit hit = SearchHit.unpooled(0, "id"); |
| 277 | + hit.sourceRef(new BytesArray("{\"field1\":\"source_value\"}")); |
| 278 | + |
| 279 | + Map<String, DocumentField> fields = new HashMap<>(); |
| 280 | + fields.put("field1", new DocumentField("field1", List.of("field_value"))); |
| 281 | + hit.addDocumentFields(fields, new HashMap<>()); |
| 282 | + |
| 283 | + BytesReference result = ClientScrollableHitSource.generateSource(hit); |
| 284 | + Map<String, Object> resultSource = XContentHelper.convertToMap(result, false, XContentHelper.xContentType(result)).v2(); |
| 285 | + |
| 286 | + // Source value should be preserved |
| 287 | + assertEquals("source_value", resultSource.get("field1")); |
| 288 | + } |
| 289 | + |
162 | 290 | private SearchResponse createSearchResponse() { |
163 | 291 | // create a simulated response. |
164 | 292 | SearchHit hit = SearchHit.unpooled(0, "id").sourceRef(new BytesArray("{}")); |
|
0 commit comments