diff --git a/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/AddUDlResponse.java b/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/AddUDlResponse.java index 5bca12d1f..7dd7c0e38 100644 --- a/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/AddUDlResponse.java +++ b/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/AddUDlResponse.java @@ -17,8 +17,10 @@ package org.nzbhydra.downloading.downloaders.torbox.mapping; import lombok.Data; +import org.nzbhydra.springnative.ReflectionMarker; @Data +@ReflectionMarker public class AddUDlResponse implements UsenetResponse { private boolean success; private String error; diff --git a/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/TorboxAddUdlData.java b/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/TorboxAddUdlData.java index 2da019bc9..a8fcfe998 100644 --- a/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/TorboxAddUdlData.java +++ b/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/TorboxAddUdlData.java @@ -17,8 +17,10 @@ package org.nzbhydra.downloading.downloaders.torbox.mapping; import lombok.Data; +import org.nzbhydra.springnative.ReflectionMarker; @Data +@ReflectionMarker public class TorboxAddUdlData { private String hash; private String usenetdownload_id; diff --git a/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/TorboxDownload.java b/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/TorboxDownload.java index 6540c78e4..e12987278 100644 --- a/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/TorboxDownload.java +++ b/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/TorboxDownload.java @@ -18,11 +18,13 @@ import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; +import org.nzbhydra.springnative.ReflectionMarker; import java.time.Instant; import java.util.List; @Data +@ReflectionMarker public class TorboxDownload { private long id; private Instant created_at; diff --git a/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/TorboxFile.java b/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/TorboxFile.java index 617688c1f..679d2c7f6 100644 --- a/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/TorboxFile.java +++ b/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/TorboxFile.java @@ -17,8 +17,10 @@ package org.nzbhydra.downloading.downloaders.torbox.mapping; import lombok.Data; +import org.nzbhydra.springnative.ReflectionMarker; @Data +@ReflectionMarker public class TorboxFile { private long id; private String md5; diff --git a/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/UsenetListResponse.java b/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/UsenetListResponse.java index 19558252e..b3340e5a6 100644 --- a/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/UsenetListResponse.java +++ b/core/src/main/java/org/nzbhydra/downloading/downloaders/torbox/mapping/UsenetListResponse.java @@ -17,10 +17,12 @@ package org.nzbhydra.downloading.downloaders.torbox.mapping; import lombok.Data; +import org.nzbhydra.springnative.ReflectionMarker; import java.util.List; @Data +@ReflectionMarker public class UsenetListResponse implements UsenetResponse { private boolean success; private String error; diff --git a/core/src/main/java/org/nzbhydra/indexers/IndexerEntity.java b/core/src/main/java/org/nzbhydra/indexers/IndexerEntity.java index 726083824..08894d4f9 100644 --- a/core/src/main/java/org/nzbhydra/indexers/IndexerEntity.java +++ b/core/src/main/java/org/nzbhydra/indexers/IndexerEntity.java @@ -18,7 +18,7 @@ @ReflectionMarker @Entity @Table(name = "indexer") -public final class IndexerEntity { +public class IndexerEntity { @Id @GeneratedValue(strategy = GenerationType.AUTO) diff --git a/core/src/test/java/org/nzbhydra/downloading/FileDownloadEntityTest.java b/core/src/test/java/org/nzbhydra/downloading/FileDownloadEntityTest.java index c65f6bfd6..c5532373a 100644 --- a/core/src/test/java/org/nzbhydra/downloading/FileDownloadEntityTest.java +++ b/core/src/test/java/org/nzbhydra/downloading/FileDownloadEntityTest.java @@ -51,6 +51,7 @@ public void shouldBeConvertibleToTest() throws Exception { searchResult.setFirstFound(Instant.now()); searchResult.setPubDate(Instant.now()); searchResult.setDownloadType(DownloadType.NZB); + searchResult.setId(1234L); final IndexerEntity indexerEntity = new IndexerEntity("indexerName"); searchResult.setIndexer(indexerEntity); final SearchEntity searchEntity = new SearchEntity(); @@ -61,7 +62,9 @@ public void shouldBeConvertibleToTest() throws Exception { final ObjectWriter printer = Jackson.JSON_MAPPER.writerWithDefaultPrettyPrinter(); final FileDownloadEntityTO to = Jackson.JSON_MAPPER.convertValue(testee, FileDownloadEntityTO.class); - final String jsonTO = printer.writeValueAsString(to); + final String jsonTO = printer.writeValueAsString(to) + //Long value is serialized as string to prevent precision loss + .replace("\"1234\"", "1234"); final String jsonEntity = printer.writeValueAsString(testee); assertThat(jsonTO).isEqualTo(jsonEntity); } diff --git a/core/src/test/java/org/nzbhydra/indexers/IndexerSearchResultPersistorTest.java b/core/src/test/java/org/nzbhydra/indexers/IndexerSearchResultPersistorTest.java new file mode 100644 index 000000000..a22688474 --- /dev/null +++ b/core/src/test/java/org/nzbhydra/indexers/IndexerSearchResultPersistorTest.java @@ -0,0 +1,127 @@ +/* + * (C) Copyright 2024 TheOtherP (theotherp@posteo.net) + * + * 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.nzbhydra.indexers; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.nzbhydra.config.downloading.DownloadType; +import org.nzbhydra.searching.SearchResultIdCalculator; +import org.nzbhydra.searching.db.SearchResultEntity; +import org.nzbhydra.searching.db.SearchResultRepository; +import org.nzbhydra.searching.dtoseventsenums.IndexerSearchResult; +import org.nzbhydra.searching.dtoseventsenums.SearchResultItem; + +import java.time.Instant; +import java.util.List; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class IndexerSearchResultPersistorTest { + + @Mock + private SearchResultRepository searchResultRepository; + @Mock + private Indexer indexer; + @Mock + private IndexerEntity indexerEntity; + @Captor + private ArgumentCaptor> entitiesCaptor; + + @InjectMocks + private IndexerSearchResultPersistor testee; + + @BeforeEach + void setUp() { + when(indexer.getIndexerEntity()).thenReturn(indexerEntity); + } + + @Test + void shouldPersistNewSearchResults() { + // given + SearchResultItem item1 = getSearchResultItem("title1", "link1", "guid1"); + SearchResultItem item2 = getSearchResultItem("title2", "link2", "guid2"); + List items = List.of(item1, item2); + IndexerSearchResult indexerSearchResult = new IndexerSearchResult(); + when(searchResultRepository.findAllIdsByIdIn(anyList())).thenReturn(Set.of()); + + // when + List result = testee.persistSearchResults(indexer, items, indexerSearchResult); + + // then + verify(searchResultRepository).saveAll(entitiesCaptor.capture()); + List savedEntities = entitiesCaptor.getValue(); + assertThat(savedEntities).hasSize(2); + + SearchResultEntity savedEntity1 = savedEntities.get(0); + assertThat(savedEntity1.getTitle()).isEqualTo("title1"); + assertThat(savedEntity1.getLink()).isEqualTo("link1"); + assertThat(savedEntity1.getIndexerGuid()).isEqualTo("guid1"); + assertThat(savedEntity1.getIndexer()).isEqualTo(indexerEntity); + + assertThat(result).hasSize(2); + assertThat(result.get(0).getSearchResultId()).isEqualTo(SearchResultIdCalculator.calculateSearchResultId(item1)); + } + + @Test + void shouldNotPersistExistingSearchResults() { + // given + SearchResultItem item1 = getSearchResultItem("title1", "link1", "guid1"); + SearchResultItem item2 = getSearchResultItem("title2", "link2", "guid2"); + List items = List.of(item1, item2); + IndexerSearchResult indexerSearchResult = new IndexerSearchResult(); + + + long existingId = SearchResultIdCalculator.calculateSearchResultId(item1); + when(searchResultRepository.findAllIdsByIdIn(anyList())).thenReturn(Set.of(existingId)); + + // when + List result = testee.persistSearchResults(indexer, items, indexerSearchResult); + + // then + verify(searchResultRepository).saveAll(entitiesCaptor.capture()); + List savedEntities = entitiesCaptor.getValue(); + assertThat(savedEntities).hasSize(1); + assertThat(savedEntities.get(0).getTitle()).isEqualTo("title2"); + + assertThat(result).hasSize(2); + assertThat(result.get(0).getSearchResultId()).isEqualTo(existingId); + } + + private SearchResultItem getSearchResultItem(String title, String link, String guid) { + SearchResultItem item = new SearchResultItem(); + item.setTitle(title); + item.setLink(link); + item.setIndexerGuid(guid); + item.setDetails("details"); + item.setDownloadType(DownloadType.NZB); + item.setPubDate(Instant.now()); + item.setIndexer(indexer); + return item; + } + +} \ No newline at end of file diff --git a/core/src/test/java/org/nzbhydra/indexers/IndexerTest.java b/core/src/test/java/org/nzbhydra/indexers/IndexerTest.java index 34f2502c3..369879f9e 100644 --- a/core/src/test/java/org/nzbhydra/indexers/IndexerTest.java +++ b/core/src/test/java/org/nzbhydra/indexers/IndexerTest.java @@ -2,7 +2,6 @@ import com.google.common.base.Stopwatch; import com.google.common.collect.HashMultiset; -import com.google.common.collect.Sets; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; @@ -78,8 +77,9 @@ public class IndexerTest { private IndexerApiAccessEntityShortRepository shortRepositoryMock; @Mock private SearchResultRepository searchResultRepositoryMock; - @Captor - private ArgumentCaptor> searchResultEntitiesCaptor; + @Mock + private IndexerSearchResultPersistor searchResultPersistor; + @Captor private ArgumentCaptor errorMessageCaptor; @Captor @@ -139,6 +139,11 @@ public NfoResult getNfo(String guid) { protected String getAndStoreResultToDatabase(URI uri, IndexerApiAccessType apiAccessType) throws IndexerAccessException { return null; } + + @Override + protected List persistSearchResults(List searchResultItems, IndexerSearchResult indexerSearchResult) { + return searchResultItems; + } }; } @@ -179,41 +184,6 @@ public Object answer(InvocationOnMock invocation) throws Throwable { }); } - @Test - void shouldCreateNewSearchResultEntityWhenNoneIsFound() throws Exception { - SearchResultItem item = new SearchResultItem(); - item.setIndexer(indexerMock); - item.setTitle("title"); - item.setDetails("details"); - item.setIndexerGuid("guid"); - - testee.persistSearchResults(Collections.singletonList(item), new IndexerSearchResult()); - - verify(searchResultRepositoryMock).saveAll(searchResultEntitiesCaptor.capture()); - - List persistedEntities = searchResultEntitiesCaptor.getValue(); - assertThat(persistedEntities.size()).isEqualTo(1); - assertThat(persistedEntities.get(0).getTitle()).isEqualTo("title"); - assertThat(persistedEntities.get(0).getDetails()).isEqualTo("details"); - assertThat(persistedEntities.get(0).getIndexerGuid()).isEqualTo("guid"); - } - - @Test - void shouldNotCreateNewSearchResultEntityWhenOneExists() throws Exception { - SearchResultItem item = new SearchResultItem(); - item.setIndexerGuid("guid"); - item.setIndexer(indexerMock); - searchResultEntityMock.setIndexerGuid("guid"); - when(searchResultRepositoryMock.findAllIdsByIdIn(anyList())).thenReturn(Sets.newHashSet(299225959498991027L)); - - testee.persistSearchResults(Collections.singletonList(item), new IndexerSearchResult()); - - verify(searchResultRepositoryMock).saveAll(searchResultEntitiesCaptor.capture()); - - List persistedEntities = searchResultEntitiesCaptor.getValue(); - assertThat(persistedEntities.size()).isEqualTo(0); - } - @Test void handleSuccess() throws Exception { diff --git a/core/src/test/java/org/nzbhydra/indexers/NewznabTest.java b/core/src/test/java/org/nzbhydra/indexers/NewznabTest.java index 1d6bc3396..91e27d7bc 100644 --- a/core/src/test/java/org/nzbhydra/indexers/NewznabTest.java +++ b/core/src/test/java/org/nzbhydra/indexers/NewznabTest.java @@ -49,6 +49,7 @@ import org.nzbhydra.mediainfo.InfoProvider; import org.nzbhydra.mediainfo.MediaInfo; import org.nzbhydra.searching.CategoryProvider; +import org.nzbhydra.searching.CustomQueryAndTitleMappingHandler; import org.nzbhydra.searching.SearchResultAcceptor; import org.nzbhydra.searching.SearchResultAcceptor.AcceptorResult; import org.nzbhydra.searching.db.SearchResultRepository; @@ -61,6 +62,7 @@ import org.springframework.util.MultiValueMap; import org.springframework.web.util.UriComponentsBuilder; +import java.lang.reflect.Field; import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; @@ -100,6 +102,10 @@ public class NewznabTest { private SearchResultAcceptor resultAcceptorMock; @Mock private Unmarshaller unmarshallerMock; + @Mock + private CustomQueryAndTitleMappingHandler customQueryAndTitleMappingHandler; + @Mock + private IndexerSearchResultPersistor searchResultPersistor; @Captor ArgumentCaptor errorMessageCaptor; @Captor @@ -129,6 +135,7 @@ public class NewznabTest { @BeforeEach public void setUp() throws Exception { MockitoAnnotations.initMocks(this); +// testee = new Newznab(configProviderMock,indexerRepositoryMock,searchResultRepositoryMock, indexerApiAccessRepositoryMock, null,null,indexerWebAccessMock,resultAcceptorMock, categoryProviderMock, infoProviderMock, null,queryGeneratorMock, customQueryAndTitleMappingHandler,unmarshallerMock,baseConfigHandler,null); testee = spy(testee); when(infoProviderMock.canConvert(MediaIdType.IMDB, MediaIdType.TMDB)).thenReturn(true); MediaInfo info = new MediaInfo(); @@ -148,6 +155,9 @@ public void setUp() throws Exception { testee.config.setHost("http://127.0.0.1:1234"); testee.config.setForbiddenWordPrefix(IndexerConfig.ForbiddenWordPrefix.EXCLAMATION_MARK); testee.indexer = indexerEntityMock; + Field field = Indexer.class.getDeclaredField("titleMapping"); + field.setAccessible(true); + field.set(testee, customQueryAndTitleMappingHandler); baseConfig = new BaseConfig(); when(configProviderMock.getBaseConfig()).thenReturn(baseConfig);