66package org.opensearch.indexmanagement.snapshotmanagement.action
77
88import org.opensearch.common.io.stream.BytesStreamOutput
9+ import org.opensearch.common.xcontent.XContentFactory
910import org.opensearch.core.common.io.stream.StreamInput
1011import org.opensearch.core.rest.RestStatus
12+ import org.opensearch.core.xcontent.ToXContent
1113import org.opensearch.indexmanagement.indexstatemanagement.util.XCONTENT_WITHOUT_TYPE_AND_USER
14+ import org.opensearch.indexmanagement.opensearchapi.toMap
1215import org.opensearch.indexmanagement.snapshotmanagement.api.transport.explain.ExplainSMPolicyResponse
1316import org.opensearch.indexmanagement.snapshotmanagement.api.transport.get.GetSMPoliciesResponse
1417import org.opensearch.indexmanagement.snapshotmanagement.api.transport.get.GetSMPolicyResponse
@@ -17,8 +20,8 @@ import org.opensearch.indexmanagement.snapshotmanagement.model.ExplainSMPolicy
1720import org.opensearch.indexmanagement.snapshotmanagement.randomSMMetadata
1821import org.opensearch.indexmanagement.snapshotmanagement.randomSMPolicy
1922import org.opensearch.indexmanagement.snapshotmanagement.smDocIdToPolicyName
20- import org.opensearch.indexmanagement.snapshotmanagement.toMap
2123import org.opensearch.test.OpenSearchTestCase
24+ import org.opensearch.indexmanagement.snapshotmanagement.toMap as toMapHelper
2225
2326class ResponseTests : OpenSearchTestCase () {
2427 fun `test index sm policy response` () {
@@ -38,8 +41,8 @@ class ResponseTests : OpenSearchTestCase() {
3841 fun `test index sm policy toXContent` () {
3942 val smPolicy = randomSMPolicy()
4043 val res = IndexSMPolicyResponse (" someid" , 1L , 2L , 3L , smPolicy, RestStatus .OK )
41- val resMap = res.toMap ()
42- assertEquals(resMap[" sm_policy" ], smPolicy.toMap (XCONTENT_WITHOUT_TYPE_AND_USER ))
44+ val resMap = res.toMapHelper ()
45+ assertEquals(resMap[" sm_policy" ], smPolicy.toMapHelper (XCONTENT_WITHOUT_TYPE_AND_USER ))
4346 }
4447
4548 fun `test get sm policy response` () {
@@ -81,7 +84,32 @@ class ResponseTests : OpenSearchTestCase() {
8184 fun `test get sm policy toXContent` () {
8285 val smPolicy = randomSMPolicy()
8386 val res = GetSMPolicyResponse (" someid" , 1L , 2L , 3L , smPolicy)
84- val resMap = res.toMap()
85- assertEquals(resMap[" sm_policy" ], smPolicy.toMap(XCONTENT_WITHOUT_TYPE_AND_USER ))
87+ val resMap = res.toMapHelper()
88+ assertEquals(resMap[" sm_policy" ], smPolicy.toMapHelper(XCONTENT_WITHOUT_TYPE_AND_USER ))
89+ }
90+
91+ fun `test explain sm policy toXContent with null creation` () {
92+ // Test that ExplainSMPolicy.toXContent() handles null creation correctly (for V_3_3_0+)
93+ val smMetadata = randomSMMetadata()
94+ val smMetadataWithNullCreation = smMetadata.copy(creation = null )
95+ val explainSMPolicy = ExplainSMPolicy (smMetadataWithNullCreation, true )
96+
97+ // Properly convert ToXContentFragment to map by wrapping in an object
98+ val builder = XContentFactory .jsonBuilder().startObject()
99+ explainSMPolicy.toXContent(builder, ToXContent .EMPTY_PARAMS )
100+ builder.endObject()
101+ val explainMap = builder.toMap()
102+
103+ // Verify that creation field is NOT present when null (optionalField behavior for V_3_3_0+)
104+ assertFalse(" Creation field should not be present when null" , explainMap.containsKey(" creation" ))
105+
106+ // Verify deletion field IS present
107+ assertTrue(" Deletion field should be present" , explainMap.containsKey(" deletion" ))
108+
109+ // Verify other mandatory fields are present
110+ assertTrue(" Policy seq_no should be present" , explainMap.containsKey(" policy_seq_no" ))
111+ assertTrue(" Policy primary_term should be present" , explainMap.containsKey(" policy_primary_term" ))
112+ assertTrue(" Enabled field should be present" , explainMap.containsKey(" enabled" ))
113+ assertEquals(true , explainMap[" enabled" ])
86114 }
87115}
0 commit comments