Skip to content

Commit 00607c7

Browse files
author
Lingxi Chen
committed
Add autotagging rule integration tests
1 parent a6b1849 commit 00607c7

File tree

3 files changed

+302
-1
lines changed

3 files changed

+302
-1
lines changed

modules/autotagging-commons/build.gradle

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
* compatible open source license.
77
*/
88

9+
apply plugin: 'opensearch.internal-cluster-test'
10+
911
opensearchplugin {
1012
name = "rule-framework"
1113
description = 'OpenSearch Rule Framework plugin'
@@ -15,7 +17,17 @@ opensearchplugin {
1517
dependencies {
1618
api project("spi")
1719
api project("common")
20+
1821
testImplementation(project(":test:framework")) {
1922
exclude group: 'org.opensearch', module: 'opensearch-core'
2023
}
24+
25+
internalClusterTestImplementation(project(":test:framework")) {
26+
exclude group: 'org.opensearch', module: 'server'
27+
}
28+
}
29+
30+
tasks.named("internalClusterTest").configure {
31+
// TODO: these run faster with C2 only because they run for so, so long
32+
jvmArgs -= '-XX:TieredStopAtLevel=1'
2133
}

modules/autotagging-commons/common/src/main/java/org/opensearch/rule/action/UpdateRuleResponse.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
6464
/**
6565
* rule getter
6666
*/
67-
Rule getRule() {
67+
public Rule getRule() {
6868
return rule;
6969
}
7070
}
Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.rule;
10+
11+
import org.opensearch.action.support.clustermanager.AcknowledgedResponse;
12+
import org.opensearch.core.action.ActionListener;
13+
import org.opensearch.rule.action.CreateRuleRequest;
14+
import org.opensearch.rule.action.CreateRuleResponse;
15+
import org.opensearch.rule.action.DeleteRuleRequest;
16+
import org.opensearch.rule.action.GetRuleRequest;
17+
import org.opensearch.rule.action.GetRuleResponse;
18+
import org.opensearch.rule.action.UpdateRuleRequest;
19+
import org.opensearch.rule.action.UpdateRuleResponse;
20+
import org.opensearch.rule.autotagging.Attribute;
21+
import org.opensearch.rule.autotagging.FeatureType;
22+
import org.opensearch.rule.autotagging.Rule;
23+
import org.opensearch.test.OpenSearchTestCase;
24+
25+
import java.util.List;
26+
import java.util.Map;
27+
import java.util.Set;
28+
29+
public class AutoTaggingIT extends OpenSearchTestCase {
30+
31+
private final FeatureType featureType = new TestFeatureType();
32+
private final RulePersistenceService persistenceService = new TestRulePersistenceService();
33+
34+
public void testCreateRulePersistence() {
35+
Rule rule = buildRule("create-id", "create-rule", "logs-*");
36+
CreateRuleRequest request = new CreateRuleRequest(rule);
37+
TestActionListener<CreateRuleResponse> listener = new TestActionListener<>();
38+
39+
persistenceService.createRule(request, listener);
40+
41+
assertTrue(listener.successCalled);
42+
assertEquals("create-id", listener.result.getRule().getId());
43+
}
44+
45+
public void testUpdateRulePersistence() {
46+
Rule rule = buildRule("update-id", "updated rule", "metrics-*");
47+
UpdateRuleRequest request = new UpdateRuleRequest(
48+
rule.getId(),
49+
rule.getDescription(),
50+
rule.getAttributeMap(),
51+
rule.getFeatureValue(),
52+
rule.getFeatureType()
53+
);
54+
TestActionListener<UpdateRuleResponse> listener = new TestActionListener<>();
55+
56+
persistenceService.updateRule(request, listener);
57+
58+
assertTrue(listener.successCalled);
59+
assertEquals("update-id", listener.result.getRule().getId());
60+
assertEquals("updated rule", listener.result.getRule().getDescription());
61+
}
62+
63+
public void testGetRulePersistence() {
64+
GetRuleRequest request = new GetRuleRequest("get-id", Map.of(), null, featureType);
65+
66+
TestActionListener<GetRuleResponse> listener = new TestActionListener<>();
67+
68+
persistenceService.getRule(request, listener);
69+
70+
assertTrue(listener.successCalled);
71+
assertNotNull(listener.result);
72+
assertEquals(0, listener.result.getRules().size());
73+
}
74+
75+
public void testDeleteRulePersistence() {
76+
DeleteRuleRequest request = new DeleteRuleRequest("delete-id", featureType);
77+
TestActionListener<AcknowledgedResponse> listener = new TestActionListener<>();
78+
79+
persistenceService.deleteRule(request, listener);
80+
81+
assertTrue(listener.successCalled);
82+
assertTrue(listener.result.isAcknowledged());
83+
}
84+
85+
public void testGetRuleWithAttributeFilters() {
86+
Attribute attr = featureType.getAttributeFromName("index_pattern");
87+
Map<Attribute, Set<String>> filters = Map.of(attr, Set.of("logs-*"));
88+
89+
GetRuleRequest request = new GetRuleRequest("some-id", filters, null, featureType);
90+
TestActionListener<GetRuleResponse> listener = new TestActionListener<>();
91+
92+
persistenceService.getRule(request, listener);
93+
94+
assertTrue(listener.successCalled);
95+
assertNotNull(listener.result);
96+
}
97+
98+
public void testUpdateRuleWithEmptyDescriptionShouldFail() {
99+
Rule rule = null;
100+
try {
101+
rule = buildRule("bad-id", "", "data-*");
102+
fail("Expected ValidationException due to empty description");
103+
} catch (IllegalArgumentException e) {
104+
assertTrue(e.getMessage().contains("Rule description can't be null or empty"));
105+
}
106+
}
107+
108+
public void testDeleteRuleWithNulls() {
109+
DeleteRuleRequest request = new DeleteRuleRequest(null, featureType);
110+
TestActionListener<AcknowledgedResponse> listener = new TestActionListener<>();
111+
112+
persistenceService.deleteRule(request, listener);
113+
assertTrue(listener.successCalled);
114+
}
115+
116+
public void testCreateThenUpdateThenGet() {
117+
Rule rule = buildRule("roundtrip-id", "initial", "index-*");
118+
119+
CreateRuleRequest createRequest = new CreateRuleRequest(rule);
120+
TestActionListener<CreateRuleResponse> createListener = new TestActionListener<>();
121+
persistenceService.createRule(createRequest, createListener);
122+
assertTrue(createListener.successCalled);
123+
124+
UpdateRuleRequest updateRequest = new UpdateRuleRequest(
125+
rule.getId(),
126+
"updated",
127+
rule.getAttributeMap(),
128+
rule.getFeatureValue(),
129+
rule.getFeatureType()
130+
);
131+
TestActionListener<UpdateRuleResponse> updateListener = new TestActionListener<>();
132+
persistenceService.updateRule(updateRequest, updateListener);
133+
assertTrue(updateListener.successCalled);
134+
assertEquals("updated", updateListener.result.getRule().getDescription());
135+
136+
GetRuleRequest getRequest = new GetRuleRequest(rule.getId(), Map.of(), null, featureType);
137+
TestActionListener<GetRuleResponse> getListener = new TestActionListener<>();
138+
persistenceService.getRule(getRequest, getListener);
139+
assertTrue(getListener.successCalled);
140+
}
141+
142+
public void testCreateRuleWithMultipleIndexPatterns() {
143+
Rule rule = Rule.builder()
144+
.id("multi-id")
145+
.description("multi-index")
146+
.featureType(featureType)
147+
.featureValue("groupB")
148+
.updatedAt("2025-06-17T00:00:00Z")
149+
.attributeMap(Map.of(featureType.getAttributeFromName("index_pattern"), Set.of("logs-*", "metrics-*")))
150+
.build();
151+
152+
CreateRuleRequest request = new CreateRuleRequest(rule);
153+
TestActionListener<CreateRuleResponse> listener = new TestActionListener<>();
154+
persistenceService.createRule(request, listener);
155+
156+
assertTrue(listener.successCalled);
157+
assertEquals("multi-id", listener.result.getRule().getId());
158+
assertEquals(2, listener.result.getRule().getAttributeMap().get(featureType.getAttributeFromName("index_pattern")).size());
159+
}
160+
161+
public void testUpdateRuleOnlyDescription() {
162+
Rule original = buildRule("partial-update-id", "desc-v1", "logs-*");
163+
164+
CreateRuleRequest createRequest = new CreateRuleRequest(original);
165+
TestActionListener<CreateRuleResponse> createListener = new TestActionListener<>();
166+
persistenceService.createRule(createRequest, createListener);
167+
assertTrue(createListener.successCalled);
168+
169+
UpdateRuleRequest updateRequest = new UpdateRuleRequest(
170+
original.getId(),
171+
"desc-v2",
172+
original.getAttributeMap(),
173+
original.getFeatureValue(),
174+
original.getFeatureType()
175+
);
176+
TestActionListener<UpdateRuleResponse> updateListener = new TestActionListener<>();
177+
persistenceService.updateRule(updateRequest, updateListener);
178+
179+
assertTrue(updateListener.successCalled);
180+
assertEquals("desc-v2", updateListener.result.getRule().getDescription());
181+
}
182+
183+
public void testCreateRuleWithDuplicateAttributeValues() {
184+
Attribute attr = featureType.getAttributeFromName("index_pattern");
185+
186+
IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> {
187+
Rule.builder()
188+
.id("dup-id")
189+
.description("duplicates")
190+
.featureType(featureType)
191+
.featureValue("groupD")
192+
.updatedAt("2025-06-17T00:00:00Z")
193+
.attributeMap(Map.of(attr, Set.of("logs-*", "logs-*")))
194+
.build();
195+
});
196+
197+
assertTrue(ex.getMessage().contains("duplicate element") || ex.getMessage().contains("duplicate"));
198+
}
199+
200+
public void testGetRuleRequestInvalidInput() {
201+
IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> {
202+
new GetRuleRequest("", Map.of(), "", featureType).validate();
203+
});
204+
assertTrue(ex.getMessage().contains("cannot be empty"));
205+
}
206+
207+
private Rule buildRule(String id, String description, String pattern) {
208+
return Rule.builder()
209+
.id(id)
210+
.description(description)
211+
.featureType(featureType)
212+
.featureValue("groupA")
213+
.updatedAt("2025-06-17T00:00:00Z")
214+
.attributeMap(Map.of(featureType.getAttributeFromName("index_pattern"), Set.of(pattern)))
215+
.build();
216+
}
217+
218+
public static class TestFeatureType implements FeatureType {
219+
private final Map<String, Attribute> attributes = Map.of("index_pattern", new IndexPatternAttribute());
220+
221+
@Override
222+
public String getName() {
223+
return "workload_group";
224+
}
225+
226+
@Override
227+
public Map<String, Attribute> getAllowedAttributesRegistry() {
228+
return attributes;
229+
}
230+
231+
@Override
232+
public Attribute getAttributeFromName(String name) {
233+
return attributes.get(name);
234+
}
235+
}
236+
237+
public static class IndexPatternAttribute implements Attribute {
238+
@Override
239+
public String getName() {
240+
return "index_pattern";
241+
}
242+
}
243+
244+
public static class TestRulePersistenceService implements RulePersistenceService {
245+
@Override
246+
public void createRule(CreateRuleRequest request, ActionListener<CreateRuleResponse> listener) {
247+
listener.onResponse(new CreateRuleResponse(request.getRule()));
248+
}
249+
250+
@Override
251+
public void deleteRule(DeleteRuleRequest request, ActionListener<AcknowledgedResponse> listener) {
252+
listener.onResponse(new AcknowledgedResponse(true));
253+
}
254+
255+
@Override
256+
public void getRule(GetRuleRequest request, ActionListener<GetRuleResponse> listener) {
257+
listener.onResponse(new GetRuleResponse(List.of(), null)); // mock returns empty list
258+
}
259+
260+
@Override
261+
public void updateRule(UpdateRuleRequest request, ActionListener<UpdateRuleResponse> listener) {
262+
Rule rule = Rule.builder()
263+
.id(request.getId())
264+
.description(request.getDescription())
265+
.attributeMap(request.getAttributeMap())
266+
.featureType(request.getFeatureType())
267+
.featureValue(request.getFeatureValue())
268+
.updatedAt("2025-06-17T00:00:00Z")
269+
.build();
270+
listener.onResponse(new UpdateRuleResponse(rule));
271+
}
272+
}
273+
274+
public static class TestActionListener<T> implements ActionListener<T> {
275+
public boolean successCalled = false;
276+
public T result = null;
277+
278+
@Override
279+
public void onResponse(T t) {
280+
successCalled = true;
281+
result = t;
282+
}
283+
284+
@Override
285+
public void onFailure(Exception e) {
286+
fail("Unexpected failure: " + e.getMessage());
287+
}
288+
}
289+
}

0 commit comments

Comments
 (0)