├── .gitattributes
├── .github
└── workflows
│ ├── options-tests-with-docker-build.yml
│ ├── purge-images.yml
│ ├── push-dockerhub.yml
│ ├── push-github.yml
│ ├── rest-api-tests-with-docker-image.yml
│ ├── test-dkr-build.yml
│ ├── test-dkr-image.yml
│ ├── test-pr.yml
│ └── update-arlington-workflow.yml
├── .gitignore
├── Dockerfile
├── Dockerfile_dev
├── LICENSE
├── Pipfile
├── Pipfile.lock
├── README.md
├── charts
└── verapdf-rest
│ ├── .helmignore
│ ├── Chart.yaml
│ ├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── service.yaml
│ ├── serviceaccount.yaml
│ └── tests
│ │ └── test-connection.yaml
│ └── values.yaml
├── config
├── app.xml
├── features.xml
├── fixer.xml
├── plugins.xml
└── validator.xml
├── kubernetes.yaml
├── pom.xml
├── requirements.txt
├── server.yml
├── settings.xml
├── src
└── main
│ ├── java
│ └── org
│ │ ├── openpreservation
│ │ └── bytestreams
│ │ │ ├── ByteStreamId.java
│ │ │ ├── ByteStreamIdImpl.java
│ │ │ ├── ByteStreams.java
│ │ │ └── package-info.java
│ │ └── verapdf
│ │ └── rest
│ │ ├── app
│ │ ├── VeraPdfRestApplication.java
│ │ └── VeraPdfRestConfiguration.java
│ │ ├── environment
│ │ ├── Environment.java
│ │ ├── Environments.java
│ │ ├── JvmDetails.java
│ │ ├── OsDetails.java
│ │ └── ServerDetails.java
│ │ ├── package-info.java
│ │ ├── resources
│ │ ├── ApiResource.java
│ │ ├── ByteStreamResource.java
│ │ ├── HomePageResource.java
│ │ ├── ProfileResource.java
│ │ ├── ValidateResource.java
│ │ └── ValidationExceptionMapper.java
│ │ └── views
│ │ └── RestClientView.java
│ └── resources
│ ├── assets
│ ├── css
│ │ └── verapdf.css
│ ├── img
│ │ ├── vera-pages.jpg
│ │ └── veraPDF-logo-400.png
│ └── js
│ │ ├── docs.min.js
│ │ ├── jquery.bootstrap.wizard.js
│ │ ├── mustache.js
│ │ ├── sha1.js
│ │ ├── vera.results.js
│ │ └── verapdf.js
│ └── org
│ └── verapdf
│ ├── release
│ └── rest.properties
│ └── rest
│ └── views
│ └── restclient.mustache
└── tests
├── Options
├── config
│ ├── app
│ │ ├── format.bats
│ │ ├── format
│ │ │ └── app.xml
│ │ ├── type.bats
│ │ ├── type
│ │ │ ├── app.xml
│ │ │ ├── features.xml
│ │ │ └── validator.xml
│ │ ├── wikiPath.bats
│ │ └── wikiPath
│ │ │ └── app.xml
│ ├── features
│ │ ├── features.bats
│ │ └── features
│ │ │ ├── app.xml
│ │ │ └── features.xml
│ └── validator
│ │ ├── debug.bats
│ │ ├── debug
│ │ └── validator.xml
│ │ ├── flavour.bats
│ │ ├── flavour
│ │ └── validator.xml
│ │ ├── isLogsEnabled.bats
│ │ ├── isLogsEnabled
│ │ └── validator.xml
│ │ ├── loggingLevel.bats
│ │ ├── loggingLevel
│ │ └── validator.xml
│ │ ├── maxFails.bats
│ │ ├── maxFails
│ │ └── validator.xml
│ │ ├── maxNumberOfDisplayedFailedChecks.bats
│ │ ├── maxNumberOfDisplayedFailedChecks
│ │ ├── validator_Checks_0.xml
│ │ └── validator_Checks_2.xml
│ │ ├── recordPasses.bats
│ │ ├── recordPasses
│ │ └── validator.xml
│ │ ├── showErrorMessages.bats
│ │ └── showErrorMessages
│ │ └── validator.xml
├── services
│ ├── bindMountLocalFiles
│ │ ├── steps_in_docker.sh
│ │ └── withBindMountLocalFiles.bats
│ └── limitingFileSize
│ │ └── limitingFileSize.bats
└── setup_suite.bash
├── Resources
├── 5-t02-fail-a.pdf
├── 6.1.3-01-fail-5.pdf
├── Mustang_505.pdf
├── PDFBOX_allowed_file_size.pdf
├── a.pdf
├── a_for_debug.pdf
├── orange.pdf
├── veraPDFPDFAConformanceCheckerGUI.pdf
└── veraPDF_MF3.pdf
├── __init__.py
├── conftest.py
├── rest_api
├── __init__.py
├── model
│ ├── __init__.py
│ ├── api_info
│ │ ├── __init__.py
│ │ ├── api_endpoint.py
│ │ ├── environment.py
│ │ ├── java.py
│ │ ├── os.py
│ │ └── server.py
│ ├── api_profiles
│ │ ├── __init__.py
│ │ ├── profile.py
│ │ ├── profile_id.py
│ │ ├── profile_ids.py
│ │ ├── profile_rule.py
│ │ ├── profile_variables.py
│ │ ├── profiles_flavours.py
│ │ └── rule_id.py
│ ├── api_sha1
│ │ ├── __init__.py
│ │ └── sha1.py
│ └── api_validate_details
│ │ ├── __init__.py
│ │ ├── api_validate_details.py
│ │ ├── job.py
│ │ ├── log.py
│ │ ├── report.py
│ │ ├── result.py
│ │ └── summary.py
└── tests
│ ├── __init__.py
│ ├── api_info
│ ├── __init__.py
│ ├── test_api.py
│ └── test_api_info.py
│ ├── api_profiles
│ ├── __init__.py
│ ├── test_api_profiles.py
│ ├── test_api_profiles_clause.py
│ ├── test_api_profiles_flavours.py
│ ├── test_api_profiles_id.py
│ ├── test_api_profiles_ids.py
│ └── test_api_profiles_ruleids.py
│ ├── api_sha1
│ ├── __init__.py
│ ├── api_sha1.py
│ └── test_api_sha1_null.py
│ ├── api_validate
│ ├── __init__.py
│ ├── test_api_validate_details.py
│ ├── test_api_validate_profileId.py
│ ├── test_api_validate_sha_profileId.py
│ └── test_validate_pdf_by_url.py
│ └── base_test.py
└── tools
└── test_helper
└── common-setup.bash
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Handle line endings automatically for files detected as text
2 | # and leave all files detected as binary untouched.
3 | * text=auto
4 |
5 | #
6 | # The above will handle all files NOT found below
7 | #
8 | # These files are text and should be normalized (Convert crlf => lf)
9 | *.css text
10 | *.df text
11 | *.htm text
12 | *.html text
13 | *.java text
14 | *.js text
15 | *.json text
16 | *.jsp text
17 | *.jspf text
18 | *.properties text
19 | *.sh text
20 | *.tld text
21 | *.txt text
22 | *.xml text
23 |
24 | # These files are binary and should be left untouched
25 | # (binary is a macro for -text -diff)
26 | *.class binary
27 | *.dll binary
28 | *.ear binary
29 | *.gif binary
30 | *.ico binary
31 | *.jar binary
32 | *.jpg binary
33 | *.jpeg binary
34 | *.png binary
35 | *.so binary
36 | *.war binary
37 |
38 |
--------------------------------------------------------------------------------
/.github/workflows/options-tests-with-docker-build.yml:
--------------------------------------------------------------------------------
1 | name: Options tests with docker build
2 |
3 | on:
4 | schedule:
5 | - cron: "05 09 * * 1"
6 | push:
7 | branches:
8 | - 'integration'
9 |
10 | jobs:
11 | build:
12 | if: github.repository == 'veraPDF/veraPDF-rest'
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | - name: Checkout the branch
17 | uses: actions/checkout@v3
18 |
19 | - name: Build and run Docker Image
20 | run: |
21 | docker build --build-arg GH_CHECKOUT=integration -t rest:dev . && docker run --user root -d -p 8080:8080 -p 8081:8081 -e VERAPDF_MAX_FILE_SIZE=1 -v /tmp:/home/Res_tmp rest:dev
22 | echo whoami: $(docker inspect $(docker ps -q) --format '{{.Config.User}} {{.Name}}')
23 |
24 | - name: Check Docker Container
25 | run: |
26 | docker images
27 | docker ps
28 |
29 | - name: Preparing Linux packages(Bats-core and more ...)
30 | if: runner.os == 'Linux'
31 | working-directory: ./tests
32 | run: |
33 | echo whoami: $(whoami)
34 | mkdir ./results
35 |
36 | sudo apt-get update -y
37 | sudo apt install git -y
38 |
39 | sudo apt-get install python3 -y
40 | sudo apt-get install python3-pip -y
41 |
42 | sudo pip install junit2html
43 |
44 | echo $(pip list)
45 |
46 | git --version
47 |
48 | echo "Adding: bats-core.git, bats-support.git and bats-assert.git"
49 | git clone https://github.com/bats-core/bats-core.git ./bats
50 | git clone https://github.com/bats-core/bats-support.git ./bats-support
51 | git clone https://github.com/bats-core/bats-assert.git ./bats-assert
52 |
53 | ./bats/bin/bats -v
54 |
55 | - name: Running tests ... Options
56 | working-directory: ./tests
57 | run: |
58 | echo pwd: $PWD
59 | echo dir: $(ls ./)
60 | ./bats/bin/bats -r ./Options --show-output-of-passing-tests --print-output-on-failure --report-formatter junit --output ./results
61 |
62 | - name: Generating report
63 | if: always()
64 | working-directory: ./tests/results
65 | run: |
66 | echo pwd: $PWD
67 | junit2html report.xml --report-matrix report.html
68 |
69 | - name: Uploading report
70 | uses: actions/upload-artifact@v4
71 | if: success() || failure()
72 | with:
73 | name: Results
74 | path: "./tests/results"
75 |
76 | - name: Notify slack tests succeeded
77 | if: success()
78 | env:
79 | SLACK_BOT_TOKEN: ${{ secrets.SLACK_NOTIFICATIONS_BOT_TOKEN }}
80 | uses: voxmedia/github-action-slack-notify-build@v1
81 | with:
82 | channel_id: C03E3JJGLQL
83 | status: SUCCESS
84 | color: good
85 |
86 | - name: Notify slack tests failed
87 | if: failure()
88 | env:
89 | SLACK_BOT_TOKEN: ${{ secrets.SLACK_NOTIFICATIONS_BOT_TOKEN }}
90 | uses: voxmedia/github-action-slack-notify-build@v1
91 | with:
92 | channel_id: C03E3JJGLQL
93 | status: FAILED
94 | color: danger
95 |
--------------------------------------------------------------------------------
/.github/workflows/purge-images.yml:
--------------------------------------------------------------------------------
1 | name: Purge GitHub container registry.
2 |
3 | on:
4 | workflow_dispatch:
5 | # Runs daily at midnight
6 | schedule:
7 | - cron: '0 0 * * *'
8 |
9 | jobs:
10 | purge-images:
11 | if: github.repository == 'veraPDF/veraPDF-rest'
12 | name: Delete old untagged images from ghcr.io
13 | runs-on: ubuntu-latest
14 | steps:
15 | - name: Delete all PR containers older than a week
16 | uses: snok/container-retention-policy@v2
17 | with:
18 | image-names: rest, arlington
19 | cut-off: 1 week ago UTC
20 | account-type: org
21 | org-name: veraPDF
22 | keep-at-least: 1
23 | skip-tags: latest
24 | untagged-only: false
25 | token: ${{ secrets.PAT }}
26 |
--------------------------------------------------------------------------------
/.github/workflows/push-dockerhub.yml:
--------------------------------------------------------------------------------
1 | name: Publish Docker image
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches: [ master ]
7 |
8 | jobs:
9 | push_to_registry:
10 | if: github.repository == 'veraPDF/veraPDF-rest'
11 | name: Push Docker image to Docker Hub
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Check out the repo
15 | uses: actions/checkout@v3
16 |
17 | - name: Log in to Docker Hub
18 | uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
19 | with:
20 | username: ${{ secrets.DOCKER_USERNAME }}
21 | password: ${{ secrets.DOCKER_PASSWORD }}
22 |
23 | - name: Extract metadata (tags, labels) for Docker
24 | id: meta
25 | uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
26 | with:
27 | images: verapdf/rest
28 |
29 | - name: Build and push Docker image
30 | uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
31 | with:
32 | context: .
33 | file: ./Dockerfile
34 | push: true
35 | tags: verapdf/rest:latest,verapdf/rest:v1.28.1
36 | labels: ${{ steps.meta.outputs.labels }}
37 |
--------------------------------------------------------------------------------
/.github/workflows/push-github.yml:
--------------------------------------------------------------------------------
1 | name: Publish image to GitHub Packages
2 | on:
3 | workflow_dispatch:
4 | push:
5 | branches:
6 | - 'integration'
7 |
8 | env:
9 | REGISTRY: ghcr.io
10 | IMAGE_NAME: veraPDF/rest
11 |
12 | jobs:
13 | publish:
14 | if: github.repository == 'veraPDF/veraPDF-rest'
15 | name: Build and push Docker image to GitHub packages
16 | runs-on: ubuntu-latest
17 |
18 | steps:
19 | - uses: actions/checkout@v3
20 |
21 | - name: Log in to the Container registry
22 | uses: docker/login-action@v2
23 | with:
24 | registry: ${{ env.REGISTRY }}
25 | username: ${{ github.actor }}
26 | password: ${{ secrets.GITHUB_TOKEN }}
27 |
28 | - name: Extract metadata (tags, labels) for GitHub
29 | id: meta
30 | uses: docker/metadata-action@v2
31 | with:
32 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
33 |
34 | - name: Build and push Docker image
35 | uses: docker/build-push-action@v2
36 | with:
37 | context: .
38 | push: true
39 | file: Dockerfile
40 | build-args: GH_CHECKOUT=integration
41 | tags: ghcr.io/verapdf/rest:latest
42 | labels: ${{ steps.meta.outputs.labels }}
43 |
44 | test:
45 | name: Test Docker image
46 | needs: [ publish ]
47 | runs-on: ubuntu-latest
48 | steps:
49 | - uses: actions/checkout@v3
50 |
51 | - name: Set up JDK 1.11
52 | uses: actions/setup-java@v1
53 | with:
54 | java-version: 1.11
55 |
56 | - name: Run rest-api-tests-with-docker-image
57 | uses: actions/github-script@v6
58 | with:
59 | github-token: ${{ secrets.WORKFLOW_TOKEN }}
60 | script: |
61 | await github.rest.actions.createWorkflowDispatch({
62 | owner: 'veraPDF',
63 | repo: 'veraPDF-rest',
64 | workflow_id: 'rest-api-tests-with-docker-image.yml',
65 | ref: 'integration'
66 | })
67 |
68 |
69 |
--------------------------------------------------------------------------------
/.github/workflows/rest-api-tests-with-docker-image.yml:
--------------------------------------------------------------------------------
1 | name: Rest-api tests - ghcr.io/verapdf/rest:latest
2 |
3 | on:
4 | schedule:
5 | - cron: "05 09 * * 1"
6 | workflow_dispatch:
7 |
8 | jobs:
9 | test:
10 | if: github.repository == 'veraPDF/veraPDF-rest'
11 | name: Rest-api tests running in Docker container
12 | runs-on: ubuntu-latest
13 | container: ubuntu
14 | services:
15 | verarest:
16 | image: ghcr.io/verapdf/rest:latest
17 | ports:
18 | - 8080:8080
19 | steps:
20 | - uses: actions/checkout@v3
21 |
22 | - name: Preparing Linux packages(Python and more ...)
23 | if: runner.os == 'Linux'
24 | run: |
25 | echo pwd: $PWD
26 | echo dir: $(ls ./)
27 |
28 | apt-get update -y
29 | apt-get install python3 -y
30 | apt-get install python3-pip -y
31 | echo install python3-venv -y
32 | apt-get install python3-venv -y
33 |
34 | echo python3 -m venv .venv
35 | python3 -m venv .venv
36 | echo . .venv/bin/activate
37 | . .venv/bin/activate
38 | echo which python
39 | which python
40 | echo python3 -m pip install -r requirements.txt
41 | python3 -m pip install -r requirements.txt
42 | echo $(pip list)
43 | echo pwd: $PWD
44 | mkdir ./results
45 | echo $(pip list)
46 | echo dir: $(ls ./)
47 | echo $(which python)
48 | echo $(pytest --version)
49 | pytest --base_url=http://verarest:8080 --html=./results/report.html ./tests/
50 | echo $(ls ./results/)
51 |
52 | - name: Generating report
53 | uses: actions/upload-artifact@v4
54 | if: success() || failure()
55 | with:
56 | name: Results
57 | path: "./results"
58 |
59 | - name: Notify slack tests succeeded
60 | if: success()
61 | env:
62 | SLACK_BOT_TOKEN: ${{ secrets.SLACK_NOTIFICATIONS_BOT_TOKEN }}
63 | uses: voxmedia/github-action-slack-notify-build@v1
64 | with:
65 | channel_id: C03E3JJGLQL
66 | status: SUCCESS
67 | color: good
68 |
69 | - name: Notify slack tests failed
70 | if: failure()
71 | env:
72 | SLACK_BOT_TOKEN: ${{ secrets.SLACK_NOTIFICATIONS_BOT_TOKEN }}
73 | uses: voxmedia/github-action-slack-notify-build@v1
74 | with:
75 | channel_id: C03E3JJGLQL
76 | status: FAILED
77 | color: danger
78 |
--------------------------------------------------------------------------------
/.github/workflows/test-dkr-build.yml:
--------------------------------------------------------------------------------
1 | name: Build Docker test container
2 |
3 | on:
4 | workflow_call
5 |
6 | env:
7 | REGISTRY: ghcr.io
8 | IMAGE_NAME: veraPDF/rest
9 |
10 | jobs:
11 | push_to_registry:
12 | if: github.repository == 'veraPDF/veraPDF-rest'
13 | name: Build and push Docker image to GitHub packages
14 | runs-on: ubuntu-latest
15 |
16 | steps:
17 | - uses: actions/checkout@v3
18 |
19 | - name: Log in to the Container registry
20 | uses: docker/login-action@v2
21 | with:
22 | registry: ${{ env.REGISTRY }}
23 | username: ${{ github.actor }}
24 | password: ${{ secrets.GITHUB_TOKEN }}
25 |
26 | - name: Extract metadata (tags, labels) for Docker
27 | id: meta
28 | uses: docker/metadata-action@v2
29 | with:
30 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
31 |
32 | - name: Build and push Docker image
33 | uses: docker/build-push-action@v2
34 | with:
35 | context: .
36 | push: true
37 | file: Dockerfile_dev
38 | tags: ghcr.io/verapdf/rest:pr-${{github.event.number}}
39 | labels: ${{ steps.meta.outputs.labels }}
40 |
--------------------------------------------------------------------------------
/.github/workflows/test-dkr-image.yml:
--------------------------------------------------------------------------------
1 | name: Test Docker deployment
2 |
3 | on:
4 | workflow_call
5 |
6 | jobs:
7 | test:
8 | name: Deploy and test image
9 | runs-on: ubuntu-latest
10 | container: ubuntu
11 | services:
12 | verarest:
13 | image: ghcr.io/verapdf/rest:pr-${{ github.event.pull_request.number }}
14 | ports:
15 | - 8080:8080
16 | steps:
17 | - name: Install wget
18 | run: apt-get update; apt-get install wget -y
19 | - name: Test Profiles endpoint
20 | run: wget -O- http://verarest:8080/api/profiles
21 | - name: Test 1B profile endpoint
22 | run: wget -O- http://verarest:8080/api/profiles/1b
23 |
--------------------------------------------------------------------------------
/.github/workflows/test-pr.yml:
--------------------------------------------------------------------------------
1 | name: PR QA
2 |
3 | on:
4 | pull_request:
5 | types: [opened, synchronize, reopened]
6 |
7 | jobs:
8 | build:
9 | name: Checkout and Build
10 | runs-on: ubuntu-latest
11 |
12 | continue-on-error: true
13 |
14 | strategy:
15 | fail-fast: false
16 | matrix:
17 | java-version: [8, 11, 17, 21]
18 |
19 | steps:
20 | - uses: actions/checkout@v4
21 |
22 | - name: JDK setup
23 | uses: actions/setup-java@v4
24 | with:
25 | java-version: ${{ matrix.java-version }}
26 | distribution: 'temurin'
27 | cache: maven
28 |
29 | - name: Build with Maven
30 | run: mvn --batch-mode --update-snapshots verify
31 |
32 | docker_build:
33 | name: Build a test Docker image and add to GH container registry
34 | needs: [ build ]
35 | uses: veraPDF/veraPDF-rest/.github/workflows/test-dkr-build.yml@integration
36 |
37 | docker_test:
38 | name: Deploy and test the image built in previous step
39 | needs: [ docker_build ]
40 | uses: veraPDF/veraPDF-rest/.github/workflows/test-dkr-image.yml@integration
41 |
--------------------------------------------------------------------------------
/.github/workflows/update-arlington-workflow.yml:
--------------------------------------------------------------------------------
1 | name: Update arlington branch
2 |
3 | on:
4 | push:
5 | branches:
6 | - integration
7 |
8 | jobs:
9 | checkout-and-build:
10 | if: github.repository == 'veraPDF/veraPDF-rest'
11 | runs-on: ubuntu-latest
12 |
13 | strategy:
14 | fail-fast: false
15 | matrix:
16 | java-version: [11, 17, 21]
17 |
18 | steps:
19 | - name: Checkout code
20 | uses: actions/checkout@v4
21 | with:
22 | fetch-depth: 0
23 | ref: integration
24 | - name: JDK setup
25 | uses: actions/setup-java@v4
26 | continue-on-error: true
27 | with:
28 | java-version: ${{ matrix.java-version }}
29 | distribution: 'temurin'
30 | cache: maven
31 | - name: Fetch arlington branch and checkout
32 | run: |
33 | git fetch origin arlington:arlington
34 | git checkout -b test-branch arlington
35 | - name: Configure user name
36 | run: |
37 | git config user.name "Git User"
38 | git config user.email "user@test.com"
39 | - name: Add commit to the test branch
40 | run: git cherry-pick -m 1 ${{ github.event.before }}..${{ github.event.after }} --empty=drop
41 | - name: Build project with Maven
42 | if: success()
43 | run: mvn --batch-mode --update-snapshots verify
44 |
45 | merge:
46 | runs-on: ubuntu-latest
47 | needs: checkout-and-build
48 | steps:
49 | - name: Checkout code
50 | uses: actions/checkout@v4
51 | with:
52 | fetch-depth: 0
53 | ref: integration
54 | - name: Generate new branch name
55 | id: new-branch-name
56 | run: echo "branch_name=new-branch-$(date +%s)" >> "$GITHUB_OUTPUT"
57 | - name: Fetch arlington branch and checkout
58 | run: |
59 | git fetch origin arlington:arlington
60 | git checkout -b ${{ steps.new-branch-name.outputs.branch_name }} arlington
61 | - name: Configure user name
62 | run: |
63 | git config user.name "Git User"
64 | git config user.email "user@temp.com"
65 | - name: Add commit to new branch
66 | run: git cherry-pick -m 1 ${{ github.event.before }}..${{ github.event.after }} --empty=drop
67 | - name: Merge branch into arlington
68 | if: success()
69 | run: |
70 | git push origin ${{ steps.new-branch-name.outputs.branch_name }}
71 | git checkout arlington
72 | git merge ${{ steps.new-branch-name.outputs.branch_name }}
73 | git push origin arlington
74 | - name: Delete new branch
75 | run: git push origin --delete ${{ steps.new-branch-name.outputs.branch_name }}
76 |
77 | send-notification:
78 | runs-on: ubuntu-latest
79 | needs: [checkout-and-build, merge]
80 | if: |
81 | always() &&
82 | github.repository == 'veraPDF/veraPDF-rest' &&
83 | (contains(needs.*.result, 'failure') ||
84 | contains(needs.*.result, 'skipped') ||
85 | contains(needs.*.result, 'cancelled'))
86 | steps:
87 | - name: Send notification if build or merge failed
88 | env:
89 | SLACK_BOT_TOKEN: ${{ secrets.SLACK_NOTIFICATIONS_BOT_TOKEN }}
90 | uses: voxmedia/github-action-slack-notify-build@v1
91 | with:
92 | channel_id: C03E3JJGLQL
93 | status: FAILED
94 | color: danger
95 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore Maven artifacts
2 | target/
3 | pom.xml.tag
4 | pom.xml.releaseBackup
5 | pom.xml.versionsBackup
6 | pom.xml.next
7 | release.properties
8 | dependency-reduced-pom.xml
9 | buildNumber.properties
10 | .mvn/timing.properties
11 |
12 | # Ignore VS code
13 | .vscode
14 |
15 | # Ignore Eclipse artifacts
16 | .project
17 | .settings
18 | .classpath
19 | bin/
20 |
21 | # Ignore IDEA files
22 | .idea/
23 | *.iml
24 |
25 | # Ignore pytest files
26 | .pytest_cache
27 |
28 | # Ignore external libraries
29 | bats-assert/
30 | bats-support/
31 | ./verapdf/
32 | *.pyc
33 | *.log
34 | *.html
35 | *.css
36 | *.code-workspace
37 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # See https://docs.docker.com/engine/userguide/eng-image/multistage-build/
2 | # First build the app on a maven open jdk 11 container
3 | FROM maven:3-eclipse-temurin-11-alpine AS app-builder
4 | RUN apk add --no-cache git
5 | WORKDIR /build
6 |
7 | # A specifc git branch, tag or commit to build from, defaults to master (release build)
8 | ARG GH_CHECKOUT
9 | ENV GH_CHECKOUT=${GH_CHECKOUT:-master}
10 |
11 | # Clone the repo, checkout the revision and build the application
12 | RUN git clone https://github.com/veraPDF/veraPDF-rest.git
13 |
14 | WORKDIR /build/veraPDF-rest
15 | RUN git checkout ${GH_CHECKOUT} && mvn clean package
16 |
17 | # Now build a Java JRE for the Alpine application image
18 | # https://github.com/docker-library/docs/blob/master/eclipse-temurin/README.md#creating-a-jre-using-jlink
19 | FROM eclipse-temurin:11-jdk-alpine as jre-builder
20 |
21 | # Create a custom Java runtime
22 | RUN "$JAVA_HOME/bin/jlink" \
23 | --add-modules java.base,java.logging,java.xml,java.management,java.sql,java.desktop,jdk.crypto.ec \
24 | --strip-debug \
25 | --no-man-pages \
26 | --no-header-files \
27 | --compress=2 \
28 | --output /javaruntime
29 |
30 | # Now the final application image
31 | FROM alpine:3
32 |
33 | # Specify the veraPDF REST version if you want to (to be used in build automation), default is 1.29.1
34 | ARG VERAPDF_REST_VERSION
35 | ENV VERAPDF_REST_VERSION=${VERAPDF_REST_VERSION:-1.29.1}
36 |
37 | # Set up dumb-init for process safety: https://github.com/Yelp/dumb-init
38 | ADD --link https://github.com/Yelp/dumb-init/releases/download/v1.2.5/dumb-init_1.2.5_x86_64 /usr/local/bin/dumb-init
39 | RUN chmod +x /usr/local/bin/dumb-init
40 |
41 | # Copy the JRE from the previous stage
42 | ENV JAVA_HOME=/opt/java/openjdk
43 | ENV PATH "${JAVA_HOME}/bin:${PATH}"
44 | COPY --from=jre-builder /javaruntime $JAVA_HOME
45 |
46 | # Since this is a running network service we'll create an unprivileged account
47 | # which will be used to perform the rest of the work and run the actual service:
48 | RUN addgroup -S verapdf-rest && adduser --system -D --home /opt/verapdf-rest -G verapdf-rest verapdf-rest
49 | RUN mkdir --parents /var/opt/verapdf-rest/logs && chown -R verapdf-rest:verapdf-rest /var/opt/verapdf-rest
50 |
51 | USER verapdf-rest
52 | WORKDIR /opt/verapdf-rest
53 |
54 | # Copy the application from the previous stage
55 | COPY --from=app-builder /build/veraPDF-rest/target/verapdf-rest-${VERAPDF_REST_VERSION}.jar /opt/verapdf-rest/verapdf-rest.jar
56 | # Copy the default configuration file
57 | COPY --from=app-builder /build/veraPDF-rest/server.yml /var/opt/verapdf-rest/config/
58 | COPY --from=app-builder /build/veraPDF-rest/config /opt/verapdf-rest/config/
59 |
60 | VOLUME /var/opt/verapdf-rest
61 | EXPOSE 8080
62 |
63 | ENTRYPOINT [ "dumb-init", "--" ]
64 | CMD ["java", "-Djava.awt.headless=true", "-jar", "/opt/verapdf-rest/verapdf-rest.jar", "server", "/var/opt/verapdf-rest/config/server.yml"]
65 |
--------------------------------------------------------------------------------
/Dockerfile_dev:
--------------------------------------------------------------------------------
1 | # See https://docs.docker.com/engine/userguide/eng-image/multistage-build/
2 | # First build the app on a maven open jdk 11 container
3 | FROM maven:3-eclipse-temurin-11-alpine AS dev-builder
4 | WORKDIR /build
5 |
6 | # Copy the current dev source branch to a local build dir
7 | COPY src/ /build/veraPDF-rest/src/
8 | COPY pom.xml /build/veraPDF-rest/
9 |
10 | WORKDIR /build/veraPDF-rest
11 | RUN mvn clean package
12 |
13 | # Now build a Java JRE for the Alpine application image
14 | # https://github.com/docker-library/docs/blob/master/eclipse-temurin/README.md#creating-a-jre-using-jlink
15 | FROM eclipse-temurin:11-jdk-alpine as jre-builder
16 |
17 | # Create a custom Java runtime
18 | RUN "$JAVA_HOME/bin/jlink" \
19 | --add-modules java.base,java.logging,java.xml,java.management,java.sql,java.desktop,jdk.crypto.ec \
20 | --strip-debug \
21 | --no-man-pages \
22 | --no-header-files \
23 | --compress=2 \
24 | --output /javaruntime
25 |
26 | # Now the final application image
27 | FROM alpine:3
28 |
29 | # Specify the veraPDF REST version if you want to (to be used in build automation), default is 1.29.1
30 | ARG VERAPDF_REST_VERSION
31 | ENV VERAPDF_REST_VERSION=${VERAPDF_REST_VERSION:-1.29.1}
32 |
33 | # Set up dumb-init for process safety: https://github.com/Yelp/dumb-init
34 | ADD --link https://github.com/Yelp/dumb-init/releases/download/v1.2.5/dumb-init_1.2.5_x86_64 /usr/local/bin/dumb-init
35 | RUN chmod +x /usr/local/bin/dumb-init
36 |
37 | # Copy the JRE from the previous stage
38 | ENV JAVA_HOME=/opt/java/openjdk
39 | ENV PATH "${JAVA_HOME}/bin:${PATH}"
40 | COPY --from=jre-builder /javaruntime $JAVA_HOME
41 |
42 | # Since this is a running network service we'll create an unprivileged account
43 | # which will be used to perform the rest of the work and run the actual service:
44 | RUN addgroup -S verapdf-rest && adduser --system -D --home /opt/verapdf-rest -G verapdf-rest verapdf-rest
45 | RUN mkdir --parents /var/opt/verapdf-rest/logs && chown -R verapdf-rest:verapdf-rest /var/opt/verapdf-rest
46 |
47 | USER verapdf-rest
48 | WORKDIR /opt/verapdf-rest
49 | # Copy the application from the previous stage
50 | COPY --from=dev-builder /build/veraPDF-rest/target/verapdf-rest-${VERAPDF_REST_VERSION}.jar /opt/verapdf-rest/verapdf-rest.jar
51 |
52 | # Copy the default configuration file
53 | COPY server.yml /var/opt/verapdf-rest/config/
54 | COPY config /opt/verapdf-rest/config/
55 |
56 | VOLUME /var/opt/verapdf-rest
57 | EXPOSE 8080
58 |
59 | ENTRYPOINT [ "dumb-init", "--" ]
60 | CMD ["java", "-Djava.awt.headless=true", "-jar", "/opt/verapdf-rest/verapdf-rest.jar", "server", "/var/opt/verapdf-rest/config/server.yml"]
61 |
--------------------------------------------------------------------------------
/Pipfile:
--------------------------------------------------------------------------------
1 | [[source]]
2 | url = "https://pypi.python.org/simple"
3 | verify_ssl = true
4 | name = "pypi"
5 |
6 | [packages]
7 |
8 | [dev-packages]
9 |
10 | [requires]
11 | python_version = "3.9"
12 |
--------------------------------------------------------------------------------
/Pipfile.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_meta": {
3 | "hash": {
4 | "sha256": "b20aaa9718024ec28b53570df5a504bc1765bb9490e31099da47c34bd616c357"
5 | },
6 | "pipfile-spec": 6,
7 | "requires": {
8 | "python_version": "3.9"
9 | },
10 | "sources": [
11 | {
12 | "name": "pypi",
13 | "url": "https://pypi.python.org/simple",
14 | "verify_ssl": true
15 | }
16 | ]
17 | },
18 | "default": {},
19 | "develop": {}
20 | }
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | veraPDF-rest
2 | =========================
3 |
4 | *Dropwizard based veraPDF REST Services*
5 |
6 | Introduction
7 | ------------
8 | This represents a development prototype, there's little in the way of exception handling and unit testing.
9 | The services are capable of serving up XML or JSON dependent upon the content type requested.
10 |
11 | ### Technologies
12 | The project's a Maven managed Java application, the application is based on
13 | [Dropwizard](https://www.dropwizard.io/en/stable/index.html), this brings together a set of reliable libraries, the
14 | following are most used and may prove informative if you are reading the code:
15 |
16 | * [Jetty](https://www.eclipse.org/jetty/) as a lean HTTP server,
17 | * [Jersey](https://jersey.java.net/) for REST services and associated, and
18 | * [Jackson](https://github.com/FasterXML/jackson/) for JSON and XML serialisation.
19 |
20 | A good place to get going is the [Dropwizard getting started guide](https://www.dropwizard.io/en/stable/getting-started.html).
21 | The [Dropwizard core documentation](https://www.dropwizard.io/en/stable/manual/core.html) covers the features used in the code base.
22 |
23 | Running DockerHub image
24 | --------------------
25 |
26 | To run the veraPDF rest image from DockerHub:
27 | ```
28 | docker run -d -p 8080:8080 -p 8081:8081 verapdf/rest:latest
29 | ```
30 |
31 | Port 8080 serves both the veraPDF web interface and the veraPDF Rest API. Port 8081 serves the DropWizard diagnostics.
32 |
33 | Building and running locally
34 | --------------------
35 |
36 | ### Docker
37 | This uses a Docker multi-stage build so the final container image which
38 | may be deployed does not require more than the base OpenJDK JRE without
39 | the entire build tool-chain.
40 |
41 | Tested lightly:
42 |
43 | ```
44 | docker build -t verapdf-rest:latest . && docker run -d -p 8080:8080 -p 8081:8081 verapdf-rest:latest
45 | ```
46 |
47 | If you encounter an error during docker run about "Can't set cookie dm_task_set_cookie failed", try:
48 |
49 | ```
50 | sudo dmsetup udevcomplete_all
51 | ```
52 |
53 | The built verapdf-rest image is notable smaller than just the base Maven image even before you consider the
54 | downloaded dependencies so the multi-stage build is definitely worthwhile:
55 |
56 | ```
57 | cadams@ganymede:~ $ docker images
58 | REPOSITORY TAG IMAGE ID CREATED SIZE
59 | verapdf-rest latest c3c2a52a7bc0 5 minutes ago 297MB
60 | maven latest 88714384d642 11 days ago 749MB
61 | ```
62 |
63 | Using the Alpine-based OpenJRE images provides a further hefty size reduction and we don't seem to be using
64 | anything which would be easier on Ubuntu:
65 |
66 | ```
67 | verapdf-rest latest c69af6445b35 31 seconds ago 103MB
68 | ```
69 |
70 | There's an "official" docker image that can be grabbed by `docker pull verapdf/rest:latest`.
71 |
72 | ### Kubernetes
73 |
74 | To use veraPDF-rest in as k8s deployment with load balancing and dynamic number of replicas (2 to 4) run the command:
75 | ```
76 | kubectl apply -f kubernetes.yaml
77 | ```
78 |
79 | ### Project structure
80 | Currently it's delivered as a single Maven module, veraPDF-rest.
81 |
82 | ### Swagger documentation
83 | Swagger documentation is available at [localhost:8080/swagger](http://localhost:8080/swagger).
84 |
85 | ### Want to try?
86 | First clone this project, go to the project directory, checkout to `master` branch for release version or `integration`
87 | branch for dev version, and then build the Maven project:
88 |
89 | git clone https://github.com/veraPDF/veraPDF-rest.git
90 | cd veraPDF-rest
91 | git checkout master
92 | mvn clean package
93 |
94 | To start up the server:
95 |
96 | java -jar target/verapdf-rest-1.28.1.jar server server.yml
97 |
98 | Go to [localhost:8080/api/info](http://localhost:8080/api/info) to see if the server is running, you should
99 | see something like:
100 |
101 |
').text(pdfaValidator.details.description + ' v' + pdfaValidator.details.version) 46 | $('#footer').append(footer) 47 | }) 48 | pdfaValidator.getRelease(function () { 49 | let footer = $('
').text(pdfaValidator.release.id + ' v' + pdfaValidator.release.version + ' ' + new Date(pdfaValidator.release.buildDate).toLocaleString()) 50 | $('#footer').append(footer) 51 | }) 52 | $('.btn-file :file').on('fileselect', function (event, numFiles, label, digest) { 53 | let input = $(this).parents('.input-group').find(':text') 54 | let log = numFiles > 1 ? numFiles + ' files selected' : label 55 | 56 | if (input.length) { 57 | input.val(log) 58 | if (!errorOnLoadType) $('.nextBtn').show(); 59 | } else { 60 | if (log) alert(log) 61 | } 62 | $('#sha1Hex').val(digest) 63 | }) 64 | }) 65 | 66 | $(document).ready(function () { 67 | if($('#fileInput')[0].files.length === 0 ){ 68 | $('.nextBtn').hide(); 69 | } 70 | let navListItems = $('div.setup-panel div a') 71 | let allWells = $('.setup-content') 72 | var allPreviousBtn = $('.previousBtn') 73 | var allNextBtn = $('.nextBtn') 74 | 75 | allWells.hide() 76 | 77 | navListItems.click(function (e) { 78 | e.preventDefault() 79 | var $target = $($(this).attr('href')) 80 | var $item = $(this) 81 | 82 | if (!$item.hasClass('disabled')) { 83 | navListItems.removeClass('btn-primary').addClass('btn-default') 84 | $item.addClass('btn-primary') 85 | allWells.hide() 86 | $target.show() 87 | $target.find('input:eq(0)').focus() 88 | } 89 | $('#download-results-btn').hide(); 90 | }) 91 | 92 | allNextBtn.click(function () { 93 | var curStep = $(this).closest('.setup-content') 94 | var curStepBtn = curStep.attr('id') 95 | var nextStepWizard = $('div.setup-panel div a[href="#' + curStepBtn + '"]').parent().next().children('a') 96 | var curInputs = curStep.find("input[type='text'],input[type='url']") 97 | var isValid = true 98 | $('.form-group').removeClass('has-error') 99 | for (var i = 0; i < curInputs.length; i++) { 100 | if (!curInputs[i].validity.valid) { 101 | isValid = false 102 | $(curInputs[i]).closest('.form-group').addClass('has-error') 103 | } 104 | } 105 | 106 | if (isValid) { 107 | nextStepWizard.removeAttr('disabled') 108 | nextStepWizard[0].click(); 109 | } 110 | if (curStepBtn === 'configure') { 111 | callVeraPdfService() 112 | } 113 | }) 114 | 115 | allPreviousBtn.click(function () { 116 | var curStep = $(this).closest('.setup-content') 117 | var curStepBtn = curStep.attr('id') 118 | var nextStepWizard = $('div.setup-panel div a[href="#' + curStepBtn + '"]').parent().prev().children('a') 119 | var curInputs = curStep.find("input[type='text'],input[type='url']") 120 | var isValid = true 121 | $('.form-group').removeClass('has-error') 122 | for (var i = 0; i < curInputs.length; i++) { 123 | if (!curInputs[i].validity.valid) { 124 | isValid = false 125 | $(curInputs[i]).closest('.form-group').addClass('has-error') 126 | } 127 | } 128 | 129 | if (isValid) { 130 | nextStepWizard.removeAttr('disabled') 131 | nextStepWizard[0].click(); 132 | } 133 | }) 134 | 135 | $('#download-results-btn').hide(); 136 | 137 | $('div.setup-panel div a.btn-primary').trigger('click') 138 | }) 139 | 140 | // Default profile flavour to use for validation 141 | var flavour = 'auto' 142 | 143 | function changeFlavour (newFlavour) { 144 | flavour = newFlavour 145 | } 146 | 147 | var outputFormat = 'html' 148 | 149 | function changeOutputFormat (newFormat) { 150 | outputFormat = newFormat; 151 | } 152 | 153 | function callVeraPdfService () { 154 | var formData = new FormData($('form')[0]) 155 | $.when($('#results').empty()).then(addFileConfigurationToResult()); 156 | var spinHtml = $('#spinner-template').html() 157 | $('#results').html(spinHtml) 158 | var selectedFile = $('#fileInput')[0].files[0]; 159 | pdfaValidator.validate(formData, flavour, function () { 160 | $.when(renderResult()).done(showDownloadBtn()); 161 | }, outputFormat, selectedFile.size) 162 | } 163 | 164 | function addFileConfigurationToResult () { 165 | $("#result-details").text($('#fileInput')[0].files[0].name); 166 | } 167 | 168 | function showDownloadBtn () { 169 | $('#download-results-btn').show(); 170 | } 171 | 172 | function renderResult () { 173 | $('#results').empty() 174 | if (outputFormat === 'html') { 175 | $('#results').html(pdfaValidator.result) 176 | } else { 177 | var preBlock = $('
').text(pdfaValidator.result) 178 | $('#results').append(preBlock) 179 | } 180 | } 181 | 182 | function downloadResult () { 183 | var texts = pdfaValidator.result; 184 | var hidden_a = document.createElement('a'); 185 | switch(outputFormat) { 186 | case 'html': hidden_a.setAttribute('href', 'data:text/html;charset=utf-8,'+ encodeURIComponent(texts)); 187 | break; 188 | case 'xml': hidden_a.setAttribute('href', 'data:application/xml;charset=utf-8,'+ encodeURIComponent(texts)); 189 | break; 190 | case 'json': hidden_a.setAttribute('href', 'data:application/json;charset=utf-8,'+ encodeURIComponent(texts)); 191 | break; 192 | default: hidden_a.setAttribute('href', 'data:text/plain;charset=utf-8,'+ encodeURIComponent(texts)); 193 | break; 194 | } 195 | 196 | hidden_a.setAttribute('download', "validation_results"); 197 | document.body.appendChild(hidden_a); 198 | hidden_a.click(); 199 | } 200 | 201 | $(window).on('load', function(){ 202 | $('#filename').val(''); 203 | $('#sha1Hex').val(''); 204 | flavour = 'auto'; 205 | outputFormat = 'html'; 206 | $("#flavour option:selected").prop("selected", false); 207 | $("#outputFormat option:selected").prop("selected", false); 208 | }); -------------------------------------------------------------------------------- /src/main/resources/org/verapdf/release/rest.properties: -------------------------------------------------------------------------------- 1 | verapdf.project.id=${project.artifactId} 2 | verapdf.release.version=${project.version} 3 | verapdf.release.date=${verapdf.timestamp} 4 | verapdf.date.format=${maven.build.timestamp.format} 5 | -------------------------------------------------------------------------------- /tests/Options/config/app/format.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | setup() { 4 | PROJECT_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../.." >/dev/null 2>&1 && pwd)" 5 | load "$PROJECT_ROOT/tools/test_helper/common-setup.bash" 6 | _common_setup 7 | 8 | prepare_fresh_verapdf_config_files 9 | 10 | docker cp $BATS_TEST_DIRNAME/format/app.xml $DOCKER_CONTAINER:/opt/verapdf-rest/config/app.xml 11 | 12 | } 13 | 14 | teardown() { 15 | docker cp $DOCKER_CONTAINER:/opt/verapdf-rest/config/app.xml $BATS_TEST_TMPDIR 16 | cat $BATS_TEST_TMPDIR/app.xml >&3 17 | 18 | echo -e "Done ..." >&3 19 | } 20 | 21 | @test "--format, Chooses output format, format=XML" { 22 | 23 | run curl -F "file=@$PROJECT_ROOT/Resources/Mustang_505.pdf" localhost:8080/api/validate/1b -H 'accept: application/xml' 24 | assert_output --partial "Mustang_505.pdf " 25 | 26 | [ "$status" -eq 0 ] 27 | } 28 | 29 | @test "--format, Chooses output format, the default format=JSON" { 30 | 31 | run curl -F "file=@$PROJECT_ROOT/Resources/Mustang_505.pdf" localhost:8080/api/validate/1b 32 | assert_output --partial '"jobEndStatus" : "normal"' 33 | 34 | [ "$status" -eq 0 ] 35 | } 36 | -------------------------------------------------------------------------------- /tests/Options/config/app/format/app.xml: -------------------------------------------------------------------------------- 1 | 2 |3 | 7 | -------------------------------------------------------------------------------- /tests/Options/config/app/type.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | setup() { 4 | PROJECT_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../.." >/dev/null 2>&1 && pwd)" 5 | load "$PROJECT_ROOT/tools/test_helper/common-setup.bash" 6 | _common_setup 7 | 8 | prepare_fresh_verapdf_config_files 9 | 10 | docker cp $BATS_TEST_DIRNAME/type/app.xml $DOCKER_CONTAINER:/opt/verapdf-rest/config/app.xml 11 | docker cp $BATS_TEST_DIRNAME/type/features.xml $DOCKER_CONTAINER:/opt/verapdf-rest/config/features.xml 12 | docker cp $BATS_TEST_DIRNAME/type/validator.xml $DOCKER_CONTAINER:/opt/verapdf-rest/config/validator.xml 13 | 14 | } 15 | 16 | teardown() { 17 | docker cp $DOCKER_CONTAINER:/opt/verapdf-rest/config/app.xml $BATS_TEST_TMPDIR 18 | docker cp $DOCKER_CONTAINER:/opt/verapdf-rest/config/validator.xml $BATS_TEST_TMPDIR 19 | docker cp $DOCKER_CONTAINER:/opt/verapdf-rest/config/features.xml $BATS_TEST_TMPDIR 20 | 21 | cat $BATS_TEST_TMPDIR/app.xml >&3 22 | cat $BATS_TEST_TMPDIR/validator.xml >&3 23 | cat $BATS_TEST_TMPDIR/features.xml >&3 24 | 25 | echo -e "Done ..." >&3 26 | } 27 | 28 | @test "--type, The default processing model for the GUI, type=VALIDATE_EXTRACT" { 29 | 30 | run curl -F "file=@$PROJECT_ROOT/Resources/5-t02-fail-a.pdf" localhost:8080/api/validate/ua1 -H "Accept:text/html" 31 | assert_output --partial "Information dictionary" 32 | assert_output --partial "4 | https://github.com/veraPDF/veraPDF-validation-profiles/wiki/ 5 |6 | PDF/UA-1 validation profile " 33 | 34 | [ "$status" -eq 0 ] 35 | } 36 | -------------------------------------------------------------------------------- /tests/Options/config/app/type/app.xml: -------------------------------------------------------------------------------- 1 | 2 |3 | 7 | -------------------------------------------------------------------------------- /tests/Options/config/app/type/features.xml: -------------------------------------------------------------------------------- 1 | 2 |4 | https://github.com/veraPDF/veraPDF-validation-profiles/wiki/ 5 |6 | 3 | 7 | -------------------------------------------------------------------------------- /tests/Options/config/app/type/validator.xml: -------------------------------------------------------------------------------- 1 | 2 |4 | 6 |INFORMATION_DICTIONARY 5 |3 | -------------------------------------------------------------------------------- /tests/Options/config/app/wikiPath.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | setup() { 4 | PROJECT_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../.." >/dev/null 2>&1 && pwd)" 5 | load "$PROJECT_ROOT/tools/test_helper/common-setup.bash" 6 | _common_setup 7 | 8 | prepare_fresh_verapdf_config_files 9 | 10 | sed -i '3 c\ '$BATS_TEST_TMPDIR' ' $BATS_TEST_DIRNAME/wikiPath/app.xml 11 | docker cp $BATS_TEST_DIRNAME/wikiPath/app.xml $DOCKER_CONTAINER:/opt/verapdf-rest/config/app.xml 12 | 13 | } 14 | 15 | teardown() { 16 | docker cp $DOCKER_CONTAINER:/opt/verapdf-rest/config/app.xml $BATS_TEST_TMPDIR 17 | cat $BATS_TEST_TMPDIR/app.xml >&3 18 | echo -e "Done ..." >&3 19 | } 20 | 21 | @test "--wikiPath, Defines the base URL used to create reference links in the HTML report, wikiPath=https://baseURL.com/wiki/" { 22 | 23 | run curl -F "file=@$PROJECT_ROOT/Resources/Mustang_505.pdf" localhost:8080/api/validate/2b -H "Accept:text/html" 24 | assert_output --partial "https://baseURL.com/wiki/" 25 | 26 | [ "$status" -eq 0 ] 27 | } 28 | -------------------------------------------------------------------------------- /tests/Options/config/app/wikiPath/app.xml: -------------------------------------------------------------------------------- 1 | 2 |3 | 7 | -------------------------------------------------------------------------------- /tests/Options/config/features/features.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | setup() { 4 | PROJECT_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../.." >/dev/null 2>&1 && pwd)" 5 | load "$PROJECT_ROOT/tools/test_helper/common-setup.bash" 6 | _common_setup 7 | 8 | prepare_fresh_verapdf_config_files 9 | 10 | docker cp $BATS_TEST_DIRNAME/features/app.xml $DOCKER_CONTAINER:/opt/verapdf-rest/config/app.xml 11 | docker cp $BATS_TEST_DIRNAME/features/features.xml $DOCKER_CONTAINER:/opt/verapdf-rest/config/features.xml 12 | 13 | } 14 | 15 | teardown() { 16 | docker cp $DOCKER_CONTAINER:/opt/verapdf-rest/config/app.xml $BATS_TEST_TMPDIR 17 | cat $BATS_TEST_TMPDIR/app.xml >&3 18 | 19 | echo -e "\nDone ..." >&3 20 | } 21 | 22 | @test "--features, Extracts and reports PDF features, checking feature=ICCPROFILE" { 23 | 24 | run curl -F "file=@$PROJECT_ROOT/Resources/Mustang_505.pdf" localhost:8080/api/validate/1b -H "Accept:text/html" 25 | assert_output --partial "ICC profiles" 26 | 27 | [ "$status" -eq 0 ] 28 | } 29 | -------------------------------------------------------------------------------- /tests/Options/config/features/features/app.xml: -------------------------------------------------------------------------------- 1 | 2 |/tmp/bats-run-7DQP9j/test/3 4 |https://baseURL.com/wiki/ 5 |6 | 3 | 7 | -------------------------------------------------------------------------------- /tests/Options/config/features/features/features.xml: -------------------------------------------------------------------------------- 1 | 2 |4 | https://github.com/veraPDF/veraPDF-validation-profiles/wiki/ 5 |6 | 3 | 28 | -------------------------------------------------------------------------------- /tests/Options/config/validator/debug.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | BATS_TEST_TIMEOUT=120 # sec 3 | 4 | setup() { 5 | PROJECT_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../.." >/dev/null 2>&1 && pwd)" 6 | load "$PROJECT_ROOT/tools/test_helper/common-setup.bash" 7 | _common_setup 8 | 9 | prepare_fresh_verapdf_config_files 10 | 11 | docker cp $BATS_TEST_DIRNAME/debug/validator.xml $DOCKER_CONTAINER:/opt/verapdf-rest/config/validator.xml 12 | 13 | } 14 | 15 | teardown() { 16 | docker cp $DOCKER_CONTAINER:/opt/verapdf-rest/config/validator.xml $BATS_TEST_TMPDIR 17 | echo -e "\n" >&3 18 | cat $BATS_TEST_TMPDIR/validator.xml >&3 19 | 20 | echo -e "\nDone ..." >&3 21 | } 22 | 23 | @test "--debug, Outputs all processed file names, debug=true" { 24 | 25 | run curl -F "file=@$PROJECT_ROOT/Resources/a_for_debug.pdf" localhost:8080/api/validate/3a -H "Accept:text/html" 26 | [ "$status" -eq 0 ] 27 | 28 | sleep 3 # sleep sec 29 | run docker logs $DOCKER_CONTAINER -t --since=$test_logs_starting_time 30 | 31 | sleep 3 # sleep sec 32 | echo "$output" >&3 33 | assert_output --partial "INFO: a_for_debug.pdf" 34 | } 35 | -------------------------------------------------------------------------------- /tests/Options/config/validator/debug/validator.xml: -------------------------------------------------------------------------------- 1 | 2 |4 | 27 |ACTION 5 |ANNOTATION 6 |COLORSPACE 7 |DOCUMENT_SECURITY 8 |EMBEDDED_FILE 9 |EXT_G_STATE 10 |FONT 11 |FORM_XOBJECT 12 |ICCPROFILE 13 |IMAGE_XOBJECT 14 |INFORMATION_DICTIONARY 15 |INTERACTIVE_FORM_FIELDS 16 |LOW_LEVEL_INFO 17 |METADATA 18 |OUTLINES 19 |OUTPUTINTENT 20 |PAGE 21 |PATTERN 22 |POSTSCRIPT_XOBJECT 23 |PROPERTIES 24 |SHADING 25 |SIGNATURE 26 |3 | -------------------------------------------------------------------------------- /tests/Options/config/validator/flavour.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | setup() { 4 | PROJECT_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../.." >/dev/null 2>&1 && pwd)" 5 | load "$PROJECT_ROOT/tools/test_helper/common-setup.bash" 6 | _common_setup 7 | 8 | prepare_fresh_verapdf_config_files 9 | 10 | docker cp $BATS_TEST_DIRNAME/flavour/validator.xml $DOCKER_CONTAINER:/opt/verapdf-rest/config/validator.xml 11 | 12 | } 13 | 14 | teardown() { 15 | docker cp $DOCKER_CONTAINER:/opt/verapdf-rest/config/validator.xml $BATS_TEST_TMPDIR 16 | cat $BATS_TEST_TMPDIR/validator.xml >&3 17 | 18 | echo -e "\nDone ..." >&3 19 | } 20 | 21 | @test "--flavour, flavour will be applied based on a curl options, flavour=2b" { 22 | 23 | run curl -F "file=@$PROJECT_ROOT/Resources/a.pdf" localhost:8080/api/validate/2b -H 'accept: application/json' 24 | assert_output --partial '"profileName" : "PDF/A-2B validation profile"' 25 | 26 | [ "$status" -eq 0 ] 27 | } 28 | -------------------------------------------------------------------------------- /tests/Options/config/validator/flavour/validator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /tests/Options/config/validator/isLogsEnabled.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | setup() { 4 | PROJECT_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../.." >/dev/null 2>&1 && pwd)" 5 | load "$PROJECT_ROOT/tools/test_helper/common-setup.bash" 6 | _common_setup 7 | 8 | prepare_fresh_verapdf_config_files 9 | 10 | docker cp $BATS_TEST_DIRNAME/isLogsEnabled/validator.xml $DOCKER_CONTAINER:/opt/verapdf-rest/config/validator.xml 11 | 12 | } 13 | 14 | teardown() { 15 | docker cp $DOCKER_CONTAINER:/opt/verapdf-rest/config/validator.xml $BATS_TEST_TMPDIR 16 | cat $BATS_TEST_TMPDIR/validator.xml >&3 17 | 18 | echo -e "\nDone ..." >&3 19 | } 20 | 21 | @test "--isLogsEnabled, Add logs to report, isLogsEnabled=true" { 22 | 23 | run curl -F "file=@$PROJECT_ROOT/Resources/6.1.3-01-fail-5.pdf" localhost:8080/api/validate/1b -H "Accept:text/html" 24 | assert_output --partial "WARNING" 25 | assert_output --partial "SEVERE" 26 | 27 | [ "$status" -eq 0 ] 28 | } 29 | -------------------------------------------------------------------------------- /tests/Options/config/validator/isLogsEnabled/validator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /tests/Options/config/validator/loggingLevel.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | setup() { 4 | PROJECT_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../.." >/dev/null 2>&1 && pwd)" 5 | load "$PROJECT_ROOT/tools/test_helper/common-setup.bash" 6 | _common_setup 7 | 8 | prepare_fresh_verapdf_config_files 9 | 10 | 11 | docker cp $BATS_TEST_DIRNAME/loggingLevel/validator.xml $DOCKER_CONTAINER:/opt/verapdf-rest/config/validator.xml 12 | 13 | } 14 | 15 | teardown() { 16 | docker cp $DOCKER_CONTAINER:/opt/verapdf-rest/config/validator.xml $BATS_TEST_TMPDIR 17 | cat $BATS_TEST_TMPDIR/validator.xml >&3 18 | 19 | echo -e "\nDone ..." >&3 20 | } 21 | 22 | @test "--loggingLevel, Determine the log level, loggingLevel=ALL" { 23 | 24 | run curl -F "file=@$PROJECT_ROOT/Resources/orange.pdf" localhost:8080/api/validate/1b -H "Accept:text/html" 25 | assert_output --partial 'FINE' 26 | 27 | [ "$status" -eq 0 ] 28 | } 29 | -------------------------------------------------------------------------------- /tests/Options/config/validator/loggingLevel/validator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /tests/Options/config/validator/maxFails.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | setup() { 4 | PROJECT_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../.." >/dev/null 2>&1 && pwd)" 5 | load "$PROJECT_ROOT/tools/test_helper/common-setup.bash" 6 | _common_setup 7 | 8 | prepare_fresh_verapdf_config_files 9 | 10 | docker cp $BATS_TEST_DIRNAME/maxFails/validator* $DOCKER_CONTAINER:/opt/verapdf-rest/config 11 | } 12 | 13 | teardown() { 14 | docker cp $DOCKER_CONTAINER:/opt/verapdf-rest/config/validator.xml $BATS_TEST_TMPDIR 15 | cat $BATS_TEST_TMPDIR/validator.xml >&3 16 | 17 | echo -e "\nDone ..." >&3 18 | } 19 | 20 | @test "--maxFails, Sets maximum amount of failed checks, maxFails=1" { 21 | 22 | run curl -F "file=@$PROJECT_ROOT/Resources/veraPDFPDFAConformanceCheckerGUI.pdf" localhost:8080/api/validate/1b -H "Accept:application/xml" 23 | assert_output --partial 'failedRules="1"' 24 | 25 | [ "$status" -eq 0 ] 26 | } 27 | -------------------------------------------------------------------------------- /tests/Options/config/validator/maxFails/validator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /tests/Options/config/validator/maxNumberOfDisplayedFailedChecks.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | setup() { 4 | PROJECT_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../.." >/dev/null 2>&1 && pwd)" 5 | load "$PROJECT_ROOT/tools/test_helper/common-setup.bash" 6 | _common_setup 7 | 8 | prepare_fresh_verapdf_config_files 9 | 10 | } 11 | 12 | teardown() { 13 | docker cp $DOCKER_CONTAINER:/opt/verapdf-rest/config/validator.xml $BATS_TEST_TMPDIR 14 | cat $BATS_TEST_TMPDIR/validator.xml >&3 15 | 16 | echo -e "\nDone ..." >&3 17 | } 18 | 19 | @test "--maxNumberOfDisplayedFailedChecks, Sets maximum amount of failed checks displayed for each rule, maxNumberOfDisplayedFailedChecks=0" { 20 | 21 | docker cp $BATS_TEST_DIRNAME/maxNumberOfDisplayedFailedChecks/validator_Checks_0.xml $DOCKER_CONTAINER:/opt/verapdf-rest/config/validator.xml 22 | 23 | run curl -F "file=@$PROJECT_ROOT/Resources/a.pdf" localhost:8080/api/validate/1b -H "Accept:text/html" 24 | refute_output --partial 'Rule' 25 | 26 | [ "$status" -eq 0 ] 27 | } 28 | 29 | @test "--maxNumberOfDisplayedFailedChecks, Sets maximum amount of failed checks displayed for each rule, maxNumberOfDisplayedFailedChecks=2" { 30 | 31 | docker cp $BATS_TEST_DIRNAME/maxNumberOfDisplayedFailedChecks/validator_Checks_2.xml $DOCKER_CONTAINER:/opt/verapdf-rest/config/validator.xml 32 | 33 | failedChecks=$(curl -F "file=@$PROJECT_ROOT/Resources/5-t02-fail-a.pdf" localhost:8080/api/validate/1b -H "Accept:application/xml" | grep -w -o '(8 0 obj PDContentStream)' | grep -w -o PDContentStream | wc -w) 34 | 35 | echo -e "$failedChecks\n" >&3 36 | 37 | run echo $failedChecks 38 | assert_equal $failedChecks "2" 39 | 40 | [ "$status" -eq 0 ] 41 | } 42 | -------------------------------------------------------------------------------- /tests/Options/config/validator/maxNumberOfDisplayedFailedChecks/validator_Checks_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /tests/Options/config/validator/maxNumberOfDisplayedFailedChecks/validator_Checks_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /tests/Options/config/validator/recordPasses.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | setup() { 4 | PROJECT_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../.." >/dev/null 2>&1 && pwd)" 5 | load "$PROJECT_ROOT/tools/test_helper/common-setup.bash" 6 | _common_setup 7 | 8 | prepare_fresh_verapdf_config_files 9 | 10 | docker cp $BATS_TEST_DIRNAME/recordPasses/validator.xml $DOCKER_CONTAINER:/opt/verapdf-rest/config/validator.xml 11 | 12 | } 13 | 14 | teardown() { 15 | docker cp $DOCKER_CONTAINER:/opt/verapdf-rest/config/validator.xml $BATS_TEST_TMPDIR 16 | cat $BATS_TEST_TMPDIR/validator.xml >&3 17 | 18 | echo -e "\nDone ..." >&3 19 | } 20 | 21 | @test "--recordPasses, Logs successful validation checks, recordPasses=true" { 22 | 23 | run curl -F "file=@$PROJECT_ROOT/Resources/veraPDFPDFAConformanceCheckerGUI.pdf" localhost:8080/api/validate/1b -H "Accept:text/html" 24 | assert_output --partial 'Passed' 25 | 26 | [ "$status" -eq 0 ] 27 | } 28 | -------------------------------------------------------------------------------- /tests/Options/config/validator/recordPasses/validator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /tests/Options/config/validator/showErrorMessages.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | setup() { 4 | PROJECT_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../.." >/dev/null 2>&1 && pwd)" 5 | load "$PROJECT_ROOT/tools/test_helper/common-setup.bash" 6 | _common_setup 7 | 8 | prepare_fresh_verapdf_config_files 9 | 10 | docker cp $BATS_TEST_DIRNAME/showErrorMessages/validator.xml $DOCKER_CONTAINER:/opt/verapdf-rest/config/validator.xml 11 | 12 | } 13 | 14 | teardown() { 15 | docker cp $DOCKER_CONTAINER:/opt/verapdf-rest/config/validator.xml $BATS_TEST_TMPDIR 16 | cat $BATS_TEST_TMPDIR/validator.xml >&3 17 | 18 | echo -e "\nDone ..." >&3 19 | } 20 | 21 | @test "--showErrorMessages, Add detailed error message for each check, showErrorMessages=true" { 22 | 23 | run curl -F "file=@$PROJECT_ROOT/Resources/a.pdf" localhost:8080/api/validate/1b -H "Accept:text/html" 24 | assert_output --partial "the PDF/A Identification Schema is null" 25 | 26 | [ "$status" -eq 0 ] 27 | } 28 | -------------------------------------------------------------------------------- /tests/Options/config/validator/showErrorMessages/validator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /tests/Options/services/bindMountLocalFiles/steps_in_docker.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ls -la /home/ 4 | apk update 5 | apk add --no-cache curl 6 | cd /home/Res_tmp/ 7 | echo -e "\n" 8 | 9 | curl -F "file=@/home/Res_tmp/a.pdf" localhost:8080/api/validate/3a > res_tmp_log.log -H 'accept: application/xml' 10 | exit 11 | -------------------------------------------------------------------------------- /tests/Options/services/bindMountLocalFiles/withBindMountLocalFiles.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | BATS_TEST_TIMEOUT=120 # sec 3 | 4 | setup() { 5 | PROJECT_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../.." >/dev/null 2>&1 && pwd)" 6 | load "$PROJECT_ROOT/tools/test_helper/common-setup.bash" 7 | _common_setup 8 | 9 | prepare_fresh_verapdf_config_files 10 | 11 | } 12 | 13 | teardown() { 14 | echo -e "\nDone ..." >&3 15 | } 16 | 17 | @test "-v, Mounted local files in the Docker container check, bind /tmp:/home/Res_tmp" { 18 | 19 | docker cp $BATS_TEST_DIRNAME/steps_in_docker.sh $DOCKER_CONTAINER:/home/steps_in_docker.sh 20 | cp -f $PROJECT_ROOT/Resources/a.pdf /tmp/a.pdf 21 | 22 | run docker exec -i --user root $DOCKER_CONTAINER /home/steps_in_docker.sh 23 | 24 | echo "$output" >&3 25 | 26 | run cat /tmp/res_tmp_log.log 27 | 28 | echo "$output" >&3 29 | 30 | assert_output --partial " " 31 | assert_output --partial " a.pdf " 32 | assert_output --partial 'profileName="PDF/A-3A validation profile"' 33 | 34 | } 35 | -------------------------------------------------------------------------------- /tests/Options/services/limitingFileSize/limitingFileSize.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | BATS_TEST_TIMEOUT=120 # sec 3 | 4 | setup() { 5 | PROJECT_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../.." >/dev/null 2>&1 && pwd)" 6 | load "$PROJECT_ROOT/tools/test_helper/common-setup.bash" 7 | _common_setup 8 | 9 | prepare_fresh_verapdf_config_files 10 | 11 | } 12 | 13 | teardown() { 14 | echo -e "\nDone ..." >&3 15 | } 16 | 17 | @test "-e VERAPDF_MAX_FILE_SIZE, Limiting PDF file size, VERAPDF_MAX_FILE_SIZE=1 MB" { 18 | 19 | run curl -F "file=@$PROJECT_ROOT/Resources/PDFBOX_allowed_file_size.pdf" localhost:8080/api/validate/3a 20 | 21 | echo "$output" >&3 22 | assert_output --partial '"code":400' 23 | assert_output --partial '"Maximum allowed file size exceeded: 1 MB"}' 24 | 25 | [ "$status" -eq 0 ] 26 | } 27 | -------------------------------------------------------------------------------- /tests/Options/setup_suite.bash: -------------------------------------------------------------------------------- 1 | 2 | 3 | setup_suite() { 4 | echo -e "Starting tests ... \n" >&3 5 | export DOCKER_ID=$(docker ps | grep "rest:" | awk '{print $1}') 6 | } 7 | 8 | teardown_suite() { 9 | echo -e "\nEnding tests ... \n" >&3 10 | 11 | # docker logs $DOCKER_ID >&3 12 | 13 | sleep 3 # sleep sec 14 | 15 | docker logs "$DOCKER_ID" > ./results/container.log 2>&1 16 | sleep 3 # sleep sec 17 | } 18 | -------------------------------------------------------------------------------- /tests/Resources/5-t02-fail-a.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/Resources/5-t02-fail-a.pdf -------------------------------------------------------------------------------- /tests/Resources/6.1.3-01-fail-5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/Resources/6.1.3-01-fail-5.pdf -------------------------------------------------------------------------------- /tests/Resources/Mustang_505.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/Resources/Mustang_505.pdf -------------------------------------------------------------------------------- /tests/Resources/PDFBOX_allowed_file_size.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/Resources/PDFBOX_allowed_file_size.pdf -------------------------------------------------------------------------------- /tests/Resources/a.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/Resources/a.pdf -------------------------------------------------------------------------------- /tests/Resources/a_for_debug.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/Resources/a_for_debug.pdf -------------------------------------------------------------------------------- /tests/Resources/orange.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/Resources/orange.pdf -------------------------------------------------------------------------------- /tests/Resources/veraPDFPDFAConformanceCheckerGUI.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/Resources/veraPDFPDFAConformanceCheckerGUI.pdf -------------------------------------------------------------------------------- /tests/Resources/veraPDF_MF3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/Resources/veraPDF_MF3.pdf -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/__init__.py -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | def pytest_addoption(parser): 5 | parser.addoption( 6 | "--base_url", action="store", default="https://dev.verapdf-rest.duallab.com/" 7 | ) 8 | 9 | 10 | @pytest.fixture(scope="session") 11 | def get_base_url(request): 12 | url = request.config.getoption( 13 | "--base_url", default="https://dev.verapdf-rest.duallab.com/" 14 | ) 15 | print("\n\n#### Base_url ...", url) 16 | return url 17 | -------------------------------------------------------------------------------- /tests/rest_api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/rest_api/__init__.py -------------------------------------------------------------------------------- /tests/rest_api/model/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/rest_api/model/__init__.py -------------------------------------------------------------------------------- /tests/rest_api/model/api_info/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/rest_api/model/api_info/__init__.py -------------------------------------------------------------------------------- /tests/rest_api/model/api_info/api_endpoint.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from pydantic_xml import element 3 | from pydantic_xml import BaseXmlModel 4 | 5 | 6 | class ApiEndpoint(BaseModel): 7 | id: str 8 | version: str 9 | buildDate: int 10 | 11 | 12 | class ApiEndpointXml(BaseXmlModel, tag="ReleaseDetails"): 13 | id: str = element(tag="id") 14 | version: str = element(tag="version") 15 | buildDate: int = element(tag="buildDate") 16 | -------------------------------------------------------------------------------- /tests/rest_api/model/api_info/environment.py: -------------------------------------------------------------------------------- 1 | from pydantic_xml import BaseXmlModel 2 | from pydantic import BaseModel 3 | from tests.rest_api.model.api_info.java import JavaXml 4 | from tests.rest_api.model.api_info.os import OSXml 5 | from tests.rest_api.model.api_info.server import ServerXml 6 | 7 | 8 | from tests.rest_api.model.api_info.java import Java 9 | from tests.rest_api.model.api_info.os import OS 10 | from tests.rest_api.model.api_info.server import Server 11 | 12 | 13 | class Environment(BaseModel): 14 | java: Java 15 | os: OS 16 | server: Server 17 | 18 | 19 | class EnvironmentXml( 20 | BaseXmlModel, 21 | tag="Environment", 22 | # search_mode="unordered", 23 | ): 24 | os: OSXml 25 | java: JavaXml 26 | server: ServerXml 27 | -------------------------------------------------------------------------------- /tests/rest_api/model/api_info/java.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from pydantic_xml import BaseXmlModel, element 3 | 4 | 5 | class Java(BaseModel): 6 | vendor: str 7 | version: str 8 | architecture: str 9 | home: str 10 | 11 | 12 | class JavaXml(BaseXmlModel, tag="java"): 13 | vendor: str = element(tag="vendor") 14 | version: str = element(tag="version") 15 | architecture: str = element(tag="architecture") 16 | home: str = element(tag="home") 17 | -------------------------------------------------------------------------------- /tests/rest_api/model/api_info/os.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from pydantic_xml import BaseXmlModel, element 3 | 4 | 5 | class OS(BaseModel): 6 | name: str 7 | version: str 8 | architecture: str 9 | 10 | 11 | class OSXml(BaseXmlModel, tag="os"): 12 | name: str = element(tag="name") 13 | version: str = element(tag="version") 14 | architecture: str = element(tag="architecture") 15 | -------------------------------------------------------------------------------- /tests/rest_api/model/api_info/server.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from pydantic_xml import BaseXmlModel, element 3 | 4 | 5 | class Server(BaseModel): 6 | ipAddress: str 7 | hostName: str 8 | machAddress: str 9 | 10 | 11 | class ServerXml(BaseXmlModel, tag="server"): 12 | ipAddress: str = element(tag="ipAddress") 13 | hostName: str = element(tag="hostName") 14 | machAddress: str = element(tag="machAddress") 15 | -------------------------------------------------------------------------------- /tests/rest_api/model/api_profiles/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/rest_api/model/api_profiles/__init__.py -------------------------------------------------------------------------------- /tests/rest_api/model/api_profiles/profile.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from pydantic import BaseModel 4 | from pydantic_xml import BaseXmlModel, element 5 | 6 | 7 | class Profile(BaseModel): 8 | name: str 9 | description: str 10 | creator: str 11 | dateCreated: int 12 | 13 | 14 | class ProfileXMl(BaseXmlModel): 15 | name: str = element(tag="name") 16 | description: str = element(tag="description") 17 | creator: str = element(tag="creator") 18 | dateCreated: int = element(tag="dateCreated") 19 | 20 | 21 | class ProfilesXMl( 22 | BaseXmlModel, 23 | tag="HashSet", 24 | search_mode="unordered", 25 | ): 26 | items: List[ProfileXMl] = element(tag="item") 27 | -------------------------------------------------------------------------------- /tests/rest_api/model/api_profiles/profile_id.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from pydantic_xml import BaseXmlModel, element 3 | from tests.rest_api.model.api_profiles.profile import Profile, ProfileXMl 4 | from tests.rest_api.model.api_profiles.profile_variables import ProfileVariables 5 | from tests.rest_api.model.api_profiles.profile_rule import ProfileRule 6 | 7 | 8 | from typing import List 9 | 10 | 11 | class ProfileID(BaseModel): 12 | details: Profile 13 | rules: List[ProfileRule] 14 | variables: List[ProfileVariables] 15 | tags: List[str] 16 | pdfaflavour: str 17 | hexSha1Digest: str 18 | 19 | 20 | class ProfileIDXml( 21 | BaseXmlModel, 22 | tag="ValidationProfileImpl", 23 | search_mode="unordered", 24 | ): 25 | details: ProfileXMl 26 | pdfaflavour: str = element(tag="pdfaflavour") 27 | -------------------------------------------------------------------------------- /tests/rest_api/model/api_profiles/profile_ids.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from pydantic_xml import BaseXmlModel, element 4 | 5 | 6 | class ProfileIdsXMl(BaseXmlModel, tag="UnmodifiableSet"): 7 | item: List[str] = element(tag="item") 8 | -------------------------------------------------------------------------------- /tests/rest_api/model/api_profiles/profile_rule.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from pydantic import BaseModel 4 | from pydantic_xml import BaseXmlModel, element 5 | 6 | from tests.rest_api.model.api_profiles.rule_id import RuleID, RuleIDXml 7 | 8 | 9 | class ProfileRule(BaseModel): 10 | object: str 11 | description: str 12 | test: str 13 | ruleId: RuleID 14 | 15 | 16 | class ProfileRuleXml( 17 | BaseXmlModel, 18 | search_mode="unordered", 19 | ): 20 | object: str = element(tag="object") 21 | description: str = element(tag="description") 22 | ruleId: RuleIDXml 23 | 24 | 25 | class ProfileRuleSXml( 26 | BaseXmlModel, 27 | tag="TreeSet", 28 | search_mode="unordered", 29 | ): 30 | items: List[ProfileRuleXml] = element(tag="item") 31 | -------------------------------------------------------------------------------- /tests/rest_api/model/api_profiles/profile_variables.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class ProfileVariables(BaseModel): 5 | name: str 6 | object: str 7 | defaultValue: str 8 | value: str 9 | -------------------------------------------------------------------------------- /tests/rest_api/model/api_profiles/profiles_flavours.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from pydantic_xml import BaseXmlModel, element 4 | 5 | 6 | class ProfileFlavoursXMl(BaseXmlModel, tag="UnmodifiableSet"): 7 | item: List[str] = element(tag="item") 8 | -------------------------------------------------------------------------------- /tests/rest_api/model/api_profiles/rule_id.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from pydantic import BaseModel 4 | from pydantic_xml import BaseXmlModel, element 5 | 6 | 7 | class RuleID(BaseModel): 8 | clause: str 9 | specification: str 10 | testNumber: int 11 | 12 | 13 | class RuleIDXml( 14 | BaseXmlModel, 15 | ): 16 | specification: str = element(tag="specification") 17 | clause: str = element(tag="clause") 18 | testNumber: int = element(tag="testNumber") 19 | 20 | 21 | class RulesXml( 22 | BaseXmlModel, 23 | tag="TreeSet", 24 | search_mode="unordered", 25 | ): 26 | items: List[RuleIDXml] = element(tag="item") 27 | -------------------------------------------------------------------------------- /tests/rest_api/model/api_sha1/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/rest_api/model/api_sha1/__init__.py -------------------------------------------------------------------------------- /tests/rest_api/model/api_sha1/sha1.py: -------------------------------------------------------------------------------- 1 | from pydantic_xml import BaseXmlModel, element 2 | 3 | 4 | class Sha1XMl(BaseXmlModel, tag="ByteStreamIdImpl"): 5 | hexSHA1: str = element(tag="hexSHA1") 6 | length: int = element(tag="length") 7 | -------------------------------------------------------------------------------- /tests/rest_api/model/api_validate_details/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/rest_api/model/api_validate_details/__init__.py -------------------------------------------------------------------------------- /tests/rest_api/model/api_validate_details/api_validate_details.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class ApiValidateDetails(BaseModel): 5 | id: str 6 | name: str 7 | version: str 8 | provider: str 9 | description: str 10 | -------------------------------------------------------------------------------- /tests/rest_api/model/api_validate_details/job.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | from tests.rest_api.model.api_validate_details.log import Logs 4 | 5 | 6 | class Job(BaseModel): 7 | logs: Logs 8 | -------------------------------------------------------------------------------- /tests/rest_api/model/api_validate_details/log.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from pydantic import BaseModel 4 | 5 | 6 | class Log(BaseModel): 7 | occurrences: int 8 | level: str 9 | message: str 10 | 11 | 12 | class Logs(BaseModel): 13 | logsCount: int 14 | logs: List[Log] 15 | -------------------------------------------------------------------------------- /tests/rest_api/model/api_validate_details/report.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from pydantic import BaseModel 4 | 5 | from tests.rest_api.model.api_validate_details.summary import BatchSummary 6 | from tests.rest_api.model.api_validate_details.job import Job 7 | 8 | 9 | class Report(BaseModel): 10 | batchSummary: BatchSummary 11 | jobs: List[Job] 12 | -------------------------------------------------------------------------------- /tests/rest_api/model/api_validate_details/result.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | from tests.rest_api.model.api_validate_details.report import Report 4 | 5 | 6 | class Result(BaseModel): 7 | report: Report 8 | -------------------------------------------------------------------------------- /tests/rest_api/model/api_validate_details/summary.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class ValidationSummary(BaseModel): 5 | totalJobCount: int 6 | 7 | 8 | class BatchSummary(BaseModel): 9 | totalJobs: int 10 | multiJob: bool 11 | validationSummary: ValidationSummary 12 | -------------------------------------------------------------------------------- /tests/rest_api/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/rest_api/tests/__init__.py -------------------------------------------------------------------------------- /tests/rest_api/tests/api_info/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/rest_api/tests/api_info/__init__.py -------------------------------------------------------------------------------- /tests/rest_api/tests/api_info/test_api.py: -------------------------------------------------------------------------------- 1 | import re 2 | import requests 3 | from tests.rest_api.model.api_info.api_endpoint import ApiEndpoint, ApiEndpointXml 4 | 5 | 6 | VERAPDF_REST_ID = "verapdf-rest" 7 | buildDate_regex = re.compile(r"^[0-9]+$") 8 | version_regex = re.compile(r"^[0-9]\.[0-9][0-9]\.[0-9]") 9 | 10 | 11 | def test_api_check(get_base_url): 12 | response = requests.get(get_base_url + "/api") 13 | assert response.status_code == 200 14 | 15 | resp = response.json() 16 | api = ApiEndpoint(**resp) 17 | 18 | assert api.id == VERAPDF_REST_ID 19 | assert version_regex.match(api.version) 20 | assert buildDate_regex.match(str(api.buildDate)) 21 | 22 | 23 | def test_api_xml_check(get_base_url): 24 | url = get_base_url + "/api" 25 | headers = {"Accept": "application/xml"} 26 | 27 | response = requests.get(url=url, headers=headers) 28 | api = ApiEndpointXml.from_xml(response.text) 29 | 30 | assert api.id == VERAPDF_REST_ID 31 | assert version_regex.match(api.version) 32 | assert buildDate_regex.match(str(api.buildDate)) 33 | -------------------------------------------------------------------------------- /tests/rest_api/tests/api_info/test_api_info.py: -------------------------------------------------------------------------------- 1 | import re 2 | import requests 3 | from tests.rest_api.model.api_info.environment import Environment 4 | from tests.rest_api.model.api_info.environment import EnvironmentXml 5 | 6 | 7 | os_name = re.compile(r".+") 8 | server_machAddress = re.compile(r"..-..-..-..-..-..") 9 | 10 | 11 | def test_api_info_check(get_base_url): 12 | response = requests.get(get_base_url + "/api/info") 13 | assert response.status_code == 200 14 | resp = response.json() 15 | 16 | api_info = Environment(**resp) 17 | 18 | assert api_info.java.architecture == "x64" 19 | assert os_name.match(api_info.os.name) 20 | assert server_machAddress.match(api_info.server.machAddress) 21 | 22 | 23 | def test_api_info_xml_check(get_base_url): 24 | url = get_base_url + "/api/info" 25 | headers = {"Accept": "application/xml"} 26 | 27 | response = requests.get(url=url, headers=headers) 28 | assert response.status_code == 200 29 | 30 | api_info = EnvironmentXml.from_xml(response.text) 31 | 32 | api_info.java.architecture == "x64" 33 | assert os_name.match(api_info.os.name) 34 | assert server_machAddress.match(api_info.server.machAddress) 35 | -------------------------------------------------------------------------------- /tests/rest_api/tests/api_profiles/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/rest_api/tests/api_profiles/__init__.py -------------------------------------------------------------------------------- /tests/rest_api/tests/api_profiles/test_api_profiles.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | import requests 4 | 5 | from tests.rest_api.model.api_profiles.profile import Profile, ProfilesXMl 6 | from tests.rest_api.tests.base_test import BaseClass 7 | 8 | profiles_item_list = [] 9 | profiles_item_xml_list = [] 10 | dateCreated_regex = re.compile(r"^[0-9]+$") 11 | description = re.compile(r".+") 12 | 13 | 14 | def test_profiles_list_check(get_base_url): 15 | response = requests.get(get_base_url + "/api/profiles") 16 | assert response.status_code == 200 17 | 18 | profile_list = response.json() 19 | 20 | for prof_item in profile_list: 21 | profile_info = Profile(**prof_item) 22 | profiles_item_list.append(profile_info.name) 23 | assert profile_info.creator == BaseClass.CREATOR 24 | assert description.match(profile_info.description) 25 | assert dateCreated_regex.match(str(profile_info.dateCreated)) 26 | profiles_item_list.sort() 27 | assert profiles_item_list == BaseClass.PROFILE_NAMES 28 | 29 | 30 | def test_profiles_list_check_xml(get_base_url): 31 | url = get_base_url + "/api/profiles" 32 | headers = {"Accept": "application/xml"} 33 | 34 | response = requests.get(url, headers=headers) 35 | assert response.status_code == 200 36 | 37 | profiles_list_xml = response.text 38 | 39 | profile_list = ProfilesXMl.from_xml(profiles_list_xml) 40 | 41 | for item in profile_list.items: 42 | profiles_item_xml_list.append(item.name) 43 | assert item.creator == BaseClass.CREATOR 44 | assert description.match(item.description) 45 | assert dateCreated_regex.match(str(item.dateCreated)) 46 | profiles_item_xml_list.sort() 47 | assert profiles_item_xml_list == BaseClass.PROFILE_NAMES 48 | -------------------------------------------------------------------------------- /tests/rest_api/tests/api_profiles/test_api_profiles_clause.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import requests 3 | 4 | from tests.rest_api.tests.base_test import BaseClass 5 | from tests.rest_api.model.api_profiles.profile_rule import ( 6 | ProfileRule, 7 | ProfileRuleSXml, 8 | ) 9 | 10 | 11 | @pytest.mark.parametrize( 12 | "profile_id, expected_clause, expected_clause_items", 13 | BaseClass.PROFILE_CLAUSE, 14 | ) 15 | def test_profile_id_clause_check( 16 | profile_id, expected_clause, expected_clause_items, get_base_url 17 | ): 18 | response = requests.get( 19 | get_base_url + "/api/profiles/" + profile_id + "/" + expected_clause 20 | ) 21 | assert response.status_code == 200 22 | 23 | clause_list = response.json() 24 | item_list = [] 25 | 26 | for item in clause_list: 27 | item_list.append(ProfileRule(**item)) 28 | 29 | assert len(item_list) == expected_clause_items 30 | 31 | for item in item_list: 32 | assert item.ruleId.clause == expected_clause 33 | 34 | 35 | @pytest.mark.parametrize( 36 | "profile_id, expected_clause, expected_clause_items", 37 | BaseClass.PROFILE_CLAUSE, 38 | ) 39 | def test_profile_id_clause_xml_check( 40 | profile_id, expected_clause, expected_clause_items, get_base_url 41 | ): 42 | url = get_base_url + "/api/profiles/" + profile_id + "/" + expected_clause 43 | headers = {"Accept": "application/xml"} 44 | 45 | response = requests.get(url=url, headers=headers) 46 | assert response.status_code == 200 47 | 48 | clause_list_xml = response.text 49 | clause_list = ProfileRuleSXml.from_xml(clause_list_xml) 50 | 51 | assert len(clause_list.items) == expected_clause_items 52 | 53 | for item in clause_list.items: 54 | assert item.ruleId.clause == expected_clause 55 | -------------------------------------------------------------------------------- /tests/rest_api/tests/api_profiles/test_api_profiles_flavours.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | from tests.rest_api.model.api_profiles.profiles_flavours import ProfileFlavoursXMl 4 | from tests.rest_api.tests.base_test import BaseClass 5 | 6 | 7 | def test_profile_flavours_check(get_base_url): 8 | response = requests.get(get_base_url + "/api/profiles/flavours") 9 | assert response.status_code == 200 10 | 11 | flavours_list = response.json() 12 | assert sorted(flavours_list) == BaseClass.FLAVOURS_LIST 13 | 14 | 15 | def test_profile_flavours_xml_check(get_base_url): 16 | url = get_base_url + "/api/profiles/flavours" 17 | headers = {"Accept": "application/xml"} 18 | 19 | response = requests.get(url=url, headers=headers) 20 | assert response.status_code == 200 21 | 22 | flavours_xml = response.text 23 | flavours_list = ProfileFlavoursXMl.from_xml(flavours_xml) 24 | assert sorted(flavours_list.item) == BaseClass.FLAVOURS_LIST 25 | -------------------------------------------------------------------------------- /tests/rest_api/tests/api_profiles/test_api_profiles_id.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import requests 3 | 4 | from tests.rest_api.model.api_profiles.profile_id import ProfileID, ProfileIDXml 5 | from tests.rest_api.tests.base_test import BaseClass 6 | 7 | 8 | @pytest.mark.parametrize( 9 | "profile_id, expected_pdfaflavour, expected_name", 10 | BaseClass.PROFILE_LIST, 11 | ) 12 | def test_profile_id_check( 13 | profile_id, expected_pdfaflavour, expected_name, get_base_url 14 | ): 15 | response = requests.get(get_base_url + "/api/profiles/" + profile_id) 16 | assert response.status_code == 200 17 | 18 | profile_id = response.json() 19 | profile_id_info = ProfileID(**profile_id) 20 | 21 | assert profile_id_info.details.name == expected_name 22 | assert profile_id_info.details.creator == BaseClass.CREATOR 23 | assert profile_id_info.pdfaflavour == expected_pdfaflavour 24 | 25 | 26 | @pytest.mark.parametrize( 27 | "profile_id, expected_pdfaflavour, expected_name", 28 | BaseClass.PROFILE_LIST, 29 | ) 30 | def test_profile_id_xml_check( 31 | profile_id, expected_pdfaflavour, expected_name, get_base_url 32 | ): 33 | url = get_base_url + "/api/profiles/" + profile_id 34 | headers = {"Accept": "application/xml"} 35 | 36 | response = requests.get(url, headers=headers) 37 | assert response.status_code == 200 38 | 39 | profile_id_xml = response.text 40 | profile_id = ProfileIDXml.from_xml(profile_id_xml) 41 | 42 | assert profile_id.pdfaflavour == expected_pdfaflavour 43 | assert profile_id.details.creator == BaseClass.CREATOR 44 | -------------------------------------------------------------------------------- /tests/rest_api/tests/api_profiles/test_api_profiles_ids.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | from tests.rest_api.model.api_profiles.profile_ids import ProfileIdsXMl 4 | from tests.rest_api.tests.base_test import BaseClass 5 | 6 | 7 | def test_profile_ids_check(get_base_url): 8 | response = requests.get(get_base_url + "/api/profiles/ids") 9 | assert response.status_code == 200 10 | 11 | profile_ids = response.json() 12 | 13 | assert sorted(profile_ids) == BaseClass.PROFILE_IDS 14 | 15 | 16 | def test_profile_ids_xml_check(get_base_url): 17 | url = get_base_url + "/api/profiles/ids" 18 | headers = {"Accept": "application/xml"} 19 | 20 | response = requests.get(url, headers=headers) 21 | assert response.status_code == 200 22 | 23 | profile_ids_xml = response.text 24 | profile_ids_list = ProfileIdsXMl.from_xml(profile_ids_xml) 25 | 26 | assert sorted(profile_ids_list.item) == BaseClass.PROFILE_IDS 27 | -------------------------------------------------------------------------------- /tests/rest_api/tests/api_profiles/test_api_profiles_ruleids.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import requests 3 | 4 | from tests.rest_api.model.api_profiles.rule_id import RuleID, RulesXml 5 | from tests.rest_api.tests.base_test import BaseClass 6 | 7 | 8 | @pytest.mark.parametrize( 9 | "profile_id, expected_rules_count", 10 | BaseClass.PROFILE_RULES, 11 | ) 12 | def test_ruleids_check(profile_id, expected_rules_count, get_base_url): 13 | response = requests.get(get_base_url + "/api/profiles/" + profile_id + "/ruleids") 14 | assert response.status_code == 200 15 | item_list = [] 16 | 17 | rules = response.json() 18 | 19 | for item in rules: 20 | item_list.append(RuleID(**item)) 21 | 22 | assert len(item_list) == expected_rules_count 23 | 24 | 25 | @pytest.mark.parametrize( 26 | "profile_id, expected_rules_count", 27 | BaseClass.PROFILE_RULES, 28 | ) 29 | def test_ruleids_xml_check(profile_id, expected_rules_count, get_base_url): 30 | url = get_base_url + "/api/profiles/" + profile_id + "/ruleids" 31 | headers = {"Accept": "application/xml"} 32 | 33 | response = requests.get(url, headers=headers) 34 | assert response.status_code == 200 35 | 36 | rules_xml = response.text 37 | 38 | rules_info = RulesXml.from_xml(rules_xml) 39 | assert len(rules_info.items) == expected_rules_count 40 | -------------------------------------------------------------------------------- /tests/rest_api/tests/api_sha1/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/rest_api/tests/api_sha1/__init__.py -------------------------------------------------------------------------------- /tests/rest_api/tests/api_sha1/api_sha1.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | from tests.rest_api.model.api_sha1.sha1 import Sha1XMl 4 | 5 | 6 | def test_sha1_check(get_base_url): 7 | headers = { 8 | "accept": "application/json", 9 | # requests won't add a boundary if this header is set when you pass files= 10 | # 'Content-Type': 'multipart/form-data', 11 | } 12 | files = { 13 | "file": ( 14 | "a.pdf", 15 | open("..//../../../tests/Resources/a.pdf", "rb"), 16 | "application/pdf", 17 | ), 18 | } 19 | 20 | response = requests.post( 21 | "https://demo.verapdf.org/api/sha1", headers=headers, files=files 22 | ) 23 | 24 | sha1_info = response.json() 25 | 26 | assert sha1_info["hexSHA1"] == "bb0a429d5449548a50de3d5bd2636d4f918272c4" 27 | assert sha1_info["length"] == 3175 28 | 29 | 30 | def test_sha1_xml_check(get_base_url): 31 | headers = { 32 | "accept": "application/xml", 33 | # requests won't add a boundary if this header is set when you pass files= 34 | # 'Content-Type': 'multipart/form-data', 35 | } 36 | files = { 37 | "file": ( 38 | "a.pdf", 39 | open("..//../../../tests/Resources/a.pdf", "rb"), 40 | "application/pdf", 41 | ), 42 | } 43 | 44 | response = requests.post( 45 | "https://demo.verapdf.org/api/sha1", headers=headers, files=files 46 | ) 47 | 48 | sha1_info_xml = response.text 49 | 50 | sha1_info = Sha1XMl.from_xml(sha1_info_xml) 51 | 52 | assert sha1_info.hexSHA1 == "bb0a429d5449548a50de3d5bd2636d4f918272c4" 53 | assert sha1_info.length == 3175 54 | -------------------------------------------------------------------------------- /tests/rest_api/tests/api_sha1/test_api_sha1_null.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | from tests.rest_api.model.api_sha1.sha1 import Sha1XMl 4 | 5 | 6 | def test_sha1_null_check(get_base_url): 7 | response = requests.get(get_base_url + "/api/sha1/null") 8 | assert response.status_code == 200 9 | 10 | profile_ids = response.json() 11 | 12 | assert profile_ids["hexSHA1"] == "da39a3ee5e6b4b0d3255bfef95601890afd80709" 13 | assert profile_ids["length"] == 0 14 | 15 | 16 | def test_sha1_null_xml_check(get_base_url): 17 | url = get_base_url + "/api/sha1/null" 18 | headers = {"Accept": "application/xml"} 19 | 20 | response = requests.get(url, headers=headers) 21 | assert response.status_code == 200 22 | 23 | sha1_null_xml = response.text 24 | 25 | sha1_null = Sha1XMl.from_xml(sha1_null_xml) 26 | 27 | assert sha1_null.hexSHA1 == "da39a3ee5e6b4b0d3255bfef95601890afd80709" 28 | assert sha1_null.length == 0 29 | -------------------------------------------------------------------------------- /tests/rest_api/tests/api_validate/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraPDF/veraPDF-rest/b514aa0585fee0e2a82f3e086f79f71b61677f96/tests/rest_api/tests/api_validate/__init__.py -------------------------------------------------------------------------------- /tests/rest_api/tests/api_validate/test_api_validate_details.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | import requests 4 | 5 | from tests.rest_api.model.api_validate_details.api_validate_details import ( 6 | ApiValidateDetails, 7 | ) 8 | 9 | details_version = re.compile(r"\d.\d\d.\d+") 10 | 11 | 12 | def test_api_validate_details_check(get_base_url): 13 | response = requests.get(get_base_url + "/api/validate/details") 14 | assert response.status_code == 200 15 | 16 | details = ApiValidateDetails(**(response.json())) 17 | 18 | assert details.id == "http://pdfa.verapdf.org/foundry#verapdf" 19 | assert details.name == "VeraPDF Foundry" 20 | assert details_version.match(details.version) 21 | assert details.provider == "The veraPDF Consortium." 22 | assert details.description == "veraPDF greenfield foundry instance." 23 | -------------------------------------------------------------------------------- /tests/rest_api/tests/api_validate/test_api_validate_profileId.py: -------------------------------------------------------------------------------- 1 | from io import StringIO 2 | 3 | import pytest 4 | import requests 5 | import xmltodict 6 | from lxml import etree 7 | 8 | from tests.rest_api.tests.base_test import BaseClass 9 | 10 | 11 | @pytest.mark.parametrize( 12 | "profile_id, expected_profile_name", 13 | BaseClass.VALIDATION_LIST, 14 | ) 15 | def test_api_validate_details_check(profile_id, expected_profile_name, get_base_url): 16 | url = get_base_url + "/api/validate/" + profile_id 17 | headers = { 18 | "accept": "application/json", 19 | # requests won't add a boundary if this header is set when you pass files= 20 | # 'Content-Type': 'multipart/form-data', 21 | } 22 | 23 | files = { 24 | "file": ("a.pdf", open(BaseClass.FILE_TO_PARSE, "rb"), "application/pdf"), 25 | } 26 | 27 | response = requests.post(url, headers=headers, files=files) 28 | 29 | details = response.json() 30 | 31 | assert "a.pdf" in (details["report"]["jobs"][0]["itemDetails"]["name"]) 32 | assert ( 33 | details["report"]["jobs"][0]["validationResult"][0]["profileName"] 34 | == expected_profile_name 35 | ) 36 | 37 | 38 | @pytest.mark.parametrize( 39 | "profile_id, expected_profile_name", 40 | BaseClass.VALIDATION_LIST, 41 | ) 42 | def test_api_validate_details_xml_check( 43 | profile_id, expected_profile_name, get_base_url 44 | ): 45 | url = get_base_url + "/api/validate/" + profile_id 46 | headers = { 47 | "accept": "application/xml", 48 | # requests won't add a boundary if this header is set when you pass files= 49 | # 'Content-Type': 'multipart/form-data', 50 | } 51 | 52 | files = { 53 | "file": ("a.pdf", open(BaseClass.FILE_TO_PARSE, "rb"), "application/pdf"), 54 | } 55 | 56 | response = requests.post(url, headers=headers, files=files) 57 | 58 | details = xmltodict.parse(response.text) 59 | 60 | assert ( 61 | details["report"]["jobs"]["job"]["validationReport"]["@profileName"] 62 | == expected_profile_name 63 | ) 64 | 65 | 66 | @pytest.mark.parametrize( 67 | "profile_id, expected_profile_name", 68 | BaseClass.VALIDATION_LIST, 69 | ) 70 | def test_api_validate_details_html_check( 71 | profile_id, expected_profile_name, get_base_url 72 | ): 73 | url = get_base_url + "/api/validate/" + profile_id 74 | headers = { 75 | "accept": "text/html", 76 | # requests won't add a boundary if this header is set when you pass files= 77 | # 'Content-Type': 'multipart/form-data', 78 | } 79 | 80 | files = { 81 | "file": ("a.pdf", open(BaseClass.FILE_TO_PARSE, "rb"), "application/pdf"), 82 | } 83 | parser = etree.HTMLParser() 84 | 85 | page = requests.post(url, headers=headers, files=files) 86 | 87 | html = page.content.decode("utf-8") 88 | tree = etree.parse(StringIO(html), parser=parser) 89 | file = tree.xpath('//*[@id="table1"]//tr[1]//td[2]/text()')[0] 90 | profile = tree.xpath('//*[@id="table1"]//tr[2]//td[2]/a[1]/text()')[0] 91 | 92 | assert file == "a.pdf" 93 | assert profile == expected_profile_name 94 | -------------------------------------------------------------------------------- /tests/rest_api/tests/api_validate/test_api_validate_sha_profileId.py: -------------------------------------------------------------------------------- 1 | from io import StringIO 2 | 3 | import pytest 4 | import requests 5 | import xmltodict 6 | from lxml import etree 7 | 8 | from tests.rest_api.tests.base_test import BaseClass 9 | 10 | 11 | @pytest.mark.parametrize( 12 | "profile_id, expected_profile_name", 13 | BaseClass.VALIDATION_LIST, 14 | ) 15 | def test_api_validate_sha_profileid_check( 16 | profile_id, expected_profile_name, get_base_url 17 | ): 18 | headers = { 19 | "accept": "application/json", 20 | # requests won't add a boundary if this header is set when you pass files= 21 | # 'Content-Type': 'multipart/form-data', 22 | } 23 | 24 | files = { 25 | "sha1Hex": (None, "bb0a429d5449548a50de3d5bd2636d4f918272c4"), 26 | "file": ("a.pdf", open(BaseClass.FILE_TO_PARSE, "rb"), "application/pdf"), 27 | } 28 | 29 | response = requests.post( 30 | get_base_url + "/api/validate/" + profile_id, headers=headers, files=files 31 | ) 32 | 33 | assert response.status_code == 200 34 | 35 | sha1_info = response.json() 36 | 37 | assert sha1_info["report"]["jobs"][0]["itemDetails"]["name"] == "a.pdf" 38 | assert ( 39 | sha1_info["report"]["jobs"][0]["validationResult"][0]["profileName"] 40 | == expected_profile_name 41 | ) 42 | 43 | 44 | @pytest.mark.parametrize( 45 | "profile_id, expected_profile_name", 46 | BaseClass.VALIDATION_LIST, 47 | ) 48 | def test_api_validate_sha_profileid_xml_check( 49 | profile_id, expected_profile_name, get_base_url 50 | ): 51 | headers = { 52 | "accept": "application/xml", 53 | # requests won't add a boundary if this header is set when you pass files= 54 | # 'Content-Type': 'multipart/form-data', 55 | } 56 | 57 | files = { 58 | "sha1Hex": (None, "bb0a429d5449548a50de3d5bd2636d4f918272c4"), 59 | "file": ("a.pdf", open(BaseClass.FILE_TO_PARSE, "rb"), "application/pdf"), 60 | } 61 | 62 | response = requests.post( 63 | get_base_url + "/api/validate/" + profile_id, headers=headers, files=files 64 | ) 65 | 66 | assert response.status_code == 200 67 | 68 | details = xmltodict.parse(response.text) 69 | 70 | assert details["report"]["jobs"]["job"]["item"]["name"] == "a.pdf" 71 | assert ( 72 | details["report"]["jobs"]["job"]["validationReport"]["@profileName"] 73 | == expected_profile_name 74 | ) 75 | 76 | 77 | @pytest.mark.parametrize( 78 | "profile_id, expected_profile_name", 79 | BaseClass.VALIDATION_LIST, 80 | ) 81 | def test_api_validate_sha_profileid_html_check( 82 | profile_id, expected_profile_name, get_base_url 83 | ): 84 | url = get_base_url + "/api/validate/" + profile_id 85 | headers = { 86 | "accept": "text/html", 87 | # requests won't add a boundary if this header is set when you pass files= 88 | # 'Content-Type': 'multipart/form-data', 89 | } 90 | 91 | files = { 92 | "sha1Hex": (None, "bb0a429d5449548a50de3d5bd2636d4f918272c4"), 93 | "file": ("a.pdf", open(BaseClass.FILE_TO_PARSE, "rb"), "application/pdf"), 94 | } 95 | 96 | parser = etree.HTMLParser() 97 | 98 | page = requests.post(url, headers=headers, files=files) 99 | 100 | assert page.status_code == 200 101 | 102 | html = page.content.decode("utf-8") 103 | tree = etree.parse(StringIO(html), parser=parser) 104 | 105 | file = tree.xpath('//*[@id="table1"]//tr[1]//td[2]/text()')[0] 106 | profile = tree.xpath('//*[@id="table1"]//tr[2]//td[2]/a[1]/text()')[0] 107 | 108 | assert file == "a.pdf" 109 | assert profile == expected_profile_name 110 | -------------------------------------------------------------------------------- /tests/rest_api/tests/api_validate/test_validate_pdf_by_url.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import requests 3 | 4 | from tests.rest_api.model.api_validate_details.result import Report, Result 5 | from tests.rest_api.tests.base_test import BaseClass 6 | 7 | 8 | @pytest.mark.parametrize( 9 | "file_url, expected_code, json_key, expected_message", 10 | [ 11 | ("", 400, "message", "URL is empty"), 12 | ( 13 | "https://abc.qwerty.com", 14 | 400, 15 | "message", 16 | "URL is incorrect: https://abc.qwerty.com", 17 | ), 18 | ], 19 | ) 20 | @pytest.mark.parametrize( 21 | "profile_id", 22 | BaseClass.PROFILE_IDS, 23 | ) 24 | def test_validate_pdf_with_fail_url( 25 | file_url, expected_code, json_key, expected_message, profile_id, get_base_url 26 | ): 27 | url = get_base_url + "/api/validate/url/" + profile_id 28 | 29 | headers = { 30 | "accept": "application/json", 31 | # requests won't add a boundary if this header is set when you pass files= 32 | # 'Content-Type': 'multipart/form-data', 33 | } 34 | 35 | files = { 36 | "url": (None, file_url), 37 | } 38 | 39 | response = requests.post(url=url, headers=headers, files=files) 40 | 41 | assert response.status_code == expected_code 42 | assert expected_message == response.json()[json_key] 43 | 44 | 45 | @pytest.mark.parametrize( 46 | "file_url, expected_code", 47 | [ 48 | ( 49 | "https://github.com/veraPDF/veraPDF-regression-tests/blob/integration/CLI/Resources/a.pdf", 50 | 200, 51 | ), 52 | ], 53 | ) 54 | @pytest.mark.parametrize( 55 | "profile_id", 56 | BaseClass.PROFILE_IDS, 57 | ) 58 | def test_validate_pdf_with_pass_url(file_url, expected_code, profile_id, get_base_url): 59 | url = get_base_url + "/api/validate/url/" + profile_id 60 | 61 | headers = { 62 | "accept": "application/json", 63 | # requests won't add a boundary if this header is set when you pass files= 64 | # 'Content-Type': 'multipart/form-data', 65 | } 66 | 67 | files = { 68 | "url": (None, file_url), 69 | } 70 | 71 | response = requests.post(url=url, headers=headers, files=files) 72 | 73 | result = Result(**response.json()) 74 | assert result.report.batchSummary.totalJobs == 1 75 | assert result.report.jobs[0].logs.logs[0].level == "WARNING" 76 | assert result.report.jobs[0].logs.logs[0].occurrences == 1 77 | assert "a.pdf" in result.report.jobs[0].logs.logs[0].message 78 | -------------------------------------------------------------------------------- /tests/rest_api/tests/base_test.py: -------------------------------------------------------------------------------- 1 | """ Possible urls: 2 | https://demo.verapdf.org/swagger 3 | https://dev.verapdf-rest.duallab.com/swagger 4 | http://localhost:8080/api 5 | """ 6 | import itertools 7 | 8 | 9 | class BaseClass: 10 | CREATOR = "veraPDF Consortium" 11 | FILE_TO_PARSE = "./tests/Resources/a.pdf" 12 | PROFILE_GENERAL = ( 13 | # 1b, 1a, 2b, 2a, 2u, 3b, 3a, 3u, 4, 4e, 4f, ua1, ua2, wt1a or wt1r 14 | # profile id, pdfa flavour, profile name, profile rule count, clause & clause items 15 | ("1b", "PDFA_1_B", "PDF/A-1B validation profile", 129, ("6.7.3", 8)), 16 | ("1a", "PDFA_1_A", "PDF/A-1A validation profile", 135, ("6.1.7", 3)), 17 | ("2b", "PDFA_2_B", "PDF/A-2B validation profile", 144, ("6.2.11.3.1", 1)), 18 | ("2a", "PDFA_2_A", "PDF/A-2A validation profile", 153, ("6.7.3.4", 3)), 19 | ("2u", "PDFA_2_U", "PDF/A-2U validation profile", 146, ("6.2.11.3.1", 1)), 20 | ("3a", "PDFA_3_A", "PDF/A-3A validation profile", 155, ("6.2.11.3.2", 1)), 21 | ("3b", "PDFA_3_B", "PDF/A-3B validation profile", 146, ("6.2.11.3.2", 1)), 22 | ("3u", "PDFA_3_U", "PDF/A-3U validation profile", 148, ("6.3.1", 1)), 23 | ("4", "PDFA_4", "PDF/A-4 validation profile", 109, ("6.6.1", 2)), 24 | ("4e", "PDFA_4_E", "PDF/A-4E validation profile", 109, ("6.1.6.2", 1)), 25 | ("4f", "PDFA_4_F", "PDF/A-4F validation profile", 109, ("6.2.4.2", 3)), 26 | ("ua1", "PDFUA_1", "PDF/UA-1 validation profile", 106, ("7.18.8", 1)), 27 | ("ua2", "PDFUA_2", "PDF/UA-2 + Tagged PDF validation profile", 1723, ("5", 5)), 28 | ("wt1a", "WTPDF_1_0_ACCESSIBILITY", "WTPDF 1.0 Accessibility validation profile", 1719, ("8.4.3", 3)), 29 | ("wt1r", "WTPDF_1_0_REUSE", "WTPDF 1.0 Reuse validation profile", 1706, ("8.4.5.4", 3)), 30 | ) 31 | 32 | FLAVOURS_LIST = sorted( 33 | [ 34 | item[0] 35 | for item in [ 36 | list(itertools.compress(item, [0, 1, 0, 0, 0])) 37 | for item in PROFILE_GENERAL 38 | ] 39 | ] 40 | ) 41 | VALIDATION_LIST = [ 42 | list(itertools.compress(item, [1, 0, 1, 0, 0])) for item in PROFILE_GENERAL 43 | ] 44 | 45 | PROFILE_LIST = [ 46 | list(itertools.compress(item, [1, 1, 1, 0, 0])) for item in PROFILE_GENERAL 47 | ] 48 | PROFILE_IDS = sorted( 49 | [ 50 | item[0] 51 | for item in [ 52 | list(itertools.compress(item, [1, 0, 0, 0, 0])) 53 | for item in PROFILE_GENERAL 54 | ] 55 | ] 56 | ) 57 | PROFILE_NAMES = sorted( 58 | [ 59 | item[0] 60 | for item in [ 61 | list(itertools.compress(item, [0, 0, 1, 0, 0])) 62 | for item in PROFILE_GENERAL 63 | ] 64 | ] 65 | ) 66 | PROFILE_RULES = [ 67 | list(itertools.compress(item, [1, 0, 0, 1, 0])) for item in PROFILE_GENERAL 68 | ] 69 | 70 | PROFILE_CLAUSE = [] 71 | for i in list( 72 | ([list(itertools.compress(item, [1, 0, 0, 0, 1])) for item in PROFILE_GENERAL]) 73 | ): 74 | x, (y, z) = i 75 | PROFILE_CLAUSE.append([x, y, z]) 76 | -------------------------------------------------------------------------------- /tests/tools/test_helper/common-setup.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | _common_setup() { 4 | PROJECT_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../.." >/dev/null 2>&1 && pwd)" 5 | PATH="$PROJECT_ROOT/tools/test_helper/:$PATH" 6 | 7 | load "$PROJECT_ROOT/bats-support/load.bash" 8 | load "$PROJECT_ROOT/bats-assert/load.bash" 9 | 10 | export DOCKER_CONTAINER=$(echo $(docker ps | grep "rest:" | awk '{print $1}')) 11 | echo -e "\nDOCKER_CONTAINER_ID: $DOCKER_CONTAINER \n" >&3 12 | 13 | echo "Checking docker container logs...at:" >&3 14 | sleep 1 # sleep sec 15 | 16 | export test_logs_starting_time=$(date +%s) 17 | echo $(date -d @"$test_logs_starting_time") >&3 18 | } 19 | 20 | remove_verapdf_config_files() { 21 | echo -e "Removing files ... " >&3 22 | echo -e $(docker exec -i --user=root "$DOCKER_CONTAINER" ls -la /opt/verapdf-rest/config/) >&3 23 | 24 | docker exec --user=root "$DOCKER_CONTAINER" rm -rf /opt/verapdf-rest/config/features.xml 25 | docker exec --user=root "$DOCKER_CONTAINER" rm -rf /opt/verapdf-rest/config/fixer.xml 26 | docker exec --user=root "$DOCKER_CONTAINER" rm -rf /opt/verapdf-rest/config/plugins.xml 27 | docker exec --user=root "$DOCKER_CONTAINER" rm -rf /opt/verapdf-rest/config/validator.xml 28 | docker exec --user=root "$DOCKER_CONTAINER" rm -rf /opt/verapdf-rest/config/app.xml 29 | 30 | echo -e "Removing files ... Done\n" >&3 31 | 32 | echo -e "Files in the container ... " >&3 33 | echo -e $(docker exec -i --user=root "$DOCKER_CONTAINER" ls -la /opt/verapdf-rest/config/) >&3 34 | echo -e "\n" >&3 35 | } 36 | 37 | prepare_fresh_verapdf_config_files() { 38 | 39 | remove_verapdf_config_files 40 | 41 | echo -e "Coping new files ... to the container" >&3 42 | echo "file list" $(ls "$PROJECT_ROOT"/../config) >&3 43 | 44 | docker cp "$PROJECT_ROOT"/../config/features.xml "$DOCKER_CONTAINER":/opt/verapdf-rest/config/features.xml 45 | docker cp "$PROJECT_ROOT"/../config/fixer.xml "$DOCKER_CONTAINER":/opt/verapdf-rest/config/fixer.xml 46 | docker cp "$PROJECT_ROOT"/../config/plugins.xml "$DOCKER_CONTAINER":/opt/verapdf-rest/config/plugins.xml 47 | docker cp "$PROJECT_ROOT"/../config/validator.xml "$DOCKER_CONTAINER":/opt/verapdf-rest/config/validator.xml 48 | docker cp "$PROJECT_ROOT"/../config/app.xml "$DOCKER_CONTAINER":/opt/verapdf-rest/config/app.xml 49 | 50 | echo -e "Files in the container ... " >&3 51 | echo -e $(docker exec -i --user=root "$DOCKER_CONTAINER" ls -la /opt/verapdf-rest/config/) >&3 52 | echo -e "\n" >&3 53 | } 54 | --------------------------------------------------------------------------------