@@ -1102,4 +1102,341 @@ public void testDetectMediaTypeUnrecognizable() {
11021102 MediaType result = BulkRequestParserProtoUtils .detectMediaType (invalidBytes );
11031103 assertEquals ("application/json" , result .mediaTypeWithoutParameters ());
11041104 }
1105+
1106+ /**
1107+ * Test buildCreateRequest with explicit index when allowExplicitIndex is false
1108+ */
1109+ public void testBuildCreateRequestExplicitIndexNotAllowed () {
1110+ WriteOperation writeOperation = WriteOperation .newBuilder ().setXIndex ("explicit-index" ).build ();
1111+ byte [] document = "{\" field\" :\" value\" }" .getBytes (StandardCharsets .UTF_8 );
1112+
1113+ IllegalArgumentException exception = expectThrows (
1114+ IllegalArgumentException .class ,
1115+ () -> BulkRequestParserProtoUtils .buildCreateRequest (
1116+ writeOperation ,
1117+ document ,
1118+ "default-index" ,
1119+ "default-id" ,
1120+ null ,
1121+ Versions .MATCH_ANY ,
1122+ VersionType .INTERNAL ,
1123+ null ,
1124+ SequenceNumbers .UNASSIGNED_SEQ_NO ,
1125+ UNASSIGNED_PRIMARY_TERM ,
1126+ false ,
1127+ "default-index" , // defaultIndex is not null
1128+ false // allowExplicitIndex is false
1129+ )
1130+ );
1131+
1132+ assertEquals ("explicit index in bulk is not allowed" , exception .getMessage ());
1133+ }
1134+
1135+ /**
1136+ * Test buildIndexRequest with explicit index when allowExplicitIndex is false
1137+ */
1138+ public void testBuildIndexRequestExplicitIndexNotAllowed () {
1139+ IndexOperation indexOperation = IndexOperation .newBuilder ().setXIndex ("explicit-index" ).build ();
1140+ byte [] document = "{\" field\" :\" value\" }" .getBytes (StandardCharsets .UTF_8 );
1141+
1142+ IllegalArgumentException exception = expectThrows (
1143+ IllegalArgumentException .class ,
1144+ () -> BulkRequestParserProtoUtils .buildIndexRequest (
1145+ indexOperation ,
1146+ document ,
1147+ null ,
1148+ "default-index" ,
1149+ "default-id" ,
1150+ null ,
1151+ Versions .MATCH_ANY ,
1152+ VersionType .INTERNAL ,
1153+ null ,
1154+ SequenceNumbers .UNASSIGNED_SEQ_NO ,
1155+ UNASSIGNED_PRIMARY_TERM ,
1156+ false ,
1157+ "default-index" , // defaultIndex is not null
1158+ false // allowExplicitIndex is false
1159+ )
1160+ );
1161+
1162+ assertEquals ("explicit index in bulk is not allowed" , exception .getMessage ());
1163+ }
1164+
1165+ /**
1166+ * Test buildUpdateRequest with explicit index when allowExplicitIndex is false
1167+ */
1168+ public void testBuildUpdateRequestExplicitIndexNotAllowed () {
1169+ UpdateOperation updateOperation = UpdateOperation .newBuilder ().setXIndex ("explicit-index" ).build ();
1170+ byte [] document = "{\" field\" :\" value\" }" .getBytes (StandardCharsets .UTF_8 );
1171+
1172+ BulkRequestBody bulkRequestBody = BulkRequestBody .newBuilder ()
1173+ .setOperationContainer (OperationContainer .newBuilder ().setUpdate (updateOperation ).build ())
1174+ .setObject (ByteString .copyFrom (document ))
1175+ .build ();
1176+
1177+ IllegalArgumentException exception = expectThrows (
1178+ IllegalArgumentException .class ,
1179+ () -> BulkRequestParserProtoUtils .buildUpdateRequest (
1180+ updateOperation ,
1181+ ByteString .copyFrom (document ),
1182+ bulkRequestBody ,
1183+ "default-index" ,
1184+ "default-id" ,
1185+ null ,
1186+ null ,
1187+ 0 ,
1188+ null ,
1189+ SequenceNumbers .UNASSIGNED_SEQ_NO ,
1190+ UNASSIGNED_PRIMARY_TERM ,
1191+ false ,
1192+ "default-index" , // defaultIndex is not null
1193+ false // allowExplicitIndex is false
1194+ )
1195+ );
1196+
1197+ assertEquals ("explicit index in bulk is not allowed" , exception .getMessage ());
1198+ }
1199+
1200+ /**
1201+ * Test buildDeleteRequest with explicit index when allowExplicitIndex is false
1202+ */
1203+ public void testBuildDeleteRequestExplicitIndexNotAllowed () {
1204+ DeleteOperation deleteOperation = DeleteOperation .newBuilder ().setXIndex ("explicit-index" ).build ();
1205+
1206+ IllegalArgumentException exception = expectThrows (
1207+ IllegalArgumentException .class ,
1208+ () -> BulkRequestParserProtoUtils .buildDeleteRequest (
1209+ deleteOperation ,
1210+ "default-index" ,
1211+ "default-id" ,
1212+ null ,
1213+ Versions .MATCH_ANY ,
1214+ VersionType .INTERNAL ,
1215+ SequenceNumbers .UNASSIGNED_SEQ_NO ,
1216+ UNASSIGNED_PRIMARY_TERM ,
1217+ "default-index" , // defaultIndex is not null
1218+ false // allowExplicitIndex is false
1219+ )
1220+ );
1221+
1222+ assertEquals ("explicit index in bulk is not allowed" , exception .getMessage ());
1223+ }
1224+
1225+ /**
1226+ * Test buildUpdateRequest with upsert request and pipeline
1227+ */
1228+ public void testBuildUpdateRequestWithUpsertAndPipeline () {
1229+ UpdateOperation updateOperation = UpdateOperation .newBuilder ().setXIndex ("test-index" ).setXId ("test-id" ).build ();
1230+
1231+ byte [] document = "{\" field\" :\" value\" }" .getBytes (StandardCharsets .UTF_8 );
1232+ byte [] upsertDoc = "{\" upsert_field\" :\" upsert_value\" }" .getBytes (StandardCharsets .UTF_8 );
1233+
1234+ BulkRequestBody bulkRequestBody = BulkRequestBody .newBuilder ()
1235+ .setOperationContainer (OperationContainer .newBuilder ().setUpdate (updateOperation ).build ())
1236+ .setObject (ByteString .copyFrom (document ))
1237+ .setUpdateAction (org .opensearch .protobufs .UpdateAction .newBuilder ().setUpsert (ByteString .copyFrom (upsertDoc )).build ())
1238+ .build ();
1239+
1240+ UpdateRequest updateRequest = BulkRequestParserProtoUtils .buildUpdateRequest (
1241+ updateOperation ,
1242+ ByteString .copyFrom (document ),
1243+ bulkRequestBody ,
1244+ "default-index" ,
1245+ "default-id" ,
1246+ null ,
1247+ null ,
1248+ 0 ,
1249+ "test-pipeline" , // pipeline
1250+ SequenceNumbers .UNASSIGNED_SEQ_NO ,
1251+ UNASSIGNED_PRIMARY_TERM ,
1252+ false ,
1253+ null ,
1254+ true
1255+ );
1256+
1257+ assertNotNull ("UpdateRequest should not be null" , updateRequest );
1258+ assertNotNull ("Upsert request should be set" , updateRequest .upsertRequest ());
1259+ assertEquals ("Pipeline should be set on upsert request" , "test-pipeline" , updateRequest .upsertRequest ().getPipeline ());
1260+ }
1261+
1262+ /**
1263+ * Test fromProto with empty document bytes (ByteString.EMPTY)
1264+ */
1265+ public void testFromProtoWithEmptyDocumentBytes () {
1266+ UpdateRequest updateRequest = new UpdateRequest ("test-index" , "test-id" );
1267+
1268+ BulkRequestBody bulkRequestBody = BulkRequestBody .newBuilder ()
1269+ .setUpdateAction (
1270+ org .opensearch .protobufs .UpdateAction .newBuilder ()
1271+ .setScript (
1272+ org .opensearch .protobufs .Script .newBuilder ()
1273+ .setInline (
1274+ org .opensearch .protobufs .InlineScript .newBuilder ()
1275+ .setSource ("ctx._source.counter += 1" )
1276+ .setLang (
1277+ org .opensearch .protobufs .ScriptLanguage .newBuilder ()
1278+ .setBuiltin (org .opensearch .protobufs .BuiltinScriptLanguage .BUILTIN_SCRIPT_LANGUAGE_PAINLESS )
1279+ .build ()
1280+ )
1281+ .build ()
1282+ )
1283+ .build ()
1284+ )
1285+ .build ()
1286+ )
1287+ .build ();
1288+
1289+ // Test with ByteString.EMPTY (no doc field)
1290+ UpdateRequest result = BulkRequestParserProtoUtils .fromProto (
1291+ updateRequest ,
1292+ ByteString .EMPTY ,
1293+ bulkRequestBody ,
1294+ SequenceNumbers .UNASSIGNED_SEQ_NO ,
1295+ UNASSIGNED_PRIMARY_TERM
1296+ );
1297+
1298+ assertNotNull ("Result should not be null" , result );
1299+ assertNotNull ("Script should be set" , result .script ());
1300+ assertNull ("Doc should not be set when ByteString is empty" , result .doc ());
1301+ }
1302+
1303+ /**
1304+ * Test fromProto with null document bytes
1305+ */
1306+ public void testFromProtoWithNullDocumentBytes () {
1307+ UpdateRequest updateRequest = new UpdateRequest ("test-index" , "test-id" );
1308+
1309+ BulkRequestBody bulkRequestBody = BulkRequestBody .newBuilder ()
1310+ .setUpdateAction (
1311+ org .opensearch .protobufs .UpdateAction .newBuilder ()
1312+ .setScript (
1313+ org .opensearch .protobufs .Script .newBuilder ()
1314+ .setInline (
1315+ org .opensearch .protobufs .InlineScript .newBuilder ()
1316+ .setSource ("ctx._source.counter += 1" )
1317+ .setLang (
1318+ org .opensearch .protobufs .ScriptLanguage .newBuilder ()
1319+ .setBuiltin (org .opensearch .protobufs .BuiltinScriptLanguage .BUILTIN_SCRIPT_LANGUAGE_PAINLESS )
1320+ .build ()
1321+ )
1322+ .build ()
1323+ )
1324+ .build ()
1325+ )
1326+ .build ()
1327+ )
1328+ .build ();
1329+
1330+ // Test with null documentBytes
1331+ UpdateRequest result = BulkRequestParserProtoUtils .fromProto (
1332+ updateRequest ,
1333+ null ,
1334+ bulkRequestBody ,
1335+ SequenceNumbers .UNASSIGNED_SEQ_NO ,
1336+ UNASSIGNED_PRIMARY_TERM
1337+ );
1338+
1339+ assertNotNull ("Result should not be null" , result );
1340+ assertNotNull ("Script should be set" , result .script ());
1341+ assertNull ("Doc should not be set when documentBytes is null" , result .doc ());
1342+ }
1343+
1344+ /**
1345+ * Test getDocWriteRequests with update operation using UpdateAction.doc field
1346+ */
1347+ public void testGetDocWriteRequestsWithUpdateActionDoc () {
1348+ UpdateOperation updateOp = UpdateOperation .newBuilder ().setXIndex ("test-index" ).setXId ("test-id" ).build ();
1349+
1350+ byte [] document = "{\" field\" :\" value\" }" .getBytes (StandardCharsets .UTF_8 );
1351+
1352+ BulkRequestBody updateBody = BulkRequestBody .newBuilder ()
1353+ .setOperationContainer (OperationContainer .newBuilder ().setUpdate (updateOp ).build ())
1354+ .setUpdateAction (org .opensearch .protobufs .UpdateAction .newBuilder ().setDoc (ByteString .copyFrom (document )).build ())
1355+ .build ();
1356+
1357+ BulkRequest request = BulkRequest .newBuilder ().addBulkRequestBody (updateBody ).build ();
1358+
1359+ DocWriteRequest <?>[] requests = BulkRequestParserProtoUtils .getDocWriteRequests (
1360+ request ,
1361+ "default-index" ,
1362+ null ,
1363+ null ,
1364+ null ,
1365+ false ,
1366+ true
1367+ );
1368+
1369+ assertNotNull ("Requests should not be null" , requests );
1370+ assertEquals ("Should have 1 request" , 1 , requests .length );
1371+ assertTrue ("Request should be an UpdateRequest" , requests [0 ] instanceof UpdateRequest );
1372+
1373+ UpdateRequest updateRequest = (UpdateRequest ) requests [0 ];
1374+ assertNotNull ("Doc should be set from UpdateAction.doc" , updateRequest .doc ());
1375+ }
1376+
1377+ /**
1378+ * Test valueOrDefault for String with null value and non-null globalDefault
1379+ */
1380+ public void testValueOrDefaultStringWithNullValue () {
1381+ UpdateOperation updateOp = UpdateOperation .newBuilder ().setXIndex ("test-index" ).setXId ("test-id" ).build ();
1382+
1383+ byte [] document = "{\" field\" :\" value\" }" .getBytes (StandardCharsets .UTF_8 );
1384+
1385+ BulkRequestBody updateBody = BulkRequestBody .newBuilder ()
1386+ .setOperationContainer (OperationContainer .newBuilder ().setUpdate (updateOp ).build ())
1387+ .setObject (ByteString .copyFrom (document ))
1388+ .build ();
1389+
1390+ BulkRequest request = BulkRequest .newBuilder ()
1391+ .addBulkRequestBody (updateBody )
1392+ .setRouting ("global-routing" )
1393+ .setPipeline ("global-pipeline" )
1394+ .build ();
1395+
1396+ DocWriteRequest <?>[] requests = BulkRequestParserProtoUtils .getDocWriteRequests (
1397+ request ,
1398+ "default-index" ,
1399+ null , // defaultRouting is null, should use global routing
1400+ null ,
1401+ null , // defaultPipeline is null, should use global pipeline
1402+ false ,
1403+ true
1404+ );
1405+
1406+ assertNotNull ("Requests should not be null" , requests );
1407+ assertEquals ("Should have 1 request" , 1 , requests .length );
1408+
1409+ UpdateRequest updateRequest = (UpdateRequest ) requests [0 ];
1410+ assertEquals ("Routing should use global value" , "global-routing" , updateRequest .routing ());
1411+ }
1412+
1413+ /**
1414+ * Test valueOrDefault for Boolean with null value and non-null globalDefault
1415+ */
1416+ public void testValueOrDefaultBooleanWithNullValue () {
1417+ IndexOperation indexOp = IndexOperation .newBuilder ().setXIndex ("test-index" ).setXId ("test-id" ).build ();
1418+
1419+ BulkRequestBody indexBody = BulkRequestBody .newBuilder ()
1420+ .setOperationContainer (OperationContainer .newBuilder ().setIndex (indexOp ).build ())
1421+ .setObject (ByteString .copyFromUtf8 ("{\" field\" :\" value\" }" ))
1422+ .build ();
1423+
1424+ BulkRequest request = BulkRequest .newBuilder ().addBulkRequestBody (indexBody ).setRequireAlias (true ).build ();
1425+
1426+ DocWriteRequest <?>[] requests = BulkRequestParserProtoUtils .getDocWriteRequests (
1427+ request ,
1428+ "default-index" ,
1429+ null ,
1430+ null ,
1431+ null ,
1432+ null , // defaultRequireAlias is null, should use global requireAlias
1433+ true
1434+ );
1435+
1436+ assertNotNull ("Requests should not be null" , requests );
1437+ assertEquals ("Should have 1 request" , 1 , requests .length );
1438+
1439+ IndexRequest indexRequest = (IndexRequest ) requests [0 ];
1440+ assertTrue ("RequireAlias should use global value" , indexRequest .isRequireAlias ());
1441+ }
11051442}
0 commit comments