List<Pair<String, String>> doStitchDatasetVersionGetTest(Account account, Container container, List<Dataset> datasets,
      String contentType, String ownerId, List<String> signedChunkIds, byte[] fullContentArray, long stitchedBlobSize)
      throws Exception {
    String accountName = account.getName();
    String containerName = container.getName();
    List<Pair<String, String>> datasetVersions = new ArrayList<>();
    for (Dataset dataset : datasets) {
      for (long ttl : new long[]{-1, TTL_SECS}) {
        //Test stitch
        HttpHeaders stitchHeaders = new DefaultHttpHeaders();
        setAmbryHeadersForPut(stitchHeaders, ttl, !container.isCacheable(), "stitcher", contentType, ownerId,
            account.getName(), container.getName());
        stitchHeaders.add(RestUtils.Headers.DATASET_VERSION_QUERY_ENABLED, true);
        stitchHeaders.add(RestUtils.Headers.UPLOAD_NAMED_BLOB_MODE, "STITCH");
        String version = generateDatasetVersion(dataset);
        String stitchedBlobId =
            doDatasetStitchAndVerify(account, container, dataset, version, stitchHeaders, signedChunkIds,
                stitchedBlobSize, ttl);
        HttpHeaders expectedGetHeaders = new DefaultHttpHeaders().add(stitchHeaders);
        // Test different request types on stitched blob ID
        // (getBlobInfo, getBlob, getBlob w/ range, head, updateBlobTtl, deleteBlob)
        expectedGetHeaders.add(RestUtils.Headers.BLOB_SIZE, fullContentArray.length);
        expectedGetHeaders.set(RestUtils.Headers.LIFE_VERSION, "0");
        getBlobInfoAndVerify(stitchedBlobId, GetOption.None, expectedGetHeaders, !container.isCacheable(),
            account.getName(), container.getName(), null, container);
        List<ByteRange> ranges = new ArrayList<>();
        ranges.add(null);
        ranges.add(ByteRanges.fromLastNBytes(ThreadLocalRandom.current().nextLong(fullContentArray.length + 1)));
        ranges.add(ByteRanges.fromStartOffset(ThreadLocalRandom.current().nextLong(fullContentArray.length)));
        long random1 = ThreadLocalRandom.current().nextLong(fullContentArray.length);
        long random2 = ThreadLocalRandom.current().nextLong(fullContentArray.length);
        ranges.add(ByteRanges.fromOffsetRange(Math.min(random1, random2), Math.max(random1, random2)));
        for (ByteRange range : ranges) {
          getBlobAndVerify(stitchedBlobId, range, GetOption.None, false, expectedGetHeaders, !container.isCacheable(),
              ByteBuffer.wrap(fullContentArray), account.getName(), container.getName(), container);
          getHeadAndVerify(stitchedBlobId, range, GetOption.None, expectedGetHeaders, !container.isCacheable(),
              account.getName(), container.getName());
        }

        //Test get dataset version
        HttpHeaders getHeaders = new DefaultHttpHeaders();
        getHeaders.add(RestUtils.Headers.DATASET_VERSION_QUERY_ENABLED, true);
        getDatasetVersionAndVerify(dataset, version, getHeaders, stitchedBlobSize, ttl, expectedGetHeaders,
            ByteBuffer.wrap(fullContentArray));
        getDatasetVersionInfoAndVerify(accountName, containerName, dataset.getDatasetName(), version, getHeaders, ttl,
            expectedGetHeaders);

        //add all versions when successfully get it.
        datasetVersions.add(new Pair<>(dataset.getDatasetName(), version));
      }
    }
    return datasetVersions;
  }
Verify Named blob List operation.
@param accountName The account name.
@param containerName The container name
@param ownerId The owner id
@param prefix The prefix of blob name.
@param numberOfBlobs The expected number of named blobs returned by list operation.
@throws Exception
ambry-frontend/src/integration-test/java/com/github/ambry/frontend/FrontendIntegrationTestBase.java