From 943b61ec0f76b065990eafbfb2da8470f95e3ca2 Mon Sep 17 00:00:00 2001
From: Michael Breu <Michael.Breu@arctis.at>
Date: Thu, 18 Aug 2022 09:48:34 +0200
Subject: [PATCH] Added Tests for filtering

---
 .../uibk/gitsearch/service/SearchService.java | 14 ++--
 .../service/ShoppingBasketService.java        | 69 +++++++++++++++----
 .../service/ShoppingBasketServiceTest.java    | 61 ++++++++++++++++
 3 files changed, 123 insertions(+), 21 deletions(-)
 create mode 100644 src/test/java/at/ac/uibk/gitsearch/service/ShoppingBasketServiceTest.java

diff --git a/src/main/java/at/ac/uibk/gitsearch/service/SearchService.java b/src/main/java/at/ac/uibk/gitsearch/service/SearchService.java
index 2b278ab50..f2cb9990e 100644
--- a/src/main/java/at/ac/uibk/gitsearch/service/SearchService.java
+++ b/src/main/java/at/ac/uibk/gitsearch/service/SearchService.java
@@ -1,11 +1,5 @@
 package at.ac.uibk.gitsearch.service;
 
-import at.ac.uibk.gitsearch.repository.gitlab.GitLabRepository;
-import at.ac.uibk.gitsearch.repository.search.MetaDataRepository;
-import at.ac.uibk.gitsearch.security.AuthoritiesConstants.AuthoritiesConstantEnum;
-import at.ac.uibk.gitsearch.security.jwt.TokenProvider;
-import at.ac.uibk.gitsearch.security.jwt.TokenProvider.GitLabAccessInfo;
-import at.ac.uibk.gitsearch.service.dto.AutoCompleteEntry;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -25,6 +19,7 @@ import java.util.stream.Stream;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 import java.util.zip.ZipOutputStream;
+
 import org.apache.commons.lang3.StringUtils;
 import org.codeability.sharing.plugins.api.search.SearchInputDTO;
 import org.codeability.sharing.plugins.api.search.SearchInputMetadataDTO;
@@ -39,6 +34,13 @@ import org.springframework.security.core.userdetails.User;
 import org.springframework.stereotype.Service;
 import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
 
+import at.ac.uibk.gitsearch.repository.gitlab.GitLabRepository;
+import at.ac.uibk.gitsearch.repository.search.MetaDataRepository;
+import at.ac.uibk.gitsearch.security.AuthoritiesConstants.AuthoritiesConstantEnum;
+import at.ac.uibk.gitsearch.security.jwt.TokenProvider;
+import at.ac.uibk.gitsearch.security.jwt.TokenProvider.GitLabAccessInfo;
+import at.ac.uibk.gitsearch.service.dto.AutoCompleteEntry;
+
 /**
  * Service for exercise/course search results
  * <p>
diff --git a/src/main/java/at/ac/uibk/gitsearch/service/ShoppingBasketService.java b/src/main/java/at/ac/uibk/gitsearch/service/ShoppingBasketService.java
index 4d984f1a4..14e892b15 100644
--- a/src/main/java/at/ac/uibk/gitsearch/service/ShoppingBasketService.java
+++ b/src/main/java/at/ac/uibk/gitsearch/service/ShoppingBasketService.java
@@ -1,15 +1,5 @@
 package at.ac.uibk.gitsearch.service;
 
-import at.ac.uibk.gitsearch.repository.gitlab.GitLabRepository;
-import at.ac.uibk.gitsearch.security.jwt.TokenProvider.GitLabAccessInfo;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PipedInputStream;
@@ -22,6 +12,7 @@ import java.util.UUID;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 import java.util.zip.ZipOutputStream;
+
 import org.apache.commons.lang3.StringUtils;
 import org.checkerframework.checker.nullness.qual.Nullable;
 import org.codeability.sharing.plugins.api.ShoppingBasket;
@@ -33,8 +24,21 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.util.AntPathMatcher;
 import org.springframework.util.StreamUtils;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+
+import at.ac.uibk.gitsearch.repository.gitlab.GitLabRepository;
+import at.ac.uibk.gitsearch.security.jwt.TokenProvider.GitLabAccessInfo;
+
 /**
  * Service for exercise/course search results
  * <p>
@@ -336,12 +340,15 @@ public class ShoppingBasketService {
 
                 while (zipInEntry != null) {
                     String fileName = zipInEntry.getName();
+					boolean isDirectory = zipInEntry.isDirectory();
                     if (fileName.startsWith(prefix)) {
                         String newName = fileName.substring(prefix.length());
                         String fileWithSubPath = getWithoutPathPrefix(newName, exerciseFolderPath);
                         if (fileWithSubPath != null) { // process this file
                             newName = fileWithSubPath;
-                            if (!StringUtils.isEmpty(newName) && !filterOut(newName, filterOut)) {
+							if (!StringUtils.isEmpty(newName)
+									&& !filterOut(newName, filterOut,
+											isDirectory)) {
                                 ZipEntry zipOutEntry = new ZipEntry(newName);
                                 if (zipInEntry.isDirectory()) {
                                     log.debug("ignoring directory {}", fileName);
@@ -394,11 +401,43 @@ public class ShoppingBasketService {
         return null;
     }
 
-    private boolean filterOut(String fileName, String[] filterOut) {
+	/**
+	 * tests filters against fileName. Protected for test purposes. Do not use
+	 * outside this methd
+	 * 
+	 * @param filePath
+	 *            the filename (with folder path) to check
+	 * @param filterOut
+	 *            the list of filters
+	 * @param isDirectory
+	 *            check for directories
+	 * @return
+	 */
+	protected static boolean filterOut(String filePath, String[] filterOut,
+			boolean isDirectory) {
+		if (filePath == null)
+			return false;
+		AntPathMatcher antPathMatcher = new AntPathMatcher();
         for (String filter : filterOut) {
-            if (fileName.startsWith(filter)) {
-                return fileName.length() == filter.length() || fileName.charAt(filter.length()) == '/';
-            }
+			if (filter == null) {
+				log.warn("filter should never be null!");
+				continue;
+			}
+			String filePathToTest = filePath;
+			// just adapt current path to pattern
+			if (filePathToTest
+							.startsWith(AntPathMatcher.DEFAULT_PATH_SEPARATOR)
+					&& !filter
+							.startsWith(AntPathMatcher.DEFAULT_PATH_SEPARATOR))
+				filePathToTest = filePathToTest.substring(1);
+			if (!filePathToTest
+							.startsWith(AntPathMatcher.DEFAULT_PATH_SEPARATOR)
+					&& filter.startsWith(AntPathMatcher.DEFAULT_PATH_SEPARATOR))
+				filePathToTest = AntPathMatcher.DEFAULT_PATH_SEPARATOR
+						+ filePathToTest;
+			if (antPathMatcher.match(filter, filePathToTest)) {
+				return true;
+			}
         }
         return false;
     }
diff --git a/src/test/java/at/ac/uibk/gitsearch/service/ShoppingBasketServiceTest.java b/src/test/java/at/ac/uibk/gitsearch/service/ShoppingBasketServiceTest.java
new file mode 100644
index 000000000..c28e9e305
--- /dev/null
+++ b/src/test/java/at/ac/uibk/gitsearch/service/ShoppingBasketServiceTest.java
@@ -0,0 +1,61 @@
+package at.ac.uibk.gitsearch.service;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+public class ShoppingBasketServiceTest {
+
+	@Test
+	public void simpleFilterOutTests() {
+		assertFalse(ShoppingBasketService.filterOut("someFile.txt",
+				new String[]{}, false));
+		assertFalse(ShoppingBasketService.filterOut("someFile.txt",
+				new String[]{"some"}, false));
+		assertTrue(ShoppingBasketService.filterOut("someFile.txt",
+				new String[]{"some*"}, false));
+		assertFalse(ShoppingBasketService.filterOut("someFile.txt",
+				new String[]{"some*.pdf"}, false));
+		assertTrue(ShoppingBasketService.filterOut("someFile.txt",
+				new String[]{"some*.txt"}, false));
+	}
+	@Test
+	public void filterOutTestsWithLeadingRoot() {
+		assertFalse(ShoppingBasketService.filterOut("/someFile.txt",
+				new String[]{}, false));
+		assertFalse(ShoppingBasketService.filterOut("/someFile.txt",
+				new String[]{"**/some"}, false));
+		assertTrue(ShoppingBasketService.filterOut("/someFile.txt",
+				new String[]{"**/some*"}, false));
+		assertFalse(ShoppingBasketService.filterOut("/someFile.txt",
+				new String[]{"**/some*.pdf"}, false));
+		assertTrue(ShoppingBasketService.filterOut("/someFile.txt",
+				new String[]{"**/some*.txt"}, false));
+	}
+
+	@Test
+	public void filterOutTestsWithDirectories() {
+		assertFalse(ShoppingBasketService.filterOut("someDir", new String[]{},
+				true));
+		assertFalse(ShoppingBasketService.filterOut("someDir",
+				new String[]{"some/"}, true));
+		assertTrue(ShoppingBasketService.filterOut("someDir",
+				new String[]{"/some*"}, true));
+		assertTrue(ShoppingBasketService.filterOut("someDir",
+				new String[]{"some*"}, true));
+		assertTrue(ShoppingBasketService.filterOut("someDir/",
+				new String[]{"some*/"}, true));
+		assertFalse(ShoppingBasketService.filterOut("someDir",
+				new String[]{"*/some/"}, true));
+		assertFalse(ShoppingBasketService.filterOut("parent/someDir",
+				new String[]{"*/some/"}, true));
+		assertFalse(ShoppingBasketService.filterOut("parent/someDir",
+				new String[]{"someDir/"}, true));
+		assertTrue(ShoppingBasketService.filterOut("parent/someDir",
+				new String[]{"**/someDir"}, true));
+		assertTrue(ShoppingBasketService.filterOut("parent/someDir",
+				new String[]{"**/some*"}, true));
+
+	}
+}
-- 
GitLab