From e491552cfe189aec99c94388e16ff7c80e2d615d Mon Sep 17 00:00:00 2001 From: Gonzalo Diaz Date: Mon, 9 Sep 2024 16:18:13 -0300 Subject: [PATCH] Project initialization --- .dockerignore | 2 + .editorconfig | 43 +++++ .github/ISSUE_TEMPLATE/bug_report.md | 43 +++++ .github/dependabot.yml | 19 ++ .github/workflows/cpp-coverage.yml | 58 ++++++ .github/workflows/cpp.yml | 52 ++++++ .github/workflows/cppcheck.yml | 29 +++ .github/workflows/docker-image.yml | 223 ++++++++++++++++++++++ .github/workflows/gitleaks.yml | 32 ++++ .github/workflows/markdown-lint.yml | 33 ++++ .github/workflows/sonarcloud.yml | 69 +++++++ .github/workflows/yamllint.yml | 26 +++ .gitignore | 10 + .markdownlint.yaml | 264 +++++++++++++++++++++++++++ .yamlignore | 1 + .yamllint | 19 ++ CMakeLists.txt | 27 +++ CMakePresets.json | 15 ++ Dockerfile | 106 +++++++++++ LICENSE.md | 21 +++ Makefile | 130 +++++++++++++ README.md | 147 +++++++++++++++ build/.gitkeep | 0 compose.yaml | 51 ++++++ coverage/.gitkeep | 0 sonar-project.properties | 15 ++ src/lib/foo/CMakeLists.txt | 22 +++ src/lib/foo/include/foo/foo.hpp | 7 + src/lib/foo/src/foo.cpp | 5 + src/tests/CMakeLists.txt | 20 ++ src/tests/unit/lib/foo.cpp | 12 ++ 31 files changed, 1501 insertions(+) create mode 100644 .dockerignore create mode 100644 .editorconfig create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/cpp-coverage.yml create mode 100644 .github/workflows/cpp.yml create mode 100644 .github/workflows/cppcheck.yml create mode 100644 .github/workflows/docker-image.yml create mode 100644 .github/workflows/gitleaks.yml create mode 100644 .github/workflows/markdown-lint.yml create mode 100644 .github/workflows/sonarcloud.yml create mode 100644 .github/workflows/yamllint.yml create mode 100644 .gitignore create mode 100644 .markdownlint.yaml create mode 100644 .yamlignore create mode 100644 .yamllint create mode 100644 CMakeLists.txt create mode 100644 CMakePresets.json create mode 100644 Dockerfile create mode 100644 LICENSE.md create mode 100644 Makefile create mode 100644 README.md create mode 100644 build/.gitkeep create mode 100644 compose.yaml create mode 100644 coverage/.gitkeep create mode 100644 sonar-project.properties create mode 100644 src/lib/foo/CMakeLists.txt create mode 100644 src/lib/foo/include/foo/foo.hpp create mode 100644 src/lib/foo/src/foo.cpp create mode 100644 src/tests/CMakeLists.txt create mode 100644 src/tests/unit/lib/foo.cpp diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..04c6da6 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +.git +build diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..55605ad --- /dev/null +++ b/.editorconfig @@ -0,0 +1,43 @@ +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +trim_trailing_whitespace = true +indent_size = 4 +max_line_length = 80 + +# # Already default setting +# [*.sh] +# indent_size = 4 + +# # Already default setting +# Same as in .clang-format +# [{*.cpp, *.hpp, *.S}] +# indent_size = 4 + +# # Already default setting +# [{*.ld, *.lds}] +# indent_size = 4 + +[*.nix] +indent_size = 2 + +[*.toml] +indent_size = 2 + +[*.yml] +indent_size = 2 + + +[{CMakeLists.txt,*.cmake}] +indent_size = 2 + +[{Makefile,**.mk}] +# Use tabs for indentation (Makefiles require tabs) +indent_style = tab +indent_size = 2 diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..5922571 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,43 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[BUG] ..." +labels: bug +assignees: sir-gon + +--- + +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: + +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + +- OS: [e.g. MacOS, Windows, Linux \] +- Version [e.g. 10] + +**Additional context** +Add any other context about the problem here. Consider environment variables, +IDE (+ version), framework version, runtime version, command and parameters of execution. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..50d3472 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,19 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates +--- + +version: 2 +updates: + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + + # Maintain dependencies for Docker + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/cpp-coverage.yml b/.github/workflows/cpp-coverage.yml new file mode 100644 index 0000000..80e977d --- /dev/null +++ b/.github/workflows/cpp-coverage.yml @@ -0,0 +1,58 @@ +--- + +name: C++ CI Coverage + +on: # yamllint disable-line rule:truthy + push: + branches: ["main"] + pull_request: + # The branches below must be a subset of the branches above + branches: ["main"] + workflow_dispatch: + +jobs: + coverage: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + + - name: Install Tools + run: | + pip install gcovr + + - name: Check Tools + run: | + make --version + cmake --version + vcpkg --version + gcovr --version + + - name: Install dependencies + run: | + vcpkg integrate install + vcpkg install catch2 + + # yamllint disable rule:line-length + - name: Build + run: | + export VCPKG_ROOT=/usr/local/share/vcpkg + cmake --preset debug -B build + cmake --preset debug \ + -DCMAKE_TOOLCHAIN_FILE=/usr/local/share/vcpkg/scripts/buildsystems/vcpkg.cmake \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=1 \ + build + cmake --build build --verbose + # yamllint enable rule:line-length + + - name: Test / Coverage + run: make coverage + + - name: Upload coverage reports to Codecov with GitHub Action + uses: codecov/codecov-action@v4 + with: + directory: ./coverage + files: coverage.lcov + token: ${{ secrets.CODECOV_TOKEN }} # required + verbose: true # optional (default = false) diff --git a/.github/workflows/cpp.yml b/.github/workflows/cpp.yml new file mode 100644 index 0000000..805a2d4 --- /dev/null +++ b/.github/workflows/cpp.yml @@ -0,0 +1,52 @@ +--- + +name: C++ CI Tests + +on: # yamllint disable-line rule:truthy + push: + branches: ["main"] + pull_request: + # The branches below must be a subset of the branches above + branches: ["main"] + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + os: [ + "windows-latest", + "ubuntu-latest", + "macOS-latest" + ] + + steps: + - name: Checkout repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + + - name: Check Tools + run: | + make --version + cmake --version + vcpkg --version + + - name: Install dependencies + run: | + vcpkg integrate install + vcpkg install catch2 + + # yamllint disable rule:line-length + - name: Build + run: | + export VCPKG_ROOT=/usr/local/share/vcpkg + cmake --preset debug -B build + cmake --preset debug \ + -DCMAKE_TOOLCHAIN_FILE=/usr/local/share/vcpkg/scripts/buildsystems/vcpkg.cmake \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=1 \ + build + cmake --build build --verbose + # yamllint enable rule:line-length + + - name: Test + run: make test diff --git a/.github/workflows/cppcheck.yml b/.github/workflows/cppcheck.yml new file mode 100644 index 0000000..44c53d1 --- /dev/null +++ b/.github/workflows/cppcheck.yml @@ -0,0 +1,29 @@ +--- + +name: CppCheck Lint + +on: # yamllint disable-line rule:truthy + push: + branches: ["main"] + pull_request: + # The branches below must be a subset of the branches above + branches: ["main"] + workflow_dispatch: + +jobs: + lint: + name: CppCheck Lint + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install cppcheck + cppcheck --version + + - name: Lint + run: make test/static diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml new file mode 100644 index 0000000..5391e68 --- /dev/null +++ b/.github/workflows/docker-image.yml @@ -0,0 +1,223 @@ +--- + +name: Docker Image CI + +on: # yamllint disable-line rule:truthy + push: + branches: ["main"] + pull_request: + # The branches below must be a subset of the branches above + branches: ["main"] + workflow_dispatch: + +env: + IMAGE_NAME: algorithm-exercises-cpp + ARTIFACT_NAME: algorithm-exercises-cpp_${{ github.sha }} + +jobs: + + build: + name: "Build Docker images" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: "LINT: Build and push" + uses: docker/build-push-action@v6 + with: + context: . + target: lint + outputs: | + type=docker,dest=/tmp/${{ env.ARTIFACT_NAME }}_lint.tar + tags: | + ${{ env.IMAGE_NAME }}:lint + - name: "LINT: Upload artifact" + uses: actions/upload-artifact@v4 + with: + name: ${{ env.ARTIFACT_NAME }}_lint + path: /tmp/${{ env.ARTIFACT_NAME }}_lint.tar + + - name: "TEST: Build and push" + uses: docker/build-push-action@v6 + with: + context: . + target: testing + outputs: | + type=docker,dest=/tmp/${{ env.ARTIFACT_NAME }}_test.tar + tags: | + ${{ env.IMAGE_NAME }}:test + - name: "TEST: Upload artifact" + uses: actions/upload-artifact@v4 + with: + name: ${{ env.ARTIFACT_NAME }}_test + path: /tmp/${{ env.ARTIFACT_NAME }}_test.tar + + - name: "PRODUCTION: Build and push" + uses: docker/build-push-action@v6 + with: + context: . + target: production + outputs: | + type=docker,dest=/tmp/${{ env.ARTIFACT_NAME }}_prod.tar + tags: | + ${{ env.IMAGE_NAME }}:latest + ${{ env.IMAGE_NAME }}:${{ github.sha }} + - name: "PRODUCTION: Upload artifact" + uses: actions/upload-artifact@v4 + with: + name: ${{ env.ARTIFACT_NAME }}_prod + path: /tmp/${{ env.ARTIFACT_NAME }}_prod.tar + + lint: + name: "Run in docker: LINT" + runs-on: ubuntu-latest + needs: build + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: ${{ env.ARTIFACT_NAME }}_lint + path: /tmp/ + + - name: Load image + run: | + docker load --input /tmp/${{ env.ARTIFACT_NAME }}_lint.tar + docker image ls -a + + - name: Run lint + run: > + docker + compose --profile lint + run --rm ${{ env.IMAGE_NAME }}-lint + make lint + + test: + name: "Run in docker: TEST" + runs-on: ubuntu-latest + needs: build + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: ${{ env.ARTIFACT_NAME }}_test + path: /tmp/ + + - name: Load image + run: | + docker load --input /tmp/${{ env.ARTIFACT_NAME }}_test.tar + docker image ls -a + + - name: Run test + run: > + docker + compose --profile test + run --rm ${{ env.IMAGE_NAME }}-test + make test + + security: + name: "Snyk Container" + runs-on: ubuntu-latest + needs: build + permissions: + actions: read + contents: read + security-events: write + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: ${{ env.ARTIFACT_NAME }}_prod + path: /tmp/ + + - name: Load image + run: | + docker load --input /tmp/${{ env.ARTIFACT_NAME }}_prod.tar + docker image ls -a + + - name: Run Snyk to check Docker image for vulnerabilities + # Snyk can be used to break the build when it detects vulnerabilities. + # In this case we want to upload the issues to GitHub Code Scanning + continue-on-error: true + uses: snyk/actions/docker@master + env: + # yamllint disable rule:line-length + # In order to use the Snyk Action you will need to have a Snyk API token. + # See https://docs.snyk.io/integrations/ci-cd-integrations/github-actions-integration#getting-your-snyk-token + # or you can sign up for free at https://snyk.io/login + # yamllint enable rule:line-length + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + with: + image: ${{ env.IMAGE_NAME }}:${{ github.sha }} + args: --file=Dockerfile + # yamllint disable rule:line-length + # https://github.com/github/codeql-action/issues/2187#issuecomment-2043220400 + - name: Replace security-severity undefined for license-related findings + run: | + sed -i 's/"security-severity": "undefined"/"security-severity": "0"/g' snyk.sarif + sed -i 's/"security-severity": "null"/"security-severity": "0"/g' snyk.sarif + # yamllint enable rule:line-length + - name: Upload result to GitHub Code Scanning + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: 'snyk.sarif' + scan: + name: "Trivy (sarif)" + runs-on: ubuntu-latest + needs: build + permissions: + actions: read + contents: read + security-events: write + steps: + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: ${{ env.ARTIFACT_NAME }}_prod + path: /tmp/ + + - name: Load image + run: | + docker load --input /tmp/${{ env.ARTIFACT_NAME }}_prod.tar + docker image ls -a + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@0.24.0 + with: + image-ref: ${{ env.IMAGE_NAME }}:${{ github.sha }} + format: 'sarif' + output: 'trivy-results.sarif' + + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: 'trivy-results.sarif' + + report: + name: "Trivy (report)" + runs-on: ubuntu-latest + needs: build + steps: + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: ${{ env.ARTIFACT_NAME }}_prod + path: /tmp/ + + - name: Load image + run: | + docker load --input /tmp/${{ env.ARTIFACT_NAME }}_prod.tar + docker image ls -a + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@0.24.0 + with: + image-ref: ${{ env.IMAGE_NAME }}:${{ github.sha }} + format: 'table' diff --git a/.github/workflows/gitleaks.yml b/.github/workflows/gitleaks.yml new file mode 100644 index 0000000..4e087f9 --- /dev/null +++ b/.github/workflows/gitleaks.yml @@ -0,0 +1,32 @@ +--- + +name: gitleaks + +on: # yamllint disable-line rule:truthy + pull_request: + push: + workflow_dispatch: + schedule: + # ┌───────────── minute (0 - 59) + # │ ┌───────────── hour (0 - 23) + # │ │ ┌───────────── day of the month (1 - 31) + # │ │ │ ┌───────────── month (1 - 12 or JAN-DEC) + # │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT) + # │ │ │ │ │ + # │ │ │ │ │ + # │ │ │ │ │ + # * * * * * + - cron: "0 6 * * *" # run once a day at 6 AM +jobs: + scan: + name: gitleaks + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: gitleaks/gitleaks-action@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Only required for Organizations, not personal accounts. + # GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE}} diff --git a/.github/workflows/markdown-lint.yml b/.github/workflows/markdown-lint.yml new file mode 100644 index 0000000..c146dd9 --- /dev/null +++ b/.github/workflows/markdown-lint.yml @@ -0,0 +1,33 @@ +--- + +name: Markdown Lint + +on: # yamllint disable-line rule:truthy + push: + branches: ["main"] + pull_request: + # The branches below must be a subset of the branches above + branches: ["main"] + workflow_dispatch: + +jobs: + lint: + name: Markdown Lint + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 22.x + + - name: Install dependencies + run: npm install -g markdownlint-cli + + - name: Lint + run: > + markdownlint '**/*.md' --ignore node_modules + && echo '✔ Your code looks good.' diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml new file mode 100644 index 0000000..d7a8513 --- /dev/null +++ b/.github/workflows/sonarcloud.yml @@ -0,0 +1,69 @@ +--- +name: SonarCloud + +on: # yamllint disable-line rule:truthy + push: + branches: + - main + pull_request: + types: [opened, synchronize, reopened] +jobs: + build: + name: Build + runs-on: ubuntu-latest + env: + # Directory where build-wrapper output will be placed + BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory + steps: + - uses: actions/checkout@v4 + with: + # Shallow clones should be disabled for a better relevancy of analysis + fetch-depth: 0 + - name: Install Tools + run: | + pip install gcovr + + - name: Check Tools + run: | + make --version + cmake --version + vcpkg --version + gcovr --version + + - name: Install dependencies + run: | + vcpkg integrate install + vcpkg install catch2 + + - name: Install sonar-scanner and build-wrapper + uses: sonarsource/sonarcloud-github-c-cpp@v3 + + # yamllint disable rule:line-length + - name: Run build-wrapper + run: | + export VCPKG_ROOT=/usr/local/share/vcpkg + cmake --preset debug -B build + cmake --preset debug \ + -DCMAKE_TOOLCHAIN_FILE=/usr/local/share/vcpkg/scripts/buildsystems/vcpkg.cmake \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=1 \ + build + build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build --verbose + # yamllint enable rule:line-length + + - name: Run tests to generate coverage statistics + run: | + make coverage + - name: Collect coverage into one XML report + run: | + gcovr -e "src/tests/*" --sonarqube > coverage.xml + + # yamllint disable rule:line-length + - name: Run sonar-scanner + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: | + sonar-scanner \ + --define sonar.cfamily.compile-commands="${{ env.BUILD_WRAPPER_OUT_DIR }}/compile_commands.json" \ + --define sonar.coverageReportPaths=coverage.xml + # yamllint enable rule:line-length diff --git a/.github/workflows/yamllint.yml b/.github/workflows/yamllint.yml new file mode 100644 index 0000000..58d810f --- /dev/null +++ b/.github/workflows/yamllint.yml @@ -0,0 +1,26 @@ +--- + +name: YAML lint + +on: # yamllint disable-line rule:truthy + push: + branches: ["main"] + pull_request: + # The branches below must be a subset of the branches above + branches: ["main"] + workflow_dispatch: + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + + - name: Install yamllint + run: pip install yamllint + + - name: Lint YAML files + run: > + yamllint --strict . + && echo '✔ Your code looks good.' diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0825510 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +build/ +result* +.vscode/* + +# gcovr Coverage collector +*.gcov +coverage + +# cppcheck output +cppcheck-report.txt diff --git a/.markdownlint.yaml b/.markdownlint.yaml new file mode 100644 index 0000000..c0fd5b2 --- /dev/null +++ b/.markdownlint.yaml @@ -0,0 +1,264 @@ +--- + +# yamllint disable rule:line-length + +# Example markdownlint configuration with all properties set to their default value + +# Default state for all rules +default: true + +# Path to configuration file to extend +extends: null + +# MD001/heading-increment/header-increment - Heading levels should only increment by one level at a time +MD001: true + +# MD002/first-heading-h1/first-header-h1 - First heading should be a top-level heading +MD002: + # Heading level + level: 1 + +# MD003/heading-style/header-style - Heading style +MD003: + # Heading style + style: "consistent" + +# MD004/ul-style - Unordered list style +MD004: + # List style + style: "consistent" + +# MD005/list-indent - Inconsistent indentation for list items at the same level +MD005: true + +# MD006/ul-start-left - Consider starting bulleted lists at the beginning of the line +MD006: true + +# MD007/ul-indent - Unordered list indentation +MD007: + # Spaces for indent + indent: 2 + # Whether to indent the first level of the list + start_indented: false + # Spaces for first level indent (when start_indented is set) + start_indent: 2 + +# MD009/no-trailing-spaces - Trailing spaces +MD009: + # Spaces for line break + br_spaces: 2 + # Allow spaces for empty lines in list items + list_item_empty_lines: false + # Include unnecessary breaks + strict: false + +# MD010/no-hard-tabs - Hard tabs +MD010: + # Include code blocks + code_blocks: true + # Fenced code languages to ignore + ignore_code_languages: [] + # Number of spaces for each hard tab + spaces_per_tab: 1 + +# MD011/no-reversed-links - Reversed link syntax +MD011: true + +# MD012/no-multiple-blanks - Multiple consecutive blank lines +MD012: + # Consecutive blank lines + maximum: 1 + +# MD013/line-length - Line length +MD013: + # Number of characters + line_length: 80 + # Number of characters for headings + heading_line_length: 80 + # Number of characters for code blocks + code_block_line_length: 80 + # Include code blocks + code_blocks: false + # Include tables + tables: true + # Include headings + headings: true + + # Strict length checking + strict: false + # Stern length checking + stern: false + +# MD014/commands-show-output - Dollar signs used before commands without showing output +MD014: true + +# MD018/no-missing-space-atx - No space after hash on atx style heading +MD018: true + +# MD019/no-multiple-space-atx - Multiple spaces after hash on atx style heading +MD019: true + +# MD020/no-missing-space-closed-atx - No space inside hashes on closed atx style heading +MD020: true + +# MD021/no-multiple-space-closed-atx - Multiple spaces inside hashes on closed atx style heading +MD021: true + +# MD022/blanks-around-headings/blanks-around-headers - Headings should be surrounded by blank lines +MD022: + # Blank lines above heading + lines_above: 1 + # Blank lines below heading + lines_below: 1 + +# MD023/heading-start-left/header-start-left - Headings must start at the beginning of the line +MD023: true + +# MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content +MD024: + # Only check sibling headings + siblings_only: false + +# MD025/single-title/single-h1 - Multiple top-level headings in the same document +MD025: + # Heading level + level: 1 + # RegExp for matching title in front matter + front_matter_title: "^\\s*title\\s*[:=]" + +# MD026/no-trailing-punctuation - Trailing punctuation in heading +MD026: + # Punctuation characters not allowed at end of headings + punctuation: ".,;:!。,;:!" + +# MD027/no-multiple-space-blockquote - Multiple spaces after blockquote symbol +MD027: true + +# MD028/no-blanks-blockquote - Blank line inside blockquote +MD028: true + +# MD029/ol-prefix - Ordered list item prefix +MD029: + # List style + style: "one_or_ordered" + +# MD030/list-marker-space - Spaces after list markers +MD030: + # Spaces for single-line unordered list items + ul_single: 1 + # Spaces for single-line ordered list items + ol_single: 1 + # Spaces for multi-line unordered list items + ul_multi: 1 + # Spaces for multi-line ordered list items + ol_multi: 1 + +# MD031/blanks-around-fences - Fenced code blocks should be surrounded by blank lines +MD031: + # Include list items + list_items: true + +# MD032/blanks-around-lists - Lists should be surrounded by blank lines +MD032: true + +# MD033/no-inline-html - Inline HTML +MD033: + # Allowed elements + allowed_elements: [] + +# MD034/no-bare-urls - Bare URL used +MD034: true + +# MD035/hr-style - Horizontal rule style +MD035: + # Horizontal rule style + style: "consistent" + +# MD036/no-emphasis-as-heading/no-emphasis-as-header - Emphasis used instead of a heading +MD036: + # Punctuation characters + punctuation: ".,;:!?。,;:!?" + +# MD037/no-space-in-emphasis - Spaces inside emphasis markers +MD037: true + +# MD038/no-space-in-code - Spaces inside code span elements +MD038: true + +# MD039/no-space-in-links - Spaces inside link text +MD039: true + +# MD040/fenced-code-language - Fenced code blocks should have a language specified +MD040: + # List of languages + allowed_languages: [] + # Require language only + language_only: false + +# MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading +MD041: + # Heading level + level: 1 + # RegExp for matching title in front matter + front_matter_title: "^\\s*title\\s*[:=]" + +# MD042/no-empty-links - No empty links +MD042: true + +# MD043/required-headings/required-headers - Required heading structure +MD043: + # List of headings + headings: [ + "*" + ] + # Match case of headings + match_case: false + +# MD044/proper-names - Proper names should have the correct capitalization +MD044: + # List of proper names + names: [] + # Include code blocks + code_blocks: true + # Include HTML elements + html_elements: true + +# MD045/no-alt-text - Images should have alternate text (alt text) +MD045: true + +# MD046/code-block-style - Code block style +MD046: + # Block style + style: "consistent" + +# MD047/single-trailing-newline - Files should end with a single newline character +MD047: true + +# MD048/code-fence-style - Code fence style +MD048: + # Code fence style + style: "consistent" + +# MD049/emphasis-style - Emphasis style should be consistent +MD049: + # Emphasis style should be consistent + style: "consistent" + +# MD050/strong-style - Strong style should be consistent +MD050: + # Strong style should be consistent + style: "consistent" + +# MD051/link-fragments - Link fragments should be valid +MD051: true + +# MD052/reference-links-images - Reference links and images should use a label that is defined +MD052: true + +# MD053/link-image-reference-definitions - Link and image reference definitions should be needed +MD053: + # Ignored definitions + ignored_definitions: + - "//" + +# yamllint enable rule:line-length diff --git a/.yamlignore b/.yamlignore new file mode 100644 index 0000000..544b4c7 --- /dev/null +++ b/.yamlignore @@ -0,0 +1 @@ +.trunk/* diff --git a/.yamllint b/.yamllint new file mode 100644 index 0000000..b628837 --- /dev/null +++ b/.yamllint @@ -0,0 +1,19 @@ +--- +extends: default + +ignore-from-file: [.gitignore, .yamlignore] + +rules: + comments: + min-spaces-from-content: 1 + +# yamllint disable rule:line-length +# +# References: +# False positive: interpreting GitHub actions "on:" as a truthy value #430 +# https://github.com/adrienverge/yamllint/issues/430 +# +# YAML formatting not compliant with yamllint "spaces before comments" requirement #433 +# https://github.com/redhat-developer/vscode-yaml/issues/433#issuecomment-1235681987 +# +# yamllint enable rule:line-length diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..3f6f7ea --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.21) + +project(algoritm-exercises-cpp CXX C ASM) + +# Must be set before including CTest so that these arguments are applied when +# running `$ ninja test` or `$ make test`. +set(CMAKE_CTEST_ARGUMENTS "--extra-verbose" "--output-junit" "junit.xml") +list(APPEND CMAKE_CTEST_ARGUMENTS "--output-on-failure") + +# This must be in the top-level CMakeLists.txt to enable CMake/CTest support. +include(CTest) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED on) + +SET(GCC_COVERAGE_COMPILE_FLAGS "-fsanitize=address -fprofile-arcs -ftest-coverage -g -O0") +SET(GCC_COVERAGE_LINK_FLAGS "--coverage") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}") +SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}") + +add_subdirectory(src/lib/foo) + +if(BUILD_TESTING) + add_subdirectory(src/tests) +endif() + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "") diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..ccf9964 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,15 @@ +{ + "version": 2, + + "configurePresets": [ + { + "name": "debug", + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" + }, + "generator": "Unix Makefiles", + "binaryDir": "${sourceDir}/build/default" + + } + ] +} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..42ed680 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,106 @@ +FROM ubuntu:24.04 AS init + +ENV WORKDIR=/app +WORKDIR ${WORKDIR} + +RUN apt-get -y update && \ + apt-get -y install --no-install-recommends --no-install-suggests make && \ + rm -rf /var/lib/apt/lists/* + +FROM init AS builder + +# build tools +RUN apt-get -y update && \ + apt-get -y install --no-install-recommends --no-install-suggests build-essential cmake g++ make pkg-config && \ + rm -rf /var/lib/apt/lists/* + +# vcpkg Package Manager +ADD https://github.com/microsoft/vcpkg/archive/refs/tags/2024.08.23.tar.gz vcpkg.tar.gz +RUN apt-get -y update && \ + apt-get -y install --no-install-recommends --no-install-suggests \ + ca-certificates curl git unzip zip && \ + rm -rf /var/lib/apt/lists/* && \ + mkdir /opt/vcpkg && \ + tar xf vcpkg.tar.gz --strip-components=1 -C /opt/vcpkg && \ + /opt/vcpkg/bootstrap-vcpkg.sh && \ + ln -s /opt/vcpkg/vcpkg /usr/local/bin/vcpkg && \ + rm -rf vcpkg.tar.gz && \ + vcpkg version +ENV VCPKG_ROOT=/opt/vcpkg + +# sources +COPY ./src ${WORKDIR}/src +COPY ./CMakeLists.txt ${WORKDIR}/CMakeLists.txt +COPY ./CMakePresets.json ${WORKDIR}/CMakePresets.json +COPY ./Makefile ${WORKDIR}/ + +# dependencies +RUN vcpkg integrate install && \ + vcpkg install catch2 + +LABEL vcpkg=enabled + +# build +RUN ls -alhR && \ + mkdir build && \ + make build && \ + ls -alhR + +CMD ["make", "build"] + +FROM builder AS development + +# CMD [] + +FROM init AS lint + +RUN apt-get -y update && \ + apt-get -y install --no-install-recommends --no-install-suggests dialog apt-utils && \ + apt-get -y install --no-install-recommends --no-install-suggests yamllint && \ + apt-get -y install --no-install-recommends --no-install-suggests nodejs npm && \ + apt-get -y install --no-install-recommends --no-install-suggests cppcheck && \ + rm -rf /var/lib/apt/lists/* && \ + npm install -g --ignore-scripts markdownlint-cli + +# Code source +COPY ./src ${WORKDIR}/src +COPY ./CMakeLists.txt ${WORKDIR}/CMakeLists.txt +COPY ./CMakePresets.json ${WORKDIR}/CMakePresets.json +COPY ./Makefile ${WORKDIR}/ + +# markdownlint conf +COPY ./.markdownlint.yaml ${WORKDIR}/ + +# yamllint conf +COPY ./.yamllint ${WORKDIR}/ +COPY ./.yamlignore ${WORKDIR}/ +COPY ./.gitignore ${WORKDIR}/ + +CMD ["make", "lint"] + +FROM development AS testing + +RUN apt-get -y update && \ + apt-get -y install --no-install-recommends --no-install-suggests gcovr && \ + rm -rf /var/lib/apt/lists/* + +COPY --from=builder ${WORKDIR}/build ${WORKDIR}/ + +CMD ["make", "test"] + +FROM ubuntu:24.04 AS production + +ENV LOG_LEVEL=INFO +ENV BRUTEFORCE=false +ENV WORKDIR=/app +WORKDIR ${WORKDIR} + +# COPY ./Makefile ${WORKDIR}/ +COPY --from=builder ${WORKDIR}/build/src/lib/foo/*.a ${WORKDIR}/ + +RUN useradd --user-group --system --create-home --no-log-init app +USER app + +RUN ls -alhR + +CMD ["make", "run"] diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..ddf374d --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +# MIT License + +Copyright (c) 2023 Gonzalo Diaz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..63e381f --- /dev/null +++ b/Makefile @@ -0,0 +1,130 @@ +## REFERENCES: +## (1) Passing environment variable with fallback value to Makefile: +## https://stackoverflow.com/a/70772707/6366150 +## (2) Export environment variables inside "make environment" +## https://stackoverflow.com/a/49524393/6366150 +## (3) Uppercase to lowercase and vice versa +## https://community.unix.com/t/uppercase-to-lowercase-and-vice-versa/285278/6 +## (4) How do I trim leading and trailing whitespace from each line of some output? +## https://unix.stackexchange.com/a/279222/233927 +############################################################################ + +## (1) ## Allowed values: info | warn | error | debug +LOG_LEVEL ?= info +## (3) (4) +LOG_LEVEL :=$(shell echo '${LOG_LEVEL}'| tr '[:lower:]' '[:upper:]'| tr -d '[:blank:]') + +## (1) ## Allowed values: true | false +BRUTEFORCE ?= false +## (3) (4) +BRUTEFORCE :=$(shell echo '${BRUTEFORCE}'| tr '[:lower:]' '[:upper:]'| tr -d '[:blank:]') + +# DOCKER +BUILDKIT_PROGRESS=plain +DOCKER_COMPOSE=docker compose + +.MAIN: test +.PHONY: all clean dependencies help list test outdated +.EXPORT_ALL_VARIABLES: # (2) + +help: list + +list: + @LC_ALL=C $(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' + +env: + @echo "################################################################################" + @echo "## Environment: ################################################################" + @echo "################################################################################" + @printenv | grep -E "LOG_LEVEL|BRUTEFORCE|BUILDKIT_PROGRESS" + @echo "################################################################################" + +clean: + sh -c "rm -fr -v *.gcov" || true + sh -c "rm -fr -v ./build/*" || true + sh -c "rm -fr -v ./build/.*" || true + touch ./build/.gitkeep + sh -c "rm -fr -v ./coverage/.*" || true + touch ./coverage/.gitkeep + +build: dependencies + cmake --preset debug -B build && \ + cmake --preset debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 build && \ + cmake --build build --verbose + +dependencies: + vcpkg integrate install + vcpkg install catch2 + +lint/markdown: + markdownlint '**/*.md' && echo '✔ Your code looks good.' + +lint/yaml: + yamllint --stric . && echo '✔ Your code looks good.' + +lint: lint/markdown lint/yaml test/styling test/static + +test/static: + cppcheck --enable=all \ + --inconclusive \ + --library=posix \ + --std=c++17 \ + --suppress=missingIncludeSystem \ + src/ + +test/styling: + +format: dependencies + +test: env dependencies + cd build && make test + +coverage: test + gcovr -e "src/tests/*" + gcovr -e "src/tests/*" --lcov coverage/coverage.lcov + +coverage/html: + gcovr -e "src/tests/*" --html-details coverage/index.html + open coverage/index.html + +outdated: + +update: dependencies outdated + +upgrade: update + +compose/build: env + ${DOCKER_COMPOSE} --profile lint build + ${DOCKER_COMPOSE} --profile testing build + ${DOCKER_COMPOSE} --profile production build + +compose/rebuild: env + ${DOCKER_COMPOSE} --profile lint build --no-cache + ${DOCKER_COMPOSE} --profile testing build --no-cache + ${DOCKER_COMPOSE} --profile production build --no-cache + +compose/lint/markdown: compose/build + ${DOCKER_COMPOSE} --profile lint build + ${DOCKER_COMPOSE} --profile lint run --rm algorithm-exercises-cpp-lint make lint/markdown + +compose/lint/yaml: compose/build + ${DOCKER_COMPOSE} --profile lint run --rm algorithm-exercises-cpp-lint make lint/yaml + +compose/test/styling: compose/build + ${DOCKER_COMPOSE} --profile lint run --rm algorithm-exercises-cpp-lint make test/styling + +compose/test/static: compose/build + ${DOCKER_COMPOSE} --profile lint run --rm algorithm-exercises-cpp-lint make test/static + +compose/lint: compose/lint/markdown compose/lint/yaml compose/test/styling compose/test/static + +compose/test: compose/build + ${DOCKER_COMPOSE} --profile testing run --rm algorithm-exercises-cpp-test make test + +compose/run: compose/build + ${DOCKER_COMPOSE} --profile production run --rm algorithm-exercises-cpp ls -alhR + +all: env dependencies test + +run: + ls -alh diff --git a/README.md b/README.md new file mode 100644 index 0000000..aca0448 --- /dev/null +++ b/README.md @@ -0,0 +1,147 @@ +# Algorithm Exercises (C++17) + +[![C++17 CI](https://github.com/sir-gon/algorithm-exercises-cpp/actions/workflows/cpp.yml/badge.svg)](https://github.com/sir-gon/algorithm-exercises-cpp/actions/workflows/cpp.yml) +[![CppCheck Lint](https://github.com/sir-gon/algorithm-exercises-cpp/actions/workflows/cppcheck.yml/badge.svg)](https://github.com/sir-gon/algorithm-exercises-cpp/actions/workflows/cppcheck.yml) +[![Markdown Lint](https://github.com/sir-gon/algorithm-exercises-cpp/actions/workflows/markdown-lint.yml/badge.svg)](https://github.com/sir-gon/algorithm-exercises-cpp/actions/workflows/markdown-lint.yml) +[![YAML lint](https://github.com/sir-gon/algorithm-exercises-cpp/actions/workflows/yamllint.yml/badge.svg)](https://github.com/sir-gon/algorithm-exercises-cpp/actions/workflows/yamllint.yml) + +![GitHub](https://img.shields.io/github/license/sir-gon/algorithm-exercises-cpp) +![GitHub language count](https://img.shields.io/github/languages/count/sir-gon/algorithm-exercises-cpp) +![GitHub top language](https://img.shields.io/github/languages/top/sir-gon/algorithm-exercises-cpp) +[![CodeFactor](https://www.codefactor.io/repository/github/sir-gon/algorithm-exercises-cpp/badge)](https://www.codefactor.io/repository/github/sir-gon/algorithm-exercises-cpp) +[![codecov](https://codecov.io/gh/sir-gon/algorithm-exercises-cpp/branch/main/graph/badge.svg?token=YZ41BE67E4)](https://codecov.io/gh/sir-gon/algorithm-exercises-cpp) + +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=sir-gon_algorithm-exercises-cpp&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=sir-gon_algorithm-exercises-cpp) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=sir-gon_algorithm-exercises-cpp&metric=coverage)](https://sonarcloud.io/summary/new_code?id=sir-gon_algorithm-exercises-cpp) +[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=sir-gon_algorithm-exercises-cpp&metric=bugs)](https://sonarcloud.io/summary/new_code?id=sir-gon_algorithm-exercises-cpp) +[![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=sir-gon_algorithm-exercises-cpp&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=sir-gon_algorithm-exercises-cpp) +[![Duplicated Lines (%)](https://sonarcloud.io/api/project_badges/measure?project=sir-gon_algorithm-exercises-cpp&metric=duplicated_lines_density)](https://sonarcloud.io/summary/new_code?id=sir-gon_algorithm-exercises-cpp) + +## TL;DR + +Algorithms Exercises solved in [C++17](https://en.cppreference.com/w/cpp/17), +running with [Catch2](https://github.com/catchorg/Catch2) testing suite throug [CMake](https://cmake.org/). +Developed with TDD. + +## What is this? + +This repository is part of a series that share and solve the same [objectives](#objetives), +with the difference that each one is based on a different software ecosystem, +depending on the chosen programming language: + +- [Modern Javascript: algorithm-exercises-js](https://github.com/sir-gon/algorithm-exercises-js) +- [Python 3.x: algorithm-exercises-py](https://github.com/sir-gon/algorithm-exercises-py) +- [Typescript: algorithm-exercises-cpp](https://github.com/sir-gon/algorithm-exercises-cpp) +- [Go / Golang: algorithm-exercises-go](https://github.com/sir-gon/algorithm-exercises-go) +- [Java: algorithm-exercises-java](https://github.com/sir-gon/algorithm-exercises-java) +- [.NET / C#: algorithm-exercises-cpp](https://github.com/sir-gon/algorithm-exercises-cpp) + +## Objetives + +### Functional + +- For academic purposes, it is an backup of some algorithm exercises +(with their solutions), proposed by various sources: +[leetcode, hackerrank, projecteuler](#algorithm-excersices-sources), ... + +- The solutions must be written on "vanilla code", that is, +avoiding as much as possible the use of external libraries (in runtime). + +- Adoption of methodology and good practices. +Each exercise is implemented as a unit test set, +using TDD (Test-driven Development) and Clean Code ideas. + +## Install and Run + +### Install and Run directly + +Using a NodeJS runtime in your SO. You must install dependencies: + +```bash +cd build +cmake .. +make +make test +``` + +## About development + +```sh +cmake --version +``` + +```text +cmake version 3.30.3 + +CMake suite maintained and supported by Kitware (kitware.com/cmake). +``` + +```sh +g++ --version +``` + +```text +Apple clang version 15.0.0 (clang-1500.3.9.4) +Target: x86_64-apple-darwin23.6.0 +Thread model: posix +InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin +``` + +```sh +brew info catch2 +``` + +```text +==> catch2: stable 3.7.0 (bottled) +Modern, C++-native, header-only, test framework +https://github.com/catchorg/Catch2 +Installed +/usr/local/Cellar/catch2/3.7.0 (230 files, 2.7MB) * + Poured from bottle using the formulae.brew.sh API on 2024-09-08 at 19:35:03 +From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/c/catch2.rb +License: BSL-1.0 +==> Dependencies +Build: cmake ✘ +==> Analytics +install: 602 (30 days), 1,327 (90 days), 5,032 (365 days) +install-on-request: 561 (30 days), 1,232 (90 days), 4,619 (365 days) +build-error: 0 (30 days) +``` + +## Algorithm excersices sources + +- [Leetcode](https://leetcode.com/) online platform for +coding interview preparation. +- [HackerRank](https://www.hackerrank.com/) competitive programming challenges +for both consumers and businesses. +- [Project Euler](https://projecteuler.net/) a series of computational problems +intended to be solved with computer programs. + +Use these answers to learn some tip and tricks for algorithms tests. + +### Disclaimer. Why I publish solutions? + +As Project Euler says: + + + +```text +I learned so much solving problem XXX, so is it okay to publish my solution elsewhere? +It appears that you have answered your own question. There is nothing quite like that "Aha!" moment when you finally beat a problem which you have been working on for some time. It is often through the best of intentions in wishing to share our insights so that others can enjoy that moment too. Sadly, that will rarely be the case for your readers. Real learning is an active process and seeing how it is done is a long way from experiencing that epiphany of discovery. Please do not deny others what you have so richly valued yourself. + +However, the rule about sharing solutions outside of Project Euler does not apply to the first one-hundred problems, as long as any discussion clearly aims to instruct methods, not just provide answers, and does not directly threaten to undermine the enjoyment of solving later problems. Problems 1 to 100 provide a wealth of helpful introductory teaching material and if you are able to respect our requirements, then we give permission for those problems and their solutions to be discussed elsewhere. +``` + +If you have better answers or optimal solutions, fork and PR-me + +Enjoy 😁 ! + +## Status + +### License + +[LICENSE.md](LICENSE.md) + +### Coverage + +[![Coverage](https://codecov.io/gh/sir-gon/algorithm-exercises-cpp/graphs/tree.svg?token=YZ41BE67E4)](https://codecov.io/gh/sir-gon/algorithm-exercises-cpp) diff --git a/build/.gitkeep b/build/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..b899879 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,51 @@ +--- +services: + algorithm-exercises-cpp-test: + image: algorithm-exercises-cpp:test + build: + context: . + target: testing + environment: + LOG_LEVEL: ${LOG_LEVEL:-info} ## (1) ## info | debug + BRUTEFORCE: ${BRUTEFORCE:-false} ## (1) ## true | false + volumes: + - ./coverage:/app/coverage + profiles: ["testing"] + + algorithm-exercises-cpp-lint: + image: algorithm-exercises-cpp:lint + build: + context: . + target: lint + # environment: + # LOG_LEVEL: ${LOG_LEVEL:-info} ## (1) ## info | debug + # BRUTEFORCE: ${BRUTEFORCE:-false} ## (1) ## true | false + volumes: + - ./:/app + profiles: ["lint"] + + algorithm-exercises-cpp-dev: + image: algorithm-exercises-cpp:dev + build: + context: . + target: development + environment: + LOG_LEVEL: ${LOG_LEVEL:-info} ## (1) ## info | debug + BRUTEFORCE: ${BRUTEFORCE:-false} ## (1) ## true | false + volumes: + - ./:/app + profiles: ["development"] + + algorithm-exercises-cpp: + image: algorithm-exercises-cpp:latest + build: + context: . + target: production + # volumes: + # - ./:/app + profiles: ["production"] + +## REFERENCES: +## (1) Passing Environment variable with fallback value: +## https://stackoverflow.com/a/70772707/6366150 +## diff --git a/coverage/.gitkeep b/coverage/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..038a89c --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,15 @@ +sonar.projectKey=sir-gon_algorithm-exercises-cpp +sonar.organization=sir-gon + +# This is the name and version displayed in the SonarCloud UI. +#sonar.projectName=algorithm-exercises-cpp +#sonar.projectVersion=1.0 + + +# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. +sonar.sources=src +sonar.exclusions=src/tests/* +sonar.coverage.exclusions=src/tests/* + +# Encoding of the source code. Default is default system encoding +sonar.sourceEncoding=UTF-8 diff --git a/src/lib/foo/CMakeLists.txt b/src/lib/foo/CMakeLists.txt new file mode 100644 index 0000000..5fab520 --- /dev/null +++ b/src/lib/foo/CMakeLists.txt @@ -0,0 +1,22 @@ +SET(GCC_COVERAGE_COMPILE_FLAGS "-fsanitize=address -fprofile-arcs -ftest-coverage") + +file(GLOB SOURCES "src/*.cpp") +add_library(foo STATIC ${SOURCES}) + +target_include_directories(foo + PUBLIC + $ + $ +) + +install(TARGETS foo + EXPORT fooConfig + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin + INCLUDES DESTINATION include +) + +install(DIRECTORY include/ DESTINATION include) +install(EXPORT fooConfig DESTINATION share/foo/cmake) +export(TARGETS foo FILE fooConfig.cmake) diff --git a/src/lib/foo/include/foo/foo.hpp b/src/lib/foo/include/foo/foo.hpp new file mode 100644 index 0000000..c4a0016 --- /dev/null +++ b/src/lib/foo/include/foo/foo.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include + +namespace foo { + uint64_t add(uint64_t a, uint64_t b); +}; diff --git a/src/lib/foo/src/foo.cpp b/src/lib/foo/src/foo.cpp new file mode 100644 index 0000000..534df34 --- /dev/null +++ b/src/lib/foo/src/foo.cpp @@ -0,0 +1,5 @@ +#include + +uint64_t foo::add(uint64_t a, uint64_t b) { + return a + b; +} diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt new file mode 100644 index 0000000..28245d9 --- /dev/null +++ b/src/tests/CMakeLists.txt @@ -0,0 +1,20 @@ +find_package(Catch2 3 REQUIRED) +find_path(CATCH_INCLUDE_DIR NAMES catch.hpp PATH_SUFFIXES catch2) + + + +file(GLOB SOURCES "unit/lib/*.cpp") +add_executable(unit-tests_combined ${SOURCES}) + +# Test framework dependencies. +target_link_libraries(unit-tests_combined PRIVATE Catch2::Catch2WithMain) + +# Functionality to test. +target_link_libraries(unit-tests_combined PRIVATE foo) + +list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras) +include(CTest) +include(Catch) + +# add_test(NAME unit-tests COMMAND unit-tests_combined) +catch_discover_tests(unit-tests_combined WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" DISCOVERY_MODE "PRE_TEST") diff --git a/src/tests/unit/lib/foo.cpp b/src/tests/unit/lib/foo.cpp new file mode 100644 index 0000000..55dc643 --- /dev/null +++ b/src/tests/unit/lib/foo.cpp @@ -0,0 +1,12 @@ +#include + +#include + +TEST_CASE("adding numbers work", "[foo]") +{ + CHECK(foo::add(0, 0) == 0); + CHECK(foo::add(0, 7) == 7); + CHECK(foo::add(7, 0) == 7); + CHECK(foo::add(7, 7) == 14); +} +