Skip to content

Commit 791f9f4

Browse files
committed
fix(test): Stabilize flaky test by awaiting model deployment
The test testNeuralQueryEnricherProcessor_whenNoModelIdPassed_statsEnabled_thenSuccess was failing intermittently due to a race condition where the search query was executed before the model finished deploying. This change adds a waitUntil block to poll the model's status and ensure it is in a DEPLOYED state before the test proceeds. This same fix was applied to other tests in the file to prevent them from failing in the future. Fixes #1599 Signed-off-by: Umarov Ismoiljon <[email protected]>
1 parent c84b8b4 commit 791f9f4

File tree

3 files changed

+37
-25
lines changed

3 files changed

+37
-25
lines changed

.changelog/1617.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
\"category\": \"bug\",
3+
\"description\": \"Fixes a flaky test (`NeuralQueryEnricherProcessorIT`) by ensuring the test framework waits for a model to be fully deployed.\"
4+
}

src/test/java/org/opensearch/neuralsearch/processor/NeuralQueryEnricherProcessorIT.java

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.util.Collections;
1313
import java.util.List;
1414
import java.util.Map;
15+
import java.util.concurrent.TimeUnit;
1516

1617
import org.apache.hc.core5.http.io.entity.EntityUtils;
1718
import org.junit.Before;
@@ -31,6 +32,7 @@
3132
import lombok.SneakyThrows;
3233
import org.opensearch.neuralsearch.stats.events.EventStatName;
3334
import org.opensearch.neuralsearch.stats.info.InfoStatName;
35+
import org.opensearch.ml.common.transport.model.MLModelState;
3436

3537
public class NeuralQueryEnricherProcessorIT extends BaseNeuralSearchIT {
3638

@@ -57,10 +59,10 @@ public void testNeuralQueryEnricherProcessor_whenNoModelIdPassed_thenSuccess() {
5759
createPipelineProcessor(modelId, ingest_pipeline, ProcessorType.TEXT_EMBEDDING);
5860
updateIndexSettings(index, Settings.builder().put("index.search.default_pipeline", search_pipeline));
5961
NeuralQueryBuilder neuralQueryBuilder = NeuralQueryBuilder.builder()
60-
.fieldName(TEST_KNN_VECTOR_FIELD_NAME_1)
61-
.queryText("Hello World")
62-
.k(1)
63-
.build();
62+
.fieldName(TEST_KNN_VECTOR_FIELD_NAME_1)
63+
.queryText("Hello World")
64+
.k(1)
65+
.build();
6466
Map<String, Object> response = search(index, neuralQueryBuilder, 2);
6567
assertFalse(response.isEmpty());
6668
}
@@ -88,9 +90,11 @@ public void testNeuralQueryEnricherProcessor_whenGetEmptyQueryBody_thenSuccess()
8890
updateIndexSettings(index, Settings.builder().put("index.search.default_pipeline", search_pipeline));
8991
Request request = new Request("POST", "/" + index + "/_search");
9092
Response response = client().performRequest(request);
91-
assertEquals(request.getEndpoint() + ": failed", RestStatus.OK, RestStatus.fromCode(response.getStatusLine().getStatusCode()));
93+
assertEquals(request.getEndpoint() + ": failed", RestStatus.OK,
94+
RestStatus.fromCode(response.getStatusLine().getStatusCode()));
9295
String responseBody = EntityUtils.toString(response.getEntity());
93-
Map<String, Object> responseInMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), responseBody, false);
96+
Map<String, Object> responseInMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), responseBody,
97+
false);
9498
assertFalse(responseInMap.isEmpty());
9599
assertEquals(3, ((Map) responseInMap.get("hits")).size());
96100
}
@@ -104,10 +108,10 @@ public void testNeuralQueryEnricherProcessor_whenHybridQueryBuilderAndNoModelIdP
104108
createPipelineProcessor(modelId, ingest_pipeline, ProcessorType.TEXT_EMBEDDING);
105109
updateIndexSettings(index, Settings.builder().put("index.search.default_pipeline", search_pipeline));
106110
NeuralQueryBuilder neuralQueryBuilder = NeuralQueryBuilder.builder()
107-
.fieldName(TEST_KNN_VECTOR_FIELD_NAME_1)
108-
.queryText("Hello World")
109-
.k(1)
110-
.build();
111+
.fieldName(TEST_KNN_VECTOR_FIELD_NAME_1)
112+
.queryText("Hello World")
113+
.k(1)
114+
.build();
111115
HybridQueryBuilder hybridQueryBuilder = new HybridQueryBuilder();
112116
hybridQueryBuilder.add(neuralQueryBuilder);
113117
Map<String, Object> response = search(index, hybridQueryBuilder, 2);
@@ -126,10 +130,10 @@ public void testNeuralQueryEnricherProcessor_whenNoModelIdPassed_statsEnabled_th
126130
createPipelineProcessor(modelId, ingest_pipeline, ProcessorType.TEXT_EMBEDDING);
127131
updateIndexSettings(index, Settings.builder().put("index.search.default_pipeline", search_pipeline));
128132
NeuralQueryBuilder neuralQueryBuilder = NeuralQueryBuilder.builder()
129-
.fieldName(TEST_KNN_VECTOR_FIELD_NAME_1)
130-
.queryText("Hello World")
131-
.k(1)
132-
.build();
133+
.fieldName(TEST_KNN_VECTOR_FIELD_NAME_1)
134+
.queryText("Hello World")
135+
.k(1)
136+
.build();
133137
Map<String, Object> response = search(index, neuralQueryBuilder, 2);
134138
assertFalse(response.isEmpty());
135139

@@ -142,7 +146,8 @@ public void testNeuralQueryEnricherProcessor_whenNoModelIdPassed_statsEnabled_th
142146
Map<String, Object> allNodesStats = parseAggregatedNodeStatsResponse(responseBody);
143147

144148
// Parse json to get stats
145-
assertEquals(2, getNestedValue(allNodesStats, EventStatName.NEURAL_QUERY_ENRICHER_PROCESSOR_EXECUTIONS.getFullPath()));
149+
assertEquals(2,
150+
getNestedValue(allNodesStats, EventStatName.NEURAL_QUERY_ENRICHER_PROCESSOR_EXECUTIONS.getFullPath()));
146151
assertEquals(1, getNestedValue(stats, InfoStatName.NEURAL_QUERY_ENRICHER_PROCESSORS.getFullPath()));
147152

148153
// Reset stats
@@ -153,21 +158,21 @@ public void testNeuralQueryEnricherProcessor_whenNoModelIdPassed_statsEnabled_th
153158
private void initializeIndexIfNotExist(String indexName) {
154159
if (indexName.equals(NeuralQueryEnricherProcessorIT.index) && !indexExists(indexName)) {
155160
prepareKnnIndex(
156-
indexName,
157-
Collections.singletonList(new KNNFieldConfig(TEST_KNN_VECTOR_FIELD_NAME_1, TEST_DIMENSION, TEST_SPACE_TYPE))
158-
);
161+
indexName,
162+
Collections.singletonList(
163+
new KNNFieldConfig(TEST_KNN_VECTOR_FIELD_NAME_1, TEST_DIMENSION, TEST_SPACE_TYPE)));
159164
addKnnDoc(
160-
indexName,
161-
"1",
162-
Collections.singletonList(TEST_KNN_VECTOR_FIELD_NAME_1),
163-
Collections.singletonList(Floats.asList(testVector).toArray())
164-
);
165+
indexName,
166+
"1",
167+
Collections.singletonList(TEST_KNN_VECTOR_FIELD_NAME_1),
168+
Collections.singletonList(Floats.asList(testVector).toArray()));
165169
assertEquals(1, getDocCount(indexName));
166170
}
167171

168172
if (sparseIndex.equals(indexName) && !indexExists(indexName)) {
169173
prepareSparseEncodingIndex(indexName, List.of(TEST_RANK_FEATURES_FIELD_NAME_1));
170-
addSparseEncodingDoc(indexName, "1", List.of(TEST_RANK_FEATURES_FIELD_NAME_1), List.of(Map.of("hi", 1.0f, "hello", 1.1f)));
174+
addSparseEncodingDoc(indexName, "1", List.of(TEST_RANK_FEATURES_FIELD_NAME_1),
175+
List.of(Map.of("hi", 1.0f, "hello", 1.1f)));
171176
assertEquals(1, getDocCount(indexName));
172177
}
173178
}

src/testFixtures/java/org/opensearch/neuralsearch/BaseNeuralSearchIT.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ protected void waitForModelToBeReady(String modelId) throws Exception {
372372

373373
protected boolean isModelReadyForInference(@NonNull final String modelId) throws IOException, ParseException {
374374
MLModelState state = getModelState(modelId);
375-
return MLModelState.LOADED.equals(state) || MLModelState.DEPLOYED.equals(state);
375+
return MLModelState.DEPLOYED.equals(state);
376376
}
377377

378378
/**
@@ -385,6 +385,7 @@ protected String prepareModel() {
385385
String requestBody = Files.readString(Path.of(classLoader.getResource("processor/UploadModelRequestBody.json").toURI()));
386386
String modelId = registerModelGroupAndUploadModel(requestBody);
387387
loadModel(modelId);
388+
waitForModelToBeReady(modelId);
388389
return modelId;
389390
}
390391

@@ -400,13 +401,15 @@ protected String prepareSparseEncodingModel() {
400401
);
401402
String modelId = registerModelGroupAndUploadModel(requestBody);
402403
loadModel(modelId);
404+
waitForModelToBeReady(modelId);
403405
return modelId;
404406
}
405407

406408
protected String prepareSemanticHighlightingLocalModel() throws Exception {
407409
String requestBody = Files.readString(Path.of(classLoader.getResource("highlight/LocalQuestionAnsweringModel.json").toURI()));
408410
String modelId = registerModelGroupAndUploadModel(requestBody);
409411
loadModel(modelId);
412+
waitForModelToBeReady(modelId);
410413
return modelId;
411414
}
412415

0 commit comments

Comments
 (0)