diff --git a/NOTICE b/NOTICE index 121425b665c270d20637483071524fa8a324ffae..60b4118a46591bfa65113b5bb1ca7e3039c55b93 100644 --- a/NOTICE +++ b/NOTICE @@ -374,7 +374,7 @@ The following software have components provided under the terms of this license: - Byte Buddy Java agent (from https://repo1.maven.org/maven2/net/bytebuddy/byte-buddy-agent) - ClassMate (from http://github.com/cowtowncoder/java-classmate) - Cloud Key Management Service (KMS) API (from https://repo1.maven.org/maven2/com/google/apis/google-api-services-cloudkms) -- Cloud Storage JSON API (from https://repo1.maven.org/maven2/com/google/apis/google-api-services-storage) +- Cloud Storage JSON API v1-rev20230301-2.0.0 (from https://repo1.maven.org/maven2/com/google/apis/google-api-services-storage) - CloudWatch Metrics for AWS Java SDK (from https://aws.amazon.com/sdkforjava) - Cobertura (from http://cobertura.sourceforge.net) - Cobertura Limited Runtime (from http://cobertura.sourceforge.net) diff --git a/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/IndexerServiceImpl.java b/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/IndexerServiceImpl.java index c804c056b87c5689f9c7dc203e303ae4801d21bd..8e2895fc2b0807e9ad6fedcc2a09f7b060ab27af 100644 --- a/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/IndexerServiceImpl.java +++ b/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/IndexerServiceImpl.java @@ -125,7 +125,7 @@ public class IndexerServiceImpl implements IndexerService { // get upsert records Map<String, Map<String, OperationType>> upsertRecordMap = RecordInfo.getUpsertRecordIds(recordInfos); if (upsertRecordMap != null && !upsertRecordMap.isEmpty()) { - List<String> upsertFailureRecordIds = processUpsertRecords(upsertRecordMap); + List<String> upsertFailureRecordIds = processUpsertRecords(upsertRecordMap, recordInfos); retryRecordIds.addAll(upsertFailureRecordIds); } @@ -191,7 +191,7 @@ public class IndexerServiceImpl implements IndexerService { } } - private List<String> processUpsertRecords(Map<String, Map<String, OperationType>> upsertRecordMap) throws Exception { + private List<String> processUpsertRecords(Map<String, Map<String, OperationType>> upsertRecordMap, List<RecordInfo> recordChangedInfos) throws Exception { // get schema for kind Map<String, IndexSchema> schemas = this.getSchema(upsertRecordMap); @@ -203,7 +203,7 @@ public class IndexerServiceImpl implements IndexerService { if (recordIds.isEmpty()) return new LinkedList<>(); // get records via storage api - Records storageRecords = this.storageService.getStorageRecords(recordIds); + Records storageRecords = this.storageService.getStorageRecords(recordIds, recordChangedInfos); List<String> failedOrRetryRecordIds = new LinkedList<>(storageRecords.getMissingRetryRecords()); // map storage records to indexer payload diff --git a/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/StorageService.java b/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/StorageService.java index bfbb5c6d5a0faf2cf1b62ec031697141f0f649ef..54a19e807079d6076b855e89ea2707f88308e038 100644 --- a/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/StorageService.java +++ b/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/StorageService.java @@ -15,6 +15,7 @@ package org.opengroup.osdu.indexer.service; import org.opengroup.osdu.core.common.model.http.AppException; +import org.opengroup.osdu.core.common.model.indexer.RecordInfo; import org.opengroup.osdu.core.common.model.indexer.RecordQueryResponse; import org.opengroup.osdu.core.common.model.indexer.RecordReindexRequest; import org.opengroup.osdu.core.common.model.indexer.Records; @@ -25,7 +26,7 @@ import java.util.List; public interface StorageService { - Records getStorageRecords(List<String> ids) throws AppException, URISyntaxException; + Records getStorageRecords(List<String> ids, List<RecordInfo> recordChangedInfos) throws AppException, URISyntaxException; RecordQueryResponse getRecordsByKind(RecordReindexRequest request) throws URISyntaxException; diff --git a/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/StorageServiceImpl.java b/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/StorageServiceImpl.java index e9e3328eea0cb9df4f2691b901cbf62fabc22165..1b20cfb14cd9128dcb1595d9a608d6c4ed1da4b1 100644 --- a/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/StorageServiceImpl.java +++ b/indexer-core/src/main/java/org/opengroup/osdu/indexer/service/StorageServiceImpl.java @@ -20,23 +20,28 @@ import com.google.api.client.http.HttpMethods; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.gson.Gson; - import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import org.apache.http.HttpStatus; import org.opengroup.osdu.core.common.http.FetchServiceHttpRequest; -import org.opengroup.osdu.core.common.model.http.DpsHeaders; +import org.opengroup.osdu.core.common.http.IUrlFetchService; +import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; import org.opengroup.osdu.core.common.model.http.AppException; +import org.opengroup.osdu.core.common.model.http.DpsHeaders; import org.opengroup.osdu.core.common.model.http.HttpResponse; import org.opengroup.osdu.core.common.model.http.RequestStatus; -import org.opengroup.osdu.core.common.model.indexer.*; +import org.opengroup.osdu.core.common.model.indexer.IndexingStatus; +import org.opengroup.osdu.core.common.model.indexer.JobStatus; +import org.opengroup.osdu.core.common.model.indexer.OperationType; +import org.opengroup.osdu.core.common.model.indexer.RecordInfo; +import org.opengroup.osdu.core.common.model.indexer.RecordQueryResponse; +import org.opengroup.osdu.core.common.model.indexer.RecordReindexRequest; +import org.opengroup.osdu.core.common.model.indexer.Records; +import org.opengroup.osdu.core.common.model.search.RecordMetaAttribute; import org.opengroup.osdu.core.common.model.storage.ConversionStatus; import org.opengroup.osdu.core.common.model.storage.RecordIds; -import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; -import org.opengroup.osdu.core.common.http.IUrlFetchService; -import org.opengroup.osdu.core.common.model.search.RecordMetaAttribute; import org.opengroup.osdu.core.common.provider.interfaces.IRequestInfo; -import org.apache.http.HttpStatus; import org.opengroup.osdu.indexer.config.IndexerConfigurationProperties; import org.springframework.stereotype.Component; @@ -52,8 +57,8 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import static org.opengroup.osdu.core.common.model.http.DpsHeaders.FRAME_OF_REFERENCE; import static org.opengroup.osdu.core.common.Constants.SLB_FRAME_OF_REFERENCE_VALUE; +import static org.opengroup.osdu.core.common.model.http.DpsHeaders.FRAME_OF_REFERENCE; @Component public class StorageServiceImpl implements StorageService { @@ -74,15 +79,17 @@ public class StorageServiceImpl implements StorageService { private IndexerConfigurationProperties configurationProperties; @Override - public Records getStorageRecords(List<String> ids) throws AppException, URISyntaxException { + public Records getStorageRecords(List<String> ids, List<RecordInfo> recordChangedInfos) throws AppException, URISyntaxException { List<Records.Entity> valid = new ArrayList<>(); List<String> notFound = new ArrayList<>(); List<ConversionStatus> conversionStatuses = new ArrayList<>(); List<String> missingRetryRecordIds = new ArrayList<>(); + Map<String, String> recordChangedMap = recordChangedInfos.stream().collect(Collectors.toMap(RecordInfo::getId, RecordInfo::getKind, (a, b) -> b)); + Map<String, String> validRecordKindPatchMap = getValidRecordKindPatchMap(recordChangedInfos); List<List<String>> batch = Lists.partition(ids, configurationProperties.getStorageRecordsBatchSize()); for (List<String> recordsBatch : batch) { - Records storageOut = this.getRecords(recordsBatch); + Records storageOut = this.getRecords(recordsBatch, recordChangedMap, validRecordKindPatchMap); valid.addAll(storageOut.getRecords()); notFound.addAll(storageOut.getNotFound()); conversionStatuses.addAll(storageOut.getConversionStatuses()); @@ -91,11 +98,10 @@ public class StorageServiceImpl implements StorageService { return Records.builder().records(valid).notFound(notFound).conversionStatuses(conversionStatuses).missingRetryRecords(missingRetryRecordIds).build(); } - protected Records getRecords(List<String> ids) throws URISyntaxException { + protected Records getRecords(List<String> ids, Map<String, String> recordChangedMap, Map<String, String> validRecordKindPatchMap) throws URISyntaxException { // e.g. {"records":["test:10"]} String body = this.gson.toJson(RecordIds.builder().records(ids).build()); -// Map<String, String> headers = this.requestInfo.getHeadersMap(); DpsHeaders headers = this.requestInfo.getHeaders(); headers.put(FRAME_OF_REFERENCE, SLB_FRAME_OF_REFERENCE_VALUE); FetchServiceHttpRequest request = FetchServiceHttpRequest @@ -105,10 +111,10 @@ public class StorageServiceImpl implements StorageService { .headers(headers) .body(body).build(); HttpResponse response = this.urlFetchService.sendRequest(request); - return this.validateStorageResponse(response, ids); + return this.validateStorageResponse(response, ids, recordChangedMap, validRecordKindPatchMap); } - private Records validateStorageResponse(HttpResponse response, List<String> ids) { + private Records validateStorageResponse(HttpResponse response, List<String> ids, Map<String, String> recordChangedMap, Map<String, String> validRecordKindPatchMap) { String bulkStorageData = response.getBody(); // retry entire payload -- storage service returned empty response @@ -145,8 +151,13 @@ public class StorageServiceImpl implements StorageService { throw new AppException(HttpStatus.SC_NOT_FOUND, "Invalid request", "Storage service error"); } + // validate kind to avoid data duplication + List<String> staleRecords = getStaleRecordsUpdate(recordChangedMap, validRecordKindPatchMap, validRecords); + List<Records.Entity> indexableRecords = validateKind(validRecords, staleRecords); + records.setRecords(indexableRecords); + Map<String, List<String>> conversionStatus = getConversionErrors(records.getConversionStatuses()); - for (Records.Entity storageRecord : validRecords) { + for (Records.Entity storageRecord : indexableRecords) { String recordId = storageRecord.getId(); if (conversionStatus.get(recordId) == null) { continue; @@ -157,8 +168,8 @@ public class StorageServiceImpl implements StorageService { } // retry missing records -- storage did not return response for all RecordChangeMessage record-ids - if (records.getTotalRecordCount() != ids.size()) { - List<String> missingRecords = this.getMissingRecords(records, ids); + if ((records.getRecords().size() + records.getNotFound().size() + staleRecords.size()) != ids.size()) { + List<String> missingRecords = this.getMissingRecords(records, ids, staleRecords); records.setMissingRetryRecords(missingRecords); this.jobStatus.addOrUpdateRecordStatus(missingRecords, IndexingStatus.FAIL, HttpStatus.SC_NOT_FOUND, "Partial response received from Storage service - missing records", String.format("Partial response received from Storage service: %s", String.join(",", missingRecords))); } @@ -166,12 +177,13 @@ public class StorageServiceImpl implements StorageService { return records; } - private List<String> getMissingRecords(Records records, List<String> ids) { + private List<String> getMissingRecords(Records records, List<String> ids, List<String> staleRecords) { List<String> validRecordIds = records.getRecords().stream().map(Records.Entity::getId).collect(Collectors.toList()); List<String> invalidRecordsIds = records.getNotFound(); List<String> requestedIds = new ArrayList<>(ids); requestedIds.removeAll(validRecordIds); requestedIds.removeAll(invalidRecordsIds); + requestedIds.removeAll(staleRecords); return requestedIds; } @@ -188,6 +200,54 @@ public class StorageServiceImpl implements StorageService { return errorsByRecordId; } + private List<Records.Entity> validateKind(List<Records.Entity> validRecords, List<String> staleRecords) { + List<Records.Entity> indexableRecords = new ArrayList<>(); + if (!staleRecords.isEmpty()) { + for (Records.Entity record : validRecords) { + if (staleRecords.contains(record.getId())) { + continue; + } + indexableRecords.add(record); + } + jaxRsDpsLog.warning(String.format("stale records found with older kind, skipping indexing | record ids: %s", String.join(" | ", staleRecords))); + } else { + indexableRecords.addAll(validRecords); + } + return indexableRecords; + } + + private List<String> getStaleRecordsUpdate(Map<String, String> recordChangedMap, Map<String, String> validRecordKindPatchMap, List<Records.Entity> validRecords) { + List<String> staleRecords = new ArrayList<>(); + for (Records.Entity storageRecord : validRecords) { + String kindOnStorage = storageRecord.getKind(); + String kindOnMessage = recordChangedMap.get(storageRecord.getId()); + if (validRecordKindPatchMap.containsKey(storageRecord.getId())) { + continue; + } + if (!kindOnStorage.equals(kindOnMessage)) { + staleRecords.add(storageRecord.getId()); + } + } + return staleRecords; + } + + /* + * Gets valid kind patch map, previousVersionKind is included on the record update message in such cases + * */ + private Map<String, String> getValidRecordKindPatchMap(List<RecordInfo> recordChangedInfos) { + Map<String, String> out = new HashMap<>(); + for (RecordInfo msg : recordChangedInfos) { + OperationType op = OperationType.valueOf(msg.getOp()); + if (op != OperationType.update) { + continue; + } + if (!Strings.isNullOrEmpty(msg.getPreviousVersionKind())) { + out.put(msg.getId(), msg.getPreviousVersionKind()); + } + } + return out; + } + @Override public RecordQueryResponse getRecordsByKind(RecordReindexRequest reindexRequest) throws URISyntaxException { Map<String, String> queryParams = new HashMap<>(); @@ -197,8 +257,8 @@ public class StorageServiceImpl implements StorageService { queryParams.put("cursor", reindexRequest.getCursor()); } - if(requestInfo == null) - throw new AppException(HttpStatus.SC_NO_CONTENT, "Invalid header", "header can't be null"); + if (requestInfo == null) + throw new AppException(HttpStatus.SC_NO_CONTENT, "Invalid header", "header can't be null"); FetchServiceHttpRequest request = FetchServiceHttpRequest.builder() .httpMethod(HttpMethods.GET) @@ -234,6 +294,6 @@ public class StorageServiceImpl implements StorageService { HttpResponse response = this.urlFetchService.sendRequest(request); JsonObject asJsonObject = new JsonParser().parse(response.getBody()).getAsJsonObject(); JsonElement results = asJsonObject.get("results"); - return response.getResponseCode() != HttpStatus.SC_OK ? null : this.gson.fromJson(results,List.class); + return response.getResponseCode() != HttpStatus.SC_OK ? null : this.gson.fromJson(results, List.class); } } diff --git a/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/IndexerServiceImplTest.java b/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/IndexerServiceImplTest.java index 285b384a017b4eefd044dc3e58e1434b1ad0543c..194fdab46f77aa9ca67834f640a3ba13337e25c7 100644 --- a/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/IndexerServiceImplTest.java +++ b/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/IndexerServiceImplTest.java @@ -142,7 +142,7 @@ public class IndexerServiceImplTest { validRecords.add(Records.Entity.builder().id(recordId2).kind(kind2).data(storageData).build()); List<ConversionStatus> conversionStatus = new LinkedList<>(); Records storageRecords = Records.builder().records(validRecords).conversionStatuses(conversionStatus).build(); - when(this.storageService.getStorageRecords(any())).thenReturn(storageRecords); + when(this.storageService.getStorageRecords(any(), any())).thenReturn(storageRecords); // setup elastic, index and mapped document when(this.indicesService.createIndex(any(), any(), any(), any(), any())).thenReturn(true); diff --git a/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/StorageServiceImplTest.java b/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/StorageServiceImplTest.java index 42791ea57c2541a2073ee87df7033bb6da3758f1..e64574d7a6452f704361f80ea66884232b506c0a 100644 --- a/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/StorageServiceImplTest.java +++ b/indexer-core/src/test/java/org/opengroup/osdu/indexer/service/StorageServiceImplTest.java @@ -1,54 +1,313 @@ +// Copyright 2017-2023, Schlumberger +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package org.opengroup.osdu.indexer.service; import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentMatchers; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; -import org.mockito.junit.MockitoJUnitRunner; import org.opengroup.osdu.core.common.http.IUrlFetchService; +import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; +import org.opengroup.osdu.core.common.model.http.AppException; import org.opengroup.osdu.core.common.model.http.DpsHeaders; import org.opengroup.osdu.core.common.model.http.HttpResponse; +import org.opengroup.osdu.core.common.model.indexer.IndexingStatus; +import org.opengroup.osdu.core.common.model.indexer.JobStatus; +import org.opengroup.osdu.core.common.model.indexer.OperationType; +import org.opengroup.osdu.core.common.model.indexer.RecordInfo; +import org.opengroup.osdu.core.common.model.indexer.RecordQueryResponse; +import org.opengroup.osdu.core.common.model.indexer.RecordReindexRequest; import org.opengroup.osdu.core.common.model.indexer.Records; import org.opengroup.osdu.core.common.provider.interfaces.IRequestInfo; import org.opengroup.osdu.indexer.config.IndexerConfigurationProperties; +import org.springframework.http.HttpStatus; +import org.springframework.test.context.junit4.SpringRunner; +import java.lang.reflect.Type; import java.net.URISyntaxException; +import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import static java.util.Collections.singletonList; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@RunWith(MockitoJUnitRunner.class) +@RunWith(SpringRunner.class) public class StorageServiceImplTest { - - @Spy - private ObjectMapper objectMapper = new ObjectMapper(); @Mock private IUrlFetchService urlFetchService; @Mock + private JobStatus jobStatus; + @Mock + private JaxRsDpsLog log; + @Mock private IRequestInfo requestInfo; @Mock private IndexerConfigurationProperties configurationProperties; + @Spy + private ObjectMapper objectMapper = new ObjectMapper(); @InjectMocks private StorageServiceImpl sut; + private List<String> ids; + private static final String RECORD_ID1 = "tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465"; + private static final String RECORDS_ID2 = "tenant1:doc:15e790a69beb4d789b1f979e2af2e813"; + + @Before + public void setup() { + + String recordChangedMessages = "[{\"id\":\"tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465\",\"kind\":\"tenant1:testindexer1528919679710:well:1.0.0\",\"op\":\"purge\"}," + + "{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\",\"kind\":\"tenant1:testindexer1528919679710:well:1.0.0\",\"op\":\"create\"}]"; + + when(this.requestInfo.getHeadersMap()).thenReturn(new HashMap<>()); + when(this.requestInfo.getHeaders()).thenReturn(new DpsHeaders()); + + Type listType = new TypeToken<List<RecordInfo>>() { + }.getType(); + + List<RecordInfo> msgs = (new Gson()).fromJson(recordChangedMessages, listType); + jobStatus.initialize(msgs); + ids = Arrays.asList(RECORD_ID1, RECORDS_ID2); + + when(configurationProperties.getStorageRecordsBatchSize()).thenReturn(20); + } + @Test public void should_parse_long_integer_values_as_integer_types() throws URISyntaxException { when(this.requestInfo.getHeaders()).thenReturn(new DpsHeaders()); - String body = "{\"records\":[{\"id\":\"id1\",\"version\":0,\"data\":{\"long_int\":1000000000000000000000000,\"int\":123}}],\"notFound\":[],\"conversionStatuses\":[],\"missingRetryRecords\":[]}"; + String body = "{\"records\":[{\"id\":\"id1\",\"kind\":\"tenant:test:test:1.0.0\",\"version\":0,\"data\":{\"long_int\":1000000000000000000000000,\"int\":123}}],\"notFound\":[],\"conversionStatuses\":[],\"missingRetryRecords\":[]}"; + Map<String, String> recordChangedMap = new HashMap<>(); + Map<String, String> validRecordKindPatchMap = new HashMap<>(); + recordChangedMap.put("id1", "tenant:test:test:1.0.0"); HttpResponse httpResponse = mock(HttpResponse.class); when(httpResponse.getBody()).thenReturn(body); when(this.urlFetchService.sendRequest(any())).thenReturn(httpResponse); - Records rec = sut.getRecords(Collections.singletonList("id1")); + Records rec = sut.getRecords(Collections.singletonList("id1"), recordChangedMap, validRecordKindPatchMap); assertEquals(1, rec.getRecords().size()); assertEquals("1000000000000000000000000", rec.getRecords().get(0).getData().get("long_int").toString()); assertEquals("123", rec.getRecords().get(0).getData().get("int").toString()); } + + @Test + public void should_return404_givenNullData_getValidStorageRecordsTest() throws URISyntaxException { + + HttpResponse httpResponse = mock(HttpResponse.class); + when(httpResponse.getBody()).thenReturn(null); + + when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); + + should_return404_getValidStorageRecordsTest(); + } + + @Test + public void should_return404_givenEmptyData_getValidStorageRecordsTest() throws URISyntaxException { + + String emptyDataFromStorage = "{\"records\":[],\"notFound\":[]}"; + + HttpResponse httpResponse = mock(HttpResponse.class); + when(httpResponse.getBody()).thenReturn(emptyDataFromStorage); + + when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); + + should_return404_getValidStorageRecordsTest(); + } + + @Test + public void should_returnOneValidRecords_givenValidData_getValidStorageRecordsTest() throws URISyntaxException { + + String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[\"invalid1\"], \"conversionStatuses\": []}"; + List<RecordInfo> recordChangeInfos = Arrays.asList(RecordInfo.builder().id("testid").kind("tenant:test:test:1.0.0").op(OperationType.create.getValue()).build()); + + HttpResponse httpResponse = mock(HttpResponse.class); + when(httpResponse.getBody()).thenReturn(validDataFromStorage); + + when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); + Records storageRecords = this.sut.getStorageRecords(ids, recordChangeInfos); + + assertEquals(1, storageRecords.getRecords().size()); + } + + @Test + public void should_returnOneValidRecords_givenRecord_withValidKindUpdate_getStorageRecordsTest() throws URISyntaxException { + + String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.2.0\"}],\"notFound\":[], \"conversionStatuses\": []}"; + List<RecordInfo> recordChangeInfos = Arrays.asList(RecordInfo.builder().id("testid").kind("tenant:test:test:1.2.0").op(OperationType.update.getValue()).previousVersionKind("tenant:test:test:1.1.0").build()); + + HttpResponse httpResponse = mock(HttpResponse.class); + when(httpResponse.getBody()).thenReturn(validDataFromStorage); + + when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); + Records storageRecords = this.sut.getStorageRecords(ids, recordChangeInfos); + + assertEquals(1, storageRecords.getRecords().size()); + } + + @Test + public void should_returnZeroRecords_givenStaleMessage_getStorageRecordsTest() throws URISyntaxException { + + String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.2.0\"}],\"notFound\":[], \"conversionStatuses\": []}"; + List<RecordInfo> recordChangeInfos = Arrays.asList(RecordInfo.builder().id("testid").kind("tenant:test:test:1.1.0").op(OperationType.update.getValue()).build()); + + HttpResponse httpResponse = mock(HttpResponse.class); + when(httpResponse.getBody()).thenReturn(validDataFromStorage); + + when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); + Records storageRecords = this.sut.getStorageRecords(ids, recordChangeInfos); + + assertEquals(0, storageRecords.getRecords().size()); + verify(this.log).warning("stale records found with older kind, skipping indexing | record ids: testid"); + } + + @Test + public void should_logMissingRecord_given_storageMissedRecords() throws URISyntaxException { + + String validDataFromStorage = "{\"records\":[{\"id\":\"tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[]}"; + List<RecordInfo> recordChangeInfos = Arrays.asList(RecordInfo.builder().id("tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465").kind("tenant:test:test:1.0.0").op(OperationType.update.getValue()).build()); + + HttpResponse httpResponse = mock(HttpResponse.class); + when(httpResponse.getBody()).thenReturn(validDataFromStorage); + + when(this.urlFetchService.sendRequest(any())).thenReturn(httpResponse); + Records storageRecords = this.sut.getStorageRecords(ids, recordChangeInfos); + + assertEquals(1, storageRecords.getRecords().size()); + verify(this.jobStatus).addOrUpdateRecordStatus(singletonList(RECORDS_ID2), IndexingStatus.FAIL, HttpStatus.NOT_FOUND.value(), "Partial response received from Storage service - missing records", "Partial response received from Storage service: tenant1:doc:15e790a69beb4d789b1f979e2af2e813"); + } + + @Test + public void should_returnValidJobStatus_givenFailedUnitsConversion_processRecordChangedMessageTest() throws URISyntaxException { + String validDataFromStorage = "{\"records\":[{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[],\"conversionStatuses\":[{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\",\"status\":\"ERROR\",\"errors\":[\"crs conversion failed\"]}]}"; + List<RecordInfo> recordChangeInfos = Arrays.asList(RecordInfo.builder().id("tenant1:doc:15e790a69beb4d789b1f979e2af2e813").kind("tenant:test:test:1.0.0").op(OperationType.update.getValue()).build()); + + HttpResponse httpResponse = mock(HttpResponse.class); + when(httpResponse.getBody()).thenReturn(validDataFromStorage); + + when(this.urlFetchService.sendRequest(any())).thenReturn(httpResponse); + Records storageRecords = this.sut.getStorageRecords(singletonList(RECORDS_ID2), recordChangeInfos); + + assertEquals(1, storageRecords.getRecords().size()); + verify(this.jobStatus).addOrUpdateRecordStatus(RECORDS_ID2, IndexingStatus.WARN, HttpStatus.BAD_REQUEST.value(), "crs conversion failed", String.format("record-id: %s | %s", "tenant1:doc:15e790a69beb4d789b1f979e2af2e813", "crs conversion failed")); + } + + @Test + public void should_returnValidResponse_givenValidRecordQueryRequest_getRecordListByKind() throws Exception { + + RecordReindexRequest recordReindexRequest = RecordReindexRequest.builder().kind("tenant:test:test:1.0.0").cursor("100").build(); + + HttpResponse httpResponse = new HttpResponse(); + httpResponse.setBody(new Gson().toJson(recordReindexRequest, RecordReindexRequest.class)); + + when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); + + RecordQueryResponse recordQueryResponse = this.sut.getRecordsByKind(recordReindexRequest); + + assertEquals("100", recordQueryResponse.getCursor()); + assertNull(recordQueryResponse.getResults()); + } + + @Test + public void should_returnValidResponse_givenValidKind_getSchemaByKind() throws Exception { + + String validSchemaFromStorage = "{" + + " \"kind\": \"tenant:test:test:1.0.0\"," + + " \"schema\": [" + + " {" + + " \"path\": \"msg\"," + + " \"kind\": \"string\"" + + " }," + + " {" + + " \"path\": \"references.entity\"," + + " \"kind\": \"string\"" + + " }" + + " ]," + + " \"ext\": null" + + "}"; + String kind = "tenant:test:test:1.0.0"; + + HttpResponse httpResponse = new HttpResponse(); + httpResponse.setResponseCode(HttpStatus.OK.value()); + httpResponse.setBody(validSchemaFromStorage); + + when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); + + String recordSchemaResponse = this.sut.getStorageSchema(kind); + + assertNotNull(recordSchemaResponse); + } + + @Test + public void should_returnNullResponse_givenAbsentKind_getSchemaByKind() throws Exception { + + String kind = "tenant:test:test:1.0.0"; + + HttpResponse httpResponse = new HttpResponse(); + httpResponse.setResponseCode(HttpStatus.NOT_FOUND.value()); + + when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); + + String recordSchemaResponse = this.sut.getStorageSchema(kind); + + assertNull(recordSchemaResponse); + } + + @Test + public void should_returnOneValidRecords_givenValidData_getValidStorageRecordsWithInvalidConversionTest() throws URISyntaxException { + + String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[\"invalid1\"],\"conversionStatuses\": [{\"id\":\"testid\",\"status\":\"ERROR\",\"errors\":[\"conversion error occurred\"] } ]}"; + List<RecordInfo> recordChangeInfos = Arrays.asList(RecordInfo.builder().id("testid").kind("tenant:test:test:1.0.0").op(OperationType.update.getValue()).build()); + + HttpResponse httpResponse = mock(HttpResponse.class); + when(httpResponse.getBody()).thenReturn(validDataFromStorage); + + when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); + Records storageRecords = this.sut.getStorageRecords(ids, recordChangeInfos); + + assertEquals(1, storageRecords.getRecords().size()); + + assertEquals(1, storageRecords.getConversionStatuses().get(0).getErrors().size()); + + assertEquals("conversion error occurred", storageRecords.getConversionStatuses().get(0).getErrors().get(0)); + } + + private void should_return404_getValidStorageRecordsTest() { + List<RecordInfo> recordChangeInfos = Arrays.asList(RecordInfo.builder().id("testid").kind("tenant:test:test:1.0.0").op(OperationType.update.getValue()).build()); + try { + this.sut.getStorageRecords(ids, recordChangeInfos); + fail("Should throw exception"); + } catch (AppException e) { + assertEquals(HttpStatus.NOT_FOUND.value(), e.getError().getCode()); + } catch (Exception e) { + fail("Should not throw this exception" + e.getMessage()); + } + } } \ No newline at end of file diff --git a/provider/indexer-azure/src/test/java/org/opengroup/osdu/indexer/azure/service/StorageServiceTest.java b/provider/indexer-azure/src/test/java/org/opengroup/osdu/indexer/azure/service/StorageServiceTest.java deleted file mode 100644 index 218488386affee78476390c4ba1081774ce6a3a5..0000000000000000000000000000000000000000 --- a/provider/indexer-azure/src/test/java/org/opengroup/osdu/indexer/azure/service/StorageServiceTest.java +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright 2017-2019, Schlumberger -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package org.opengroup.osdu.indexer.azure.service; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentMatchers; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.opengroup.osdu.core.common.model.indexer.IndexingStatus; -import org.opengroup.osdu.core.common.model.indexer.RecordInfo; -import org.opengroup.osdu.core.common.model.indexer.RecordQueryResponse; -import org.opengroup.osdu.core.common.model.indexer.RecordReindexRequest; -import org.opengroup.osdu.core.common.model.indexer.Records; -import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; -import org.opengroup.osdu.indexer.service.StorageServiceImpl; -import org.opengroup.osdu.core.common.model.indexer.JobStatus; -import org.opengroup.osdu.core.common.model.http.HttpResponse; -import org.opengroup.osdu.core.common.provider.interfaces.IRequestInfo; -import org.opengroup.osdu.core.common.http.IUrlFetchService; -import org.opengroup.osdu.core.common.model.http.AppException; -import org.springframework.http.HttpStatus; -import org.springframework.test.context.junit4.SpringRunner; - -import java.lang.reflect.Type; -import java.net.URISyntaxException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; - -import static java.util.Collections.singletonList; -import static org.junit.Assert.*; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.powermock.api.mockito.PowerMockito.when; - -@Ignore -@RunWith(SpringRunner.class) -public class StorageServiceTest { - - @Mock - private IUrlFetchService urlFetchService; - @Mock - private JobStatus jobStatus; - @Mock - private JaxRsDpsLog log; - @Mock - private IRequestInfo requestInfo; - @InjectMocks - private StorageServiceImpl sut; - - private List<String> ids; - private static final String RECORD_ID1 = "tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465"; - private static final String RECORDS_ID2 = "tenant1:doc:15e790a69beb4d789b1f979e2af2e813"; - - @Before - public void setup() { - - String recordChangedMessages = "[{\"id\":\"tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465\",\"kind\":\"tenant1:testindexer1528919679710:well:1.0.0\",\"op\":\"purge\"}," + - "{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\",\"kind\":\"tenant1:testindexer1528919679710:well:1.0.0\",\"op\":\"create\"}]"; - - when(this.requestInfo.getHeadersMap()).thenReturn(new HashMap<>()); - - Type listType = new TypeToken<List<RecordInfo>>() {}.getType(); - - List<RecordInfo> msgs = (new Gson()).fromJson(recordChangedMessages, listType); - jobStatus.initialize(msgs); - ids = Arrays.asList(RECORD_ID1, RECORDS_ID2); - } - - @Test - public void should_return404_givenNullData_getValidStorageRecordsTest() throws URISyntaxException { - - HttpResponse httpResponse = mock(HttpResponse.class); - Mockito.when(httpResponse.getBody()).thenReturn(null); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - - should_return404_getValidStorageRecordsTest(); - } - - @Test - public void should_return404_givenEmptyData_getValidStorageRecordsTest() throws URISyntaxException { - - String emptyDataFromStorage = "{\"records\":[],\"notFound\":[]}"; - - HttpResponse httpResponse = mock(HttpResponse.class); - Mockito.when(httpResponse.getBody()).thenReturn(emptyDataFromStorage); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - - should_return404_getValidStorageRecordsTest(); - } - - @Test - public void should_returnOneValidRecords_givenValidData_getValidStorageRecordsTest() throws URISyntaxException { - - String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[\"invalid1\"]}"; - - HttpResponse httpResponse = mock(HttpResponse.class); - Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - Records storageRecords = this.sut.getStorageRecords(ids); - - assertEquals(1, storageRecords.getRecords().size()); - } - - @Test - public void should_logMissingRecord_given_storageMissedRecords() throws URISyntaxException { - - String validDataFromStorage = "{\"records\":[{\"id\":\"tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[]}"; - - HttpResponse httpResponse = mock(HttpResponse.class); - Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage); - - when(this.urlFetchService.sendRequest(any())).thenReturn(httpResponse); - Records storageRecords = this.sut.getStorageRecords(ids); - - assertEquals(1, storageRecords.getRecords().size()); - verify(this.jobStatus).addOrUpdateRecordStatus(singletonList(RECORDS_ID2), IndexingStatus.FAIL, org.apache.http.HttpStatus.SC_NOT_FOUND, "Partial response received from Storage service - missing records", "Partial response received from Storage service: tenant1:doc:15e790a69beb4d789b1f979e2af2e813"); - } - - @Test - public void should_returnValidJobStatus_givenFailedUnitsConversion_processRecordChangedMessageTest() throws URISyntaxException { - String validDataFromStorage = "{\"records\":[{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[],\"conversionStatuses\":[{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\",\"status\":\"ERROR\",\"errors\":[\"crs conversion failed\"]}]}"; - - HttpResponse httpResponse = mock(HttpResponse.class); - Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage); - - when(this.urlFetchService.sendRequest(any())).thenReturn(httpResponse); - Records storageRecords = this.sut.getStorageRecords(singletonList("tenant1:doc:15e790a69beb4d789b1f979e2af2e813")); - - assertEquals(1, storageRecords.getRecords().size()); - verify(this.jobStatus).addOrUpdateRecordStatus("tenant1:doc:15e790a69beb4d789b1f979e2af2e813", IndexingStatus.WARN, org.apache.http.HttpStatus.SC_BAD_REQUEST, "crs conversion failed", String.format("record-id: %s | %s", "tenant1:doc:15e790a69beb4d789b1f979e2af2e813", "crs conversion failed")); - } - - @Test - public void should_returnValidResponse_givenValidRecordQueryRequest_getRecordListByKind() throws Exception { - - RecordReindexRequest recordReindexRequest = RecordReindexRequest.builder().kind("tenant:test:test:1.0.0").cursor("100").build(); - - HttpResponse httpResponse = new HttpResponse(); - httpResponse.setBody(new Gson().toJson(recordReindexRequest, RecordReindexRequest.class)); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - - RecordQueryResponse recordQueryResponse = this.sut.getRecordsByKind(recordReindexRequest); - - assertEquals("100", recordQueryResponse.getCursor()); - assertNull(recordQueryResponse.getResults()); - } - - @Test - public void should_returnValidResponse_givenValidKind_getSchemaByKind() throws Exception { - - String validSchemaFromStorage = "{" + - " \"kind\": \"tenant:test:test:1.0.0\"," + - " \"schema\": [" + - " {" + - " \"path\": \"msg\"," + - " \"kind\": \"string\"" + - " }," + - " {" + - " \"path\": \"references.entity\"," + - " \"kind\": \"string\"" + - " }" + - " ]," + - " \"ext\": null" + - "}"; - String kind = "tenant:test:test:1.0.0"; - - HttpResponse httpResponse = new HttpResponse(); - httpResponse.setResponseCode(HttpStatus.OK.value()); - httpResponse.setBody(validSchemaFromStorage); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - - String recordSchemaResponse = this.sut.getStorageSchema(kind); - - assertNotNull(recordSchemaResponse); - } - - @Test - public void should_returnNullResponse_givenAbsentKind_getSchemaByKind() throws Exception { - - String kind = "tenant:test:test:1.0.0"; - - HttpResponse httpResponse = new HttpResponse(); - httpResponse.setResponseCode(HttpStatus.NOT_FOUND.value()); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - - String recordSchemaResponse = this.sut.getStorageSchema(kind); - - assertNull(recordSchemaResponse); - } - - @Test - public void should_returnOneValidRecords_givenValidData_getValidStorageRecordsWithInvalidConversionTest() throws URISyntaxException { - - String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[\"invalid1\"],\"conversionStatuses\": [{\"id\":\"testid\",\"status\":\"ERROR\",\"errors\":[\"conversion error occurred\"] } ]}"; - - HttpResponse httpResponse = mock(HttpResponse.class); - Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - Records storageRecords = this.sut.getStorageRecords(ids); - - assertEquals(1, storageRecords.getRecords().size()); - - assertEquals(1, storageRecords.getConversionStatuses().get(0).getErrors().size()); - - assertEquals("conversion error occurred", storageRecords.getConversionStatuses().get(0).getErrors().get(0)); - } - - private void should_return404_getValidStorageRecordsTest() { - try { - this.sut.getStorageRecords(ids); - fail("Should throw exception"); - } catch (AppException e) { - assertEquals(HttpStatus.NOT_FOUND.value(), e.getError().getCode()); - } catch (Exception e) { - fail("Should not throw this exception" + e.getMessage()); - } - } -} diff --git a/provider/indexer-gc/src/test/java/org/opengroup/osdu/indexer/service/StorageServiceTest.java b/provider/indexer-gc/src/test/java/org/opengroup/osdu/indexer/service/StorageServiceTest.java deleted file mode 100644 index 3ff767ebe5c4f5cb638cef9eeb8e440eecd7db19..0000000000000000000000000000000000000000 --- a/provider/indexer-gc/src/test/java/org/opengroup/osdu/indexer/service/StorageServiceTest.java +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright 2017-2019, Schlumberger -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package org.opengroup.osdu.indexer.service; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentMatchers; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.Spy; -import org.opengroup.osdu.core.common.model.http.DpsHeaders; -import org.opengroup.osdu.core.common.model.http.AppException; -import org.opengroup.osdu.core.common.model.indexer.IndexingStatus; -import org.opengroup.osdu.core.common.model.indexer.JobStatus; -import org.opengroup.osdu.core.common.model.indexer.RecordInfo; -import org.opengroup.osdu.core.common.model.http.HttpResponse; -import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; -import org.opengroup.osdu.core.common.provider.interfaces.IRequestInfo; -import org.opengroup.osdu.core.common.http.IUrlFetchService; -import org.opengroup.osdu.core.common.model.indexer.RecordQueryResponse; -import org.opengroup.osdu.core.common.model.indexer.RecordReindexRequest; -import org.opengroup.osdu.core.common.model.indexer.Records; -import org.opengroup.osdu.indexer.config.IndexerConfigurationProperties; -import org.springframework.http.HttpStatus; -import org.springframework.test.context.junit4.SpringRunner; - -import java.lang.reflect.Type; -import java.net.URISyntaxException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; - -import static java.util.Collections.singletonList; -import static org.junit.Assert.*; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.powermock.api.mockito.PowerMockito.when; - -@RunWith(SpringRunner.class) -public class StorageServiceTest { - - @Mock - private IUrlFetchService urlFetchService; - @Mock - private JobStatus jobStatus; - @Mock - private JaxRsDpsLog log; - @Mock - private IRequestInfo requestInfo; - @Mock - private IndexerConfigurationProperties configurationProperties; - @Spy - private ObjectMapper objectMapper = new ObjectMapper(); - @InjectMocks - private StorageServiceImpl sut; - - private List<String> ids; - private static final String RECORD_ID1 = "tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465"; - private static final String RECORDS_ID2 = "tenant1:doc:15e790a69beb4d789b1f979e2af2e813"; - - @Before - public void setup() { - - String recordChangedMessages = "[{\"id\":\"tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465\",\"kind\":\"tenant1:testindexer1528919679710:well:1.0.0\",\"op\":\"purge\"}," + - "{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\",\"kind\":\"tenant1:testindexer1528919679710:well:1.0.0\",\"op\":\"create\"}]"; - - when(this.requestInfo.getHeadersMap()).thenReturn(new HashMap<>()); - when(this.requestInfo.getHeaders()).thenReturn(new DpsHeaders()); - - Type listType = new TypeToken<List<RecordInfo>>() {}.getType(); - - List<RecordInfo> msgs = (new Gson()).fromJson(recordChangedMessages, listType); - jobStatus.initialize(msgs); - ids = Arrays.asList(RECORD_ID1, RECORDS_ID2); - - when(configurationProperties.getStorageRecordsBatchSize()).thenReturn(20); - } - - @Test - public void should_return404_givenNullData_getValidStorageRecordsTest() throws URISyntaxException { - - HttpResponse httpResponse = mock(HttpResponse.class); - Mockito.when(httpResponse.getBody()).thenReturn(null); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - - should_return404_getValidStorageRecordsTest(); - } - - @Test - public void should_return404_givenEmptyData_getValidStorageRecordsTest() throws URISyntaxException { - - String emptyDataFromStorage = "{\"records\":[],\"notFound\":[]}"; - - HttpResponse httpResponse = mock(HttpResponse.class); - Mockito.when(httpResponse.getBody()).thenReturn(emptyDataFromStorage); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - - should_return404_getValidStorageRecordsTest(); - } - - @Test - public void should_returnOneValidRecords_givenValidData_getValidStorageRecordsTest() throws URISyntaxException { - - String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[\"invalid1\"], \"conversionStatuses\": []}"; - - HttpResponse httpResponse = mock(HttpResponse.class); - Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - Records storageRecords = this.sut.getStorageRecords(ids); - - assertEquals(1, storageRecords.getRecords().size()); - } - - @Test - public void should_logMissingRecord_given_storageMissedRecords() throws URISyntaxException { - - String validDataFromStorage = "{\"records\":[{\"id\":\"tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[]}"; - - HttpResponse httpResponse = mock(HttpResponse.class); - Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage); - - when(this.urlFetchService.sendRequest(any())).thenReturn(httpResponse); - Records storageRecords = this.sut.getStorageRecords(ids); - - assertEquals(1, storageRecords.getRecords().size()); - verify(this.jobStatus).addOrUpdateRecordStatus(singletonList(RECORDS_ID2), IndexingStatus.FAIL, HttpStatus.NOT_FOUND.value(), "Partial response received from Storage service - missing records", "Partial response received from Storage service: tenant1:doc:15e790a69beb4d789b1f979e2af2e813"); - } - - @Test - public void should_returnValidJobStatus_givenFailedUnitsConversion_processRecordChangedMessageTest() throws URISyntaxException { - String validDataFromStorage = "{\"records\":[{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[],\"conversionStatuses\":[{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\",\"status\":\"ERROR\",\"errors\":[\"crs conversion failed\"]}]}"; - - HttpResponse httpResponse = mock(HttpResponse.class); - Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage); - - when(this.urlFetchService.sendRequest(any())).thenReturn(httpResponse); - Records storageRecords = this.sut.getStorageRecords(singletonList(RECORDS_ID2)); - - assertEquals(1, storageRecords.getRecords().size()); - verify(this.jobStatus).addOrUpdateRecordStatus(RECORDS_ID2, IndexingStatus.WARN, HttpStatus.BAD_REQUEST.value(), "crs conversion failed", String.format("record-id: %s | %s", "tenant1:doc:15e790a69beb4d789b1f979e2af2e813", "crs conversion failed")); - } - - @Test - public void should_returnValidResponse_givenValidRecordQueryRequest_getRecordListByKind() throws Exception { - - RecordReindexRequest recordReindexRequest = RecordReindexRequest.builder().kind("tenant:test:test:1.0.0").cursor("100").build(); - - HttpResponse httpResponse = new HttpResponse(); - httpResponse.setBody(new Gson().toJson(recordReindexRequest, RecordReindexRequest.class)); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - - RecordQueryResponse recordQueryResponse = this.sut.getRecordsByKind(recordReindexRequest); - - assertEquals("100", recordQueryResponse.getCursor()); - assertNull(recordQueryResponse.getResults()); - } - - @Test - public void should_returnValidResponse_givenValidKind_getSchemaByKind() throws Exception { - - String validSchemaFromStorage = "{" + - " \"kind\": \"tenant:test:test:1.0.0\"," + - " \"schema\": [" + - " {" + - " \"path\": \"msg\"," + - " \"kind\": \"string\"" + - " }," + - " {" + - " \"path\": \"references.entity\"," + - " \"kind\": \"string\"" + - " }" + - " ]," + - " \"ext\": null" + - "}"; - String kind = "tenant:test:test:1.0.0"; - - HttpResponse httpResponse = new HttpResponse(); - httpResponse.setResponseCode(HttpStatus.OK.value()); - httpResponse.setBody(validSchemaFromStorage); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - - String recordSchemaResponse = this.sut.getStorageSchema(kind); - - assertNotNull(recordSchemaResponse); - } - - @Test - public void should_returnNullResponse_givenAbsentKind_getSchemaByKind() throws Exception { - - String kind = "tenant:test:test:1.0.0"; - - HttpResponse httpResponse = new HttpResponse(); - httpResponse.setResponseCode(HttpStatus.NOT_FOUND.value()); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - - String recordSchemaResponse = this.sut.getStorageSchema(kind); - - assertNull(recordSchemaResponse); - } - - @Test - public void should_returnOneValidRecords_givenValidData_getValidStorageRecordsWithInvalidConversionTest() throws URISyntaxException { - - String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[\"invalid1\"],\"conversionStatuses\": [{\"id\":\"testid\",\"status\":\"ERROR\",\"errors\":[\"conversion error occurred\"] } ]}"; - - HttpResponse httpResponse = mock(HttpResponse.class); - Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - Records storageRecords = this.sut.getStorageRecords(ids); - - assertEquals(1, storageRecords.getRecords().size()); - - assertEquals(1, storageRecords.getConversionStatuses().get(0).getErrors().size()); - - assertEquals("conversion error occurred", storageRecords.getConversionStatuses().get(0).getErrors().get(0)); - } - - private void should_return404_getValidStorageRecordsTest() { - try { - this.sut.getStorageRecords(ids); - fail("Should throw exception"); - } catch (AppException e) { - assertEquals(HttpStatus.NOT_FOUND.value(), e.getError().getCode()); - } catch (Exception e) { - fail("Should not throw this exception" + e.getMessage()); - } - } -} diff --git a/provider/indexer-ibm/src/test/java/org/opengroup/osdu/indexer/ibm/service/StorageServiceTest.java b/provider/indexer-ibm/src/test/java/org/opengroup/osdu/indexer/ibm/service/StorageServiceTest.java deleted file mode 100644 index dfbdb4396509ef1678d845fa12f1b9515654c120..0000000000000000000000000000000000000000 --- a/provider/indexer-ibm/src/test/java/org/opengroup/osdu/indexer/ibm/service/StorageServiceTest.java +++ /dev/null @@ -1,219 +0,0 @@ -/* Licensed Materials - Property of IBM */ -/* (c) Copyright IBM Corp. 2020. All Rights Reserved.*/ - -package org.opengroup.osdu.indexer.ibm.service; - -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentMatchers; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.opengroup.osdu.core.common.model.indexer.IndexingStatus; -import org.opengroup.osdu.core.common.model.indexer.RecordInfo; -import org.opengroup.osdu.core.common.model.indexer.RecordQueryResponse; -import org.opengroup.osdu.core.common.model.indexer.RecordReindexRequest; -import org.opengroup.osdu.core.common.model.indexer.Records; -import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; -import org.opengroup.osdu.indexer.service.StorageServiceImpl; -import org.opengroup.osdu.core.common.model.indexer.JobStatus; -import org.opengroup.osdu.core.common.model.http.HttpResponse; -import org.opengroup.osdu.core.common.provider.interfaces.IRequestInfo; -import org.opengroup.osdu.core.common.http.IUrlFetchService; -import org.opengroup.osdu.core.common.model.http.AppException; -import org.springframework.http.HttpStatus; -import org.springframework.test.context.junit4.SpringRunner; - -import java.lang.reflect.Type; -import java.net.URISyntaxException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; - -import static java.util.Collections.singletonList; -import static org.junit.Assert.*; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.powermock.api.mockito.PowerMockito.when; - -@Ignore -@RunWith(SpringRunner.class) -public class StorageServiceTest { - - @Mock - private IUrlFetchService urlFetchService; - @Mock - private JobStatus jobStatus; - @Mock - private JaxRsDpsLog log; - @Mock - private IRequestInfo requestInfo; - @InjectMocks - private StorageServiceImpl sut; - - private List<String> ids; - private static final String RECORD_ID1 = "tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465"; - private static final String RECORDS_ID2 = "tenant1:doc:15e790a69beb4d789b1f979e2af2e813"; - - @Before - public void setup() { - - String recordChangedMessages = "[{\"id\":\"tenant1:doc:1dbf528e0e0549cab7a08f29fbfc8465\",\"kind\":\"tenant1:testindexer1528919679710:well:1.0.0\",\"op\":\"purge\"}," + - "{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\",\"kind\":\"tenant1:testindexer1528919679710:well:1.0.0\",\"op\":\"create\"}]"; - - when(this.requestInfo.getHeadersMap()).thenReturn(new HashMap<>()); - - Type listType = new TypeToken<List<RecordInfo>>() {}.getType(); - - List<RecordInfo> msgs = (new Gson()).fromJson(recordChangedMessages, listType); - jobStatus.initialize(msgs); - ids = Arrays.asList(RECORD_ID1, RECORDS_ID2); - } - - @Test - public void should_return404_givenNullData_getValidStorageRecordsTest() throws URISyntaxException { - - HttpResponse httpResponse = mock(HttpResponse.class); - Mockito.when(httpResponse.getBody()).thenReturn(null); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - - should_return404_getValidStorageRecordsTest(); - } - - @Test - public void should_return404_givenEmptyData_getValidStorageRecordsTest() throws URISyntaxException { - - String emptyDataFromStorage = "{\"records\":[],\"notFound\":[]}"; - - HttpResponse httpResponse = mock(HttpResponse.class); - Mockito.when(httpResponse.getBody()).thenReturn(emptyDataFromStorage); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - - should_return404_getValidStorageRecordsTest(); - } - - @Test - public void should_returnOneValidRecords_givenValidData_getValidStorageRecordsTest() throws URISyntaxException { - - String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[\"invalid1\"]}"; - - HttpResponse httpResponse = mock(HttpResponse.class); - Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - Records storageRecords = this.sut.getStorageRecords(ids); - - assertEquals(1, storageRecords.getRecords().size()); - } - - @Test - public void should_returnValidResponse_givenValidRecordQueryRequest_getRecordListByKind() throws Exception { - - RecordReindexRequest recordReindexRequest = RecordReindexRequest.builder().kind("tenant:test:test:1.0.0").cursor("100").build(); - - HttpResponse httpResponse = new HttpResponse(); - httpResponse.setBody(new Gson().toJson(recordReindexRequest, RecordReindexRequest.class)); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - - RecordQueryResponse recordQueryResponse = this.sut.getRecordsByKind(recordReindexRequest); - - assertEquals("100", recordQueryResponse.getCursor()); - assertNull(recordQueryResponse.getResults()); - } - - @Test - public void should_returnValidJobStatus_givenFailedUnitsConversion_processRecordChangedMessageTest() throws URISyntaxException { - String validDataFromStorage = "{\"records\":[{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[],\"conversionStatuses\":[{\"id\":\"tenant1:doc:15e790a69beb4d789b1f979e2af2e813\",\"status\":\"ERROR\",\"errors\":[\"crs conversion failed\"]}]}"; - - HttpResponse httpResponse = mock(HttpResponse.class); - Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage); - - when(this.urlFetchService.sendRequest(any())).thenReturn(httpResponse); - Records storageRecords = this.sut.getStorageRecords(singletonList("tenant1:doc:15e790a69beb4d789b1f979e2af2e813")); - - assertEquals(1, storageRecords.getRecords().size()); - verify(this.jobStatus).addOrUpdateRecordStatus(RECORDS_ID2, IndexingStatus.WARN, HttpStatus.BAD_REQUEST.value(), "crs conversion failed", String.format("record-id: %s | %s", "tenant1:doc:15e790a69beb4d789b1f979e2af2e813", "crs conversion failed")); - } - - @Test - public void should_returnValidResponse_givenValidKind_getSchemaByKind() throws Exception { - - String validSchemaFromStorage = "{" + - " \"kind\": \"tenant:test:test:1.0.0\"," + - " \"schema\": [" + - " {" + - " \"path\": \"msg\"," + - " \"kind\": \"string\"" + - " }," + - " {" + - " \"path\": \"references.entity\"," + - " \"kind\": \"string\"" + - " }" + - " ]," + - " \"ext\": null" + - "}"; - String kind = "tenant:test:test:1.0.0"; - - HttpResponse httpResponse = new HttpResponse(); - httpResponse.setResponseCode(HttpStatus.OK.value()); - httpResponse.setBody(validSchemaFromStorage); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - - String recordSchemaResponse = this.sut.getStorageSchema(kind); - - assertNotNull(recordSchemaResponse); - } - - @Test - public void should_returnNullResponse_givenAbsentKind_getSchemaByKind() throws Exception { - - String kind = "tenant:test:test:1.0.0"; - - HttpResponse httpResponse = new HttpResponse(); - httpResponse.setResponseCode(HttpStatus.NOT_FOUND.value()); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - - String recordSchemaResponse = this.sut.getStorageSchema(kind); - - assertNull(recordSchemaResponse); - } - - @Test - public void should_returnOneValidRecords_givenValidData_getValidStorageRecordsWithInvalidConversionTest() throws URISyntaxException { - - String validDataFromStorage = "{\"records\":[{\"id\":\"testid\", \"version\":1, \"kind\":\"tenant:test:test:1.0.0\"}],\"notFound\":[\"invalid1\"],\"conversionStatuses\": [{\"id\":\"testid\",\"status\":\"ERROR\",\"errors\":[\"conversion error occurred\"] } ]}"; - - HttpResponse httpResponse = mock(HttpResponse.class); - Mockito.when(httpResponse.getBody()).thenReturn(validDataFromStorage); - - when(this.urlFetchService.sendRequest(ArgumentMatchers.any())).thenReturn(httpResponse); - Records storageRecords = this.sut.getStorageRecords(ids); - - assertEquals(1, storageRecords.getRecords().size()); - - assertEquals(1, storageRecords.getConversionStatuses().get(0).getErrors().size()); - - assertEquals("conversion error occurred", storageRecords.getConversionStatuses().get(0).getErrors().get(0)); - } - - private void should_return404_getValidStorageRecordsTest() { - try { - this.sut.getStorageRecords(ids); - fail("Should throw exception"); - } catch (AppException e) { - assertEquals(HttpStatus.NOT_FOUND, e.getError().getCode()); - } catch (Exception e) { - fail("Should not throw this exception" + e.getMessage()); - } - } -}