diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f1aa6b73d..766d3285a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -112,10 +112,10 @@ jobs: - name: Pip requirements run: | - pip install --require-hashes -r ./cucumber/requirements.txt + pip install --require-hashes -r ./testing/cucumber/requirements.txt - name: Run Docker Compose Tests run: | - chmod +x ./cucumber/test_webpages.sh - chmod +x ./test.sh - ./test.sh "${{ github.event.pull_request.user.login == 'dependabot[bot]' }}" + chmod +x ./testing/test_webpages.sh + chmod +x ./testing/test.sh + ./testing/test.sh "${{ github.event.pull_request.user.login == 'dependabot[bot]' }}" diff --git a/.github/workflows/testdriver.yml b/.github/workflows/testdriver.yml index 25f86f3f8..ec6d50c53 100644 --- a/.github/workflows/testdriver.yml +++ b/.github/workflows/testdriver.yml @@ -122,7 +122,7 @@ jobs: Start-Process "C:/Program Files/Google/Chrome/Application/chrome.exe" -ArgumentList "--start-maximized", "--load-extension=$(pwd)/node_modules/dashcam-chrome/build", "http://${{ secrets.VPS_HOST }}:1337" Start-Sleep -Seconds 20 prompt: | - 1. /run testdriver/test.yml + 1. /run testing/testdriver/test.yml env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} FORCE_COLOR: "3" diff --git a/.gitignore b/.gitignore index 7a4101e96..22689d115 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ clientWebUI/ !cucumber/ !cucumber/exampleFiles/ !cucumber/exampleFiles/example_html.zip +exampleYmlFiles/stirling/ # Gradle .gradle diff --git a/Dockerfile b/Dockerfile index 7afda2adc..377e6de20 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,7 +25,13 @@ LABEL org.opencontainers.image.keywords="PDF, manipulation, merge, split, conver # Set Environment Variables ENV DOCKER_ENABLE_SECURITY=false \ VERSION_TAG=$VERSION_TAG \ - JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -XX:MaxRAMPercentage=75" \ + JAVA_TOOL_OPTIONS="-XX:+UnlockExperimentalVMOptions \ + -XX:MaxRAMPercentage=75 \ + -XX:InitiatingHeapOccupancyPercent=20 \ + -XX:+G1PeriodicGCInvokesConcurrent \ + -XX:G1PeriodicGCInterval=10000 \ + -XX:+UseStringDeduplication \ + -XX:G1PeriodicGCSystemLoadThreshold=70" \ HOME=/home/stirlingpdfuser \ PUID=1000 \ PGID=1000 \ diff --git a/Dockerfile.fat b/Dockerfile.fat index f9f76b027..f8450fa02 100644 --- a/Dockerfile.fat +++ b/Dockerfile.fat @@ -25,7 +25,13 @@ ARG VERSION_TAG # Set Environment Variables ENV DOCKER_ENABLE_SECURITY=false \ VERSION_TAG=$VERSION_TAG \ - JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -XX:MaxRAMPercentage=75" \ + JAVA_TOOL_OPTIONS="-XX:+UnlockExperimentalVMOptions \ + -XX:MaxRAMPercentage=75 \ + -XX:InitiatingHeapOccupancyPercent=20 \ + -XX:+G1PeriodicGCInvokesConcurrent \ + -XX:G1PeriodicGCInterval=10000 \ + -XX:+UseStringDeduplication \ + -XX:G1PeriodicGCSystemLoadThreshold=70" \ HOME=/home/stirlingpdfuser \ PUID=1000 \ PGID=1000 \ diff --git a/Dockerfile.ultra-lite b/Dockerfile.ultra-lite index 3f2620eb8..650daf018 100644 --- a/Dockerfile.ultra-lite +++ b/Dockerfile.ultra-lite @@ -7,7 +7,13 @@ ARG VERSION_TAG ENV DOCKER_ENABLE_SECURITY=false \ HOME=/home/stirlingpdfuser \ VERSION_TAG=$VERSION_TAG \ - JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -XX:MaxRAMPercentage=75" \ + JAVA_TOOL_OPTIONS="-XX:+UnlockExperimentalVMOptions \ + -XX:MaxRAMPercentage=75 \ + -XX:InitiatingHeapOccupancyPercent=20 \ + -XX:+G1PeriodicGCInvokesConcurrent \ + -XX:G1PeriodicGCInterval=10000 \ + -XX:+UseStringDeduplication \ + -XX:G1PeriodicGCSystemLoadThreshold=70" \ PUID=1000 \ PGID=1000 \ UMASK=022 diff --git a/build.gradle b/build.gradle index 529a3ab2d..31feae92e 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ ext { } group = "stirling.software" -version = "0.38.0" +version = "0.39.0" java { @@ -370,6 +370,8 @@ dependencies { implementation ("org.apache.pdfbox:pdfbox:$pdfboxVersion") { exclude group: "commons-logging", module: "commons-logging" } + implementation "org.apache.pdfbox:preflight:$pdfboxVersion" + implementation ("org.apache.pdfbox:xmpbox:$pdfboxVersion") { exclude group: "commons-logging", module: "commons-logging" diff --git a/exampleYmlFiles/test_cicd.yml b/exampleYmlFiles/test_cicd.yml index 144348a79..cc490c71f 100644 --- a/exampleYmlFiles/test_cicd.yml +++ b/exampleYmlFiles/test_cicd.yml @@ -1,6 +1,6 @@ services: stirling-pdf: - container_name: Stirling-PDF-Security-Fat + container_name: Stirling-PDF-Security-Fat-with-login image: stirlingtools/stirling-pdf:latest-fat deploy: resources: diff --git a/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java b/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java new file mode 100644 index 000000000..a97ae2bb7 --- /dev/null +++ b/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java @@ -0,0 +1,180 @@ +package stirling.software.SPDF.controller.api; + +import org.apache.pdfbox.Loader; +import org.apache.pdfbox.cos.COSName; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.PDPageTree; +import org.apache.pdfbox.pdmodel.PDDocumentInformation; +import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; +import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation; +import org.apache.pdfbox.pdmodel.encryption.PDEncryption; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import stirling.software.SPDF.model.api.PDFFile; + +import java.io.IOException; +import java.util.*; + +@RestController +@RequestMapping("/api/v1/analysis") +@Tag(name = "Analysis", description = "Analysis APIs") +public class AnalysisController { + + + @PostMapping(value = "/page-count", consumes = "multipart/form-data") + @Operation(summary = "Get PDF page count", + description = "Returns total number of pages in PDF. Input:PDF Output:JSON Type:SISO") + public Map getPageCount(@ModelAttribute PDFFile file) throws IOException { + try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) { + return Map.of("pageCount", document.getNumberOfPages()); + } + } + + @PostMapping(value ="/basic-info", consumes = "multipart/form-data") + @Operation(summary = "Get basic PDF information", + description = "Returns page count, version, file size. Input:PDF Output:JSON Type:SISO") + public Map getBasicInfo(@ModelAttribute PDFFile file) throws IOException { + try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) { + Map info = new HashMap<>(); + info.put("pageCount", document.getNumberOfPages()); + info.put("pdfVersion", document.getVersion()); + info.put("fileSize", file.getFileInput().getSize()); + return info; + } + } + + @PostMapping(value ="/document-properties", consumes = "multipart/form-data") + @Operation(summary = "Get PDF document properties", + description = "Returns title, author, subject, etc. Input:PDF Output:JSON Type:SISO") + public Map getDocumentProperties(@ModelAttribute PDFFile file) throws IOException { + try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) { + PDDocumentInformation info = document.getDocumentInformation(); + Map properties = new HashMap<>(); + properties.put("title", info.getTitle()); + properties.put("author", info.getAuthor()); + properties.put("subject", info.getSubject()); + properties.put("keywords", info.getKeywords()); + properties.put("creator", info.getCreator()); + properties.put("producer", info.getProducer()); + properties.put("creationDate", info.getCreationDate().toString()); + properties.put("modificationDate", info.getModificationDate().toString()); + return properties; + } + } + + @PostMapping(value ="/page-dimensions", consumes = "multipart/form-data") + @Operation(summary = "Get page dimensions for all pages", + description = "Returns width and height of each page. Input:PDF Output:JSON Type:SISO") + public List> getPageDimensions(@ModelAttribute PDFFile file) throws IOException { + try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) { + List> dimensions = new ArrayList<>(); + PDPageTree pages = document.getPages(); + + for (PDPage page : pages) { + Map pageDim = new HashMap<>(); + pageDim.put("width", page.getBBox().getWidth()); + pageDim.put("height", page.getBBox().getHeight()); + dimensions.add(pageDim); + } + return dimensions; + } + } + + @PostMapping(value ="/form-fields", consumes = "multipart/form-data") + @Operation(summary = "Get form field information", + description = "Returns count and details of form fields. Input:PDF Output:JSON Type:SISO") + public Map getFormFields(@ModelAttribute PDFFile file) throws IOException { + try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) { + Map formInfo = new HashMap<>(); + PDAcroForm form = document.getDocumentCatalog().getAcroForm(); + + if (form != null) { + formInfo.put("fieldCount", form.getFields().size()); + formInfo.put("hasXFA", form.hasXFA()); + formInfo.put("isSignaturesExist", form.isSignaturesExist()); + } else { + formInfo.put("fieldCount", 0); + formInfo.put("hasXFA", false); + formInfo.put("isSignaturesExist", false); + } + return formInfo; + } + } + + @PostMapping(value ="/annotation-info", consumes = "multipart/form-data") + @Operation(summary = "Get annotation information", + description = "Returns count and types of annotations. Input:PDF Output:JSON Type:SISO") + public Map getAnnotationInfo(@ModelAttribute PDFFile file) throws IOException { + try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) { + Map annotInfo = new HashMap<>(); + int totalAnnotations = 0; + Map annotationTypes = new HashMap<>(); + + for (PDPage page : document.getPages()) { + for (PDAnnotation annot : page.getAnnotations()) { + totalAnnotations++; + String subType = annot.getSubtype(); + annotationTypes.merge(subType, 1, Integer::sum); + } + } + + annotInfo.put("totalCount", totalAnnotations); + annotInfo.put("typeBreakdown", annotationTypes); + return annotInfo; + } + } + + @PostMapping(value ="/font-info", consumes = "multipart/form-data") + @Operation(summary = "Get font information", + description = "Returns list of fonts used in the document. Input:PDF Output:JSON Type:SISO") + public Map getFontInfo(@ModelAttribute PDFFile file) throws IOException { + try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) { + Map fontInfo = new HashMap<>(); + Set fontNames = new HashSet<>(); + + for (PDPage page : document.getPages()) { + for (COSName font : page.getResources().getFontNames()) { + fontNames.add(font.getName()); + } + } + + fontInfo.put("fontCount", fontNames.size()); + fontInfo.put("fonts", fontNames); + return fontInfo; + } + } + + @PostMapping(value ="/security-info", consumes = "multipart/form-data") + @Operation(summary = "Get security information", + description = "Returns encryption and permission details. Input:PDF Output:JSON Type:SISO") + public Map getSecurityInfo(@ModelAttribute PDFFile file) throws IOException { + try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) { + Map securityInfo = new HashMap<>(); + PDEncryption encryption = document.getEncryption(); + + if (encryption != null) { + securityInfo.put("isEncrypted", true); + securityInfo.put("keyLength", encryption.getLength()); + + // Get permissions + Map permissions = new HashMap<>(); + permissions.put("canPrint", document.getCurrentAccessPermission().canPrint()); + permissions.put("canModify", document.getCurrentAccessPermission().canModify()); + permissions.put("canExtractContent", document.getCurrentAccessPermission().canExtractContent()); + permissions.put("canModifyAnnotations", document.getCurrentAccessPermission().canModifyAnnotations()); + + securityInfo.put("permissions", permissions); + } else { + securityInfo.put("isEncrypted", false); + } + + return securityInfo; + } + } + + + +} \ No newline at end of file diff --git a/src/main/resources/templates/misc/remove-blanks.html b/src/main/resources/templates/misc/remove-blanks.html index eb0d45f65..cf483e22b 100644 --- a/src/main/resources/templates/misc/remove-blanks.html +++ b/src/main/resources/templates/misc/remove-blanks.html @@ -5,6 +5,7 @@ +
diff --git a/cucumber/exampleFiles/example.docx b/testing/cucumber/exampleFiles/example.docx similarity index 100% rename from cucumber/exampleFiles/example.docx rename to testing/cucumber/exampleFiles/example.docx diff --git a/cucumber/exampleFiles/example.html b/testing/cucumber/exampleFiles/example.html similarity index 100% rename from cucumber/exampleFiles/example.html rename to testing/cucumber/exampleFiles/example.html diff --git a/cucumber/exampleFiles/example.md b/testing/cucumber/exampleFiles/example.md similarity index 100% rename from cucumber/exampleFiles/example.md rename to testing/cucumber/exampleFiles/example.md diff --git a/cucumber/exampleFiles/example.odp b/testing/cucumber/exampleFiles/example.odp similarity index 100% rename from cucumber/exampleFiles/example.odp rename to testing/cucumber/exampleFiles/example.odp diff --git a/cucumber/exampleFiles/example.odt b/testing/cucumber/exampleFiles/example.odt similarity index 100% rename from cucumber/exampleFiles/example.odt rename to testing/cucumber/exampleFiles/example.odt diff --git a/cucumber/exampleFiles/example.pptx b/testing/cucumber/exampleFiles/example.pptx similarity index 100% rename from cucumber/exampleFiles/example.pptx rename to testing/cucumber/exampleFiles/example.pptx diff --git a/cucumber/exampleFiles/example.rtf b/testing/cucumber/exampleFiles/example.rtf similarity index 100% rename from cucumber/exampleFiles/example.rtf rename to testing/cucumber/exampleFiles/example.rtf diff --git a/cucumber/exampleFiles/example_html.zip b/testing/cucumber/exampleFiles/example_html.zip similarity index 100% rename from cucumber/exampleFiles/example_html.zip rename to testing/cucumber/exampleFiles/example_html.zip diff --git a/cucumber/exampleFiles/ghost1.pdf b/testing/cucumber/exampleFiles/ghost1.pdf similarity index 100% rename from cucumber/exampleFiles/ghost1.pdf rename to testing/cucumber/exampleFiles/ghost1.pdf diff --git a/cucumber/exampleFiles/ghost2.pdf b/testing/cucumber/exampleFiles/ghost2.pdf similarity index 100% rename from cucumber/exampleFiles/ghost2.pdf rename to testing/cucumber/exampleFiles/ghost2.pdf diff --git a/cucumber/exampleFiles/ghost3.pdf b/testing/cucumber/exampleFiles/ghost3.pdf similarity index 100% rename from cucumber/exampleFiles/ghost3.pdf rename to testing/cucumber/exampleFiles/ghost3.pdf diff --git a/cucumber/exampleFiles/images.pdf b/testing/cucumber/exampleFiles/images.pdf similarity index 100% rename from cucumber/exampleFiles/images.pdf rename to testing/cucumber/exampleFiles/images.pdf diff --git a/cucumber/exampleFiles/pdfa1.pdf b/testing/cucumber/exampleFiles/pdfa1.pdf similarity index 100% rename from cucumber/exampleFiles/pdfa1.pdf rename to testing/cucumber/exampleFiles/pdfa1.pdf diff --git a/cucumber/exampleFiles/pdfa2.pdf b/testing/cucumber/exampleFiles/pdfa2.pdf similarity index 100% rename from cucumber/exampleFiles/pdfa2.pdf rename to testing/cucumber/exampleFiles/pdfa2.pdf diff --git a/cucumber/features/environment.py b/testing/cucumber/features/environment.py similarity index 100% rename from cucumber/features/environment.py rename to testing/cucumber/features/environment.py diff --git a/cucumber/features/examples.feature b/testing/cucumber/features/examples.feature similarity index 100% rename from cucumber/features/examples.feature rename to testing/cucumber/features/examples.feature diff --git a/cucumber/features/external.feature b/testing/cucumber/features/external.feature similarity index 100% rename from cucumber/features/external.feature rename to testing/cucumber/features/external.feature diff --git a/cucumber/features/general.feature b/testing/cucumber/features/general.feature similarity index 100% rename from cucumber/features/general.feature rename to testing/cucumber/features/general.feature diff --git a/cucumber/features/steps/step_definitions.py b/testing/cucumber/features/steps/step_definitions.py similarity index 100% rename from cucumber/features/steps/step_definitions.py rename to testing/cucumber/features/steps/step_definitions.py diff --git a/cucumber/requirements.in b/testing/cucumber/requirements.in similarity index 100% rename from cucumber/requirements.in rename to testing/cucumber/requirements.in diff --git a/cucumber/requirements.txt b/testing/cucumber/requirements.txt similarity index 100% rename from cucumber/requirements.txt rename to testing/cucumber/requirements.txt diff --git a/test.sh b/testing/test.sh similarity index 69% rename from test.sh rename to testing/test.sh index 46fcd815d..fe70840a4 100644 --- a/test.sh +++ b/testing/test.sh @@ -3,6 +3,22 @@ # Default value for the Boolean parameter VERIFICATION=${1:-false} # Default is "false" if no parameter is passed +# Find project root by locating build.gradle +find_root() { + local dir="$PWD" + while [[ "$dir" != "/" ]]; do + if [[ -f "$dir/build.gradle" ]]; then + echo "$dir" + return 0 + fi + dir="$(dirname "$dir")" + done + echo "Error: build.gradle not found" >&2 + exit 1 +} + +PROJECT_ROOT=$(find_root) + # Function to check the health of the service with a timeout of 80 seconds check_health() { local service_name=$1 @@ -67,13 +83,16 @@ run_tests() { main() { SECONDS=0 + cd "$PROJECT_ROOT" + # Run the gradlew build command and check if it fails if [[ "$VERIFICATION" == "true" ]]; then ./gradlew clean dependencies buildEnvironment spotlessApply --write-verification-metadata sha256 --refresh-dependencies help ./gradlew clean dependencies buildEnvironment spotlessApply --write-verification-metadata sha256,pgp --refresh-keys --export-keys --refresh-dependencies help fi - + export DOCKER_ENABLE_SECURITY=false + # Run the gradlew build command and check if it fails if ! ./gradlew clean build; then echo "Gradle build failed with security disabled, exiting script." exit 1 @@ -83,19 +102,21 @@ main() { # Building Docker images # docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest -f ./Dockerfile . docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-ultra-lite -f ./Dockerfile.ultra-lite . - + # Test each configuration run_tests "Stirling-PDF-Ultra-Lite" "./exampleYmlFiles/docker-compose-latest-ultra-lite.yml" - + echo "Testing webpage accessibility..." - if ./cucumber/test_webpages.sh; then - passed_tests+=("Webpage-Accessibility") + cd "testing" + if ./test_webpages.sh -f webpage_urls.txt -b http://localhost:8080; then + passed_tests+=("Webpage-Accessibility-lite") else - failed_tests+=("Webpage-Accessibility") - echo "Webpage accessibility tests failed" + failed_tests+=("Webpage-Accessibility-lite") + echo "Webpage accessibility lite tests failed" fi - + cd "$PROJECT_ROOT" docker-compose -f "./exampleYmlFiles/docker-compose-latest-ultra-lite.yml" down + #run_tests "Stirling-PDF" "./exampleYmlFiles/docker-compose-latest.yml" #docker-compose -f "./exampleYmlFiles/docker-compose-latest.yml" down @@ -107,32 +128,52 @@ main() { exit 1 fi + # Building Docker images with security enabled - # docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest -f ./Dockerfile . - # docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-ultra-lite -f ./Dockerfile.ultra-lite . + # docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest -f ./Dockerfile . + # docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-ultra-lite -f ./Dockerfile.ultra-lite . docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-fat -f ./Dockerfile.fat . - + + # Test each configuration with security - # run_tests "Stirling-PDF-Ultra-Lite-Security" "./exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml" - # docker-compose -f "./exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml" down - # run_tests "Stirling-PDF-Security" "./exampleYmlFiles/docker-compose-latest-security.yml" - # docker-compose -f "./exampleYmlFiles/docker-compose-latest-security.yml" down + # run_tests "Stirling-PDF-Ultra-Lite-Security" "./exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml" + #docker-compose -f "./exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml" down + # run_tests "Stirling-PDF-Security" "./exampleYmlFiles/docker-compose-latest-security.yml" +# docker-compose -f "./exampleYmlFiles/docker-compose-latest-security.yml" down + + + run_tests "Stirling-PDF-Security-Fat" "./exampleYmlFiles/docker-compose-latest-fat-security.yml" + + echo "Testing webpage accessibility..." + cd "testing" + if ./test_webpages.sh -f webpage_urls_full.txt -b http://localhost:8080; then + passed_tests+=("Webpage-Accessibility-full") + else + failed_tests+=("Webpage-Accessibility-full") + echo "Webpage accessibility full tests failed" + fi + cd "$PROJECT_ROOT" + + docker-compose -f "./exampleYmlFiles/docker-compose-latest-fat-security.yml" down + + + run_tests "Stirling-PDF-Security-Fat-with-login" "./exampleYmlFiles/test_cicd.yml" - run_tests "Stirling-PDF-Security-Fat" "./exampleYmlFiles/test_cicd.yml" if [ $? -eq 0 ]; then - cd cucumber + cd "testing/cucumber" if python -m behave; then passed_tests+=("Stirling-PDF-Regression") else failed_tests+=("Stirling-PDF-Regression") echo "Printing docker logs of failed regression" - docker logs "Stirling-PDF-Security-Fat" + docker logs "Stirling-PDF-Security-Fat-with-login" echo "Printed docker logs of failed regression" fi - cd .. + cd "$PROJECT_ROOT" fi - docker-compose -f "./exampleYmlFiles/docker-compose-latest-fat-security.yml" down - + + docker-compose -f "./exampleYmlFiles/test_cicd.yml" down + # Report results echo "All tests completed in $SECONDS seconds." @@ -151,6 +192,8 @@ main() { echo -e "\e[31m$test\e[0m" # Red color for failed tests done + + # Check if there are any failed tests and exit with an error code if so if [ ${#failed_tests[@]} -ne 0 ]; then echo "Some tests failed." @@ -159,6 +202,7 @@ main() { echo "All tests passed successfully." exit 0 fi + } -main +main \ No newline at end of file diff --git a/test2.sh b/testing/test2.sh similarity index 100% rename from test2.sh rename to testing/test2.sh diff --git a/cucumber/test_webpages.sh b/testing/test_webpages.sh similarity index 62% rename from cucumber/test_webpages.sh rename to testing/test_webpages.sh index df97d08dc..e1207c2eb 100644 --- a/cucumber/test_webpages.sh +++ b/testing/test_webpages.sh @@ -2,17 +2,16 @@ # Function to check a single webpage check_webpage() { - local url=$1 - local base_url=${2:-"http://localhost:8080"} + local url=$(echo "$1" | tr -d '\r') # Remove carriage returns + local base_url=$(echo "$2" | tr -d '\r') local full_url="${base_url}${url}" local timeout=10 - echo -n "Testing $full_url ... " # Use curl to fetch the page with timeout response=$(curl -s -w "\n%{http_code}" --max-time $timeout "$full_url") if [ $? -ne 0 ]; then - echo "FAILED - Connection error or timeout" + echo "FAILED - Connection error or timeout $full_url " return 1 fi @@ -27,7 +26,7 @@ check_webpage() { fi # Check if response contains HTML - if ! echo "$BODY" | grep -q "\|\|&2; usage ;; + esac + done + + # Check if URL file is provided + if [ -z "$url_file" ]; then + echo "Error: URL file is required" + usage + fi + + # Check if URL file exists if [ ! -f "$url_file" ]; then echo "Error: URL list file not found: $url_file" exit 1 fi # Run tests using the URL list - if test_all_urls "$url_file"; then + if test_all_urls "$url_file" "$base_url"; then echo "All webpage tests passed!" exit 0 else diff --git a/testdriver/test.yml b/testing/testdriver/test.yml similarity index 100% rename from testdriver/test.yml rename to testing/testdriver/test.yml diff --git a/cucumber/webpage_urls.txt b/testing/webpage_urls.txt similarity index 100% rename from cucumber/webpage_urls.txt rename to testing/webpage_urls.txt diff --git a/testing/webpage_urls_full.txt b/testing/webpage_urls_full.txt new file mode 100644 index 000000000..557fdfb14 --- /dev/null +++ b/testing/webpage_urls_full.txt @@ -0,0 +1,66 @@ + +/ +/add-image +/add-page-numbers +/add-password +/add-watermark +/adjust-contrast +/auto-redact +/auto-rename +/auto-split-pdf +/cert-sign +/change-metadata +/change-permissions +/compare +/compress-pdf +/crop +/extract-image-scans +/extract-images +/extract-page +/file-to-pdf +/flatten +/get-info-on-pdf +/html-to-pdf +/img-to-pdf +/licenses +/markdown-to-pdf +/merge-pdfs +/multi-page-layout +/multi-tool +/ocr-pdf +/overlay-pdf +/pdf-organizer +/pdf-to-csv +/pdf-to-html +/pdf-to-img +/pdf-to-markdown +/pdf-to-presentation +/pdf-to-single-page +/pdf-to-text +/pdf-to-word +/pdf-to-xml +/pipeline +/redact +/releases +/remove-annotations +/remove-blanks +/remove-cert-sign +/remove-image-pdf +/remove-pages +/remove-password +/repair +/replace-and-invert-color-pdf +/rotate-pdf +/sanitize-pdf +/scale-pages +/show-javascript +/sign +/split-by-size-or-count +/split-pdf-by-chapters +/split-pdf-by-sections +/split-pdfs +/stamp +/url-to-pdf +/validate-signature +/view-pdf +/swagger-ui/index.html \ No newline at end of file