From e4255b0a7ec97b386e64bbdddce3eff234b73383 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Wed, 15 Jul 2020 13:30:12 -0400 Subject: [PATCH] Fix test suite --- .github/workflows/artifact-cleanup.yml | 15 + .github/workflows/suite.yml | 557 +++++++++++++----- appveyor.yml | 29 - build/UploadCoverage.ps1 | 7 - build/coverlet.runsettings | 13 + .../Components/Byond/ByondManager.cs | 4 +- .../System/PosixProcessFeatures.cs | 30 +- tests/DMAPI/BasicOperation/Test.dm | 4 +- .../Tgstation.Server.Api.Tests.csproj | 4 +- .../Tgstation.Server.Client.Tests.csproj | 4 +- ...Tgstation.Server.Host.Console.Tests.csproj | 4 +- ...Tgstation.Server.Host.Service.Tests.csproj | 4 +- .../System/TestProcessFeatures.cs | 4 +- .../Tgstation.Server.Host.Tests.csproj | 4 +- ...gstation.Server.Host.Watchdog.Tests.csproj | 4 +- .../Instance/DeploymentTest.cs | 7 + .../Instance/WatchdogTest.cs | 4 +- .../Tgstation.Server.Tests/IntegrationTest.cs | 7 +- .../Tgstation.Server.Tests.csproj | 4 +- tgstation-server.sln | 1 - 20 files changed, 478 insertions(+), 232 deletions(-) create mode 100644 .github/workflows/artifact-cleanup.yml delete mode 100644 build/UploadCoverage.ps1 create mode 100644 build/coverlet.runsettings diff --git a/.github/workflows/artifact-cleanup.yml b/.github/workflows/artifact-cleanup.yml new file mode 100644 index 0000000000..bee44d2fa6 --- /dev/null +++ b/.github/workflows/artifact-cleanup.yml @@ -0,0 +1,15 @@ +name: 'Delete Old Artifacts' +on: + schedule: + - cron: '0 * * * *' # every hour + +jobs: + delete-artifacts: + name: Delete Artifacts + runs-on: ubuntu-latest + steps: + - name: Delete Artifacts + uses: kolpav/purge-artifacts-action@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + expire-in: 30days # Setting this to 0 will delete all artifacts diff --git a/.github/workflows/suite.yml b/.github/workflows/suite.yml index 3a0b81c4e6..2afa6cba58 100644 --- a/.github/workflows/suite.yml +++ b/.github/workflows/suite.yml @@ -10,64 +10,134 @@ on: - dev - master +env: + TGS4_TEST_DISCORD_CHANNEL: ${{ secrets.DISCORD_CHANNEL_ID }} + TGS4_TEST_DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }} + TGS4_TEST_IRC_CHANNEL: ${{ secrets.IRC_CHANNEL }} + TGS4_TEST_IRC_CONNECTION_STRING: ${{ secrets.IRC_CONNECTION_STRING }} + TGS4_TEST_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + jobs: - server-unit-tests: - name: Build Server and Run Unit Tests - strategy: - matrix: - dotnet: [ '3.1.x' ] - node: [ '12.x' ] - configuration: [ 'Debug', 'Release' ] + dmapi-build: + name: Build DMAPI env: - TGS4_TEST_DISCORD_CHANNEL: ${{ secrets.DISCORD_CHANNEL_ID }} - TGS4_TEST_DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }} - TGS4_TEST_IRC_CHANNEL: ${{ secrets.IRC_CHANNEL }} - TGS4_TEST_IRC_CONNECTION_STRING: ${{ secrets.IRC_CONNECTION_STRING }} - TGS4_TEST_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BYOND_MAJOR: 513 + BYOND_MINOR: 1527 runs-on: ubuntu-latest steps: - - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node }} + - name: Install x86 libc Dependencies + run: | + sudo dpkg --add-architecture i386 + sudo apt-get update + sudo apt-get install -y libc6-i386 libstdc++6:i386 - - name: Setup dotnet + - name: Install BYOND + if: steps.cache-byond.outputs.cache-hit != 'true' + run: | + echo "Setting up BYOND." + mkdir -p "$HOME/BYOND-${{ env.BYOND_MAJOR }}.${{ env.BYOND_MINOR }}" + cd "$HOME/BYOND-${{ env.BYOND_MAJOR }}.${{ env.BYOND_MINOR }}" + curl "http://www.byond.com/download/build/${{ env.BYOND_MAJOR }}/${{ env.BYOND_MAJOR }}.${{ env.BYOND_MINOR }}_byond_linux.zip" -o byond.zip + unzip byond.zip + cd byond + make here + exit 0 + + - name: Checkout + uses: actions/checkout@v1 + + - name: Build DMAPI Test Project + run: | + set -e + retval=1 + source $HOME/BYOND-${{ env.BYOND_MAJOR }}.${{ env.BYOND_MINOR }}/byond/bin/byondsetup + + if hash DreamMaker 2>/dev/null + then + DreamMaker tests/DMAPI/BasicOperation/basic_operation_test.dme 2>&1 | tee result.log + retval=$? + if ! grep '\- 0 errors, 0 warnings' result.log + then + retval=1 + fi + else + echo "Couldn't find the DreamMaker executable, aborting." + retval=2 + fi + exit $retval + + docker-build: + name: Build Docker Image + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v1 + + - name: Build Docker Image + run: docker build . -f build/Dockerfile + + linux-unit-tests: + name: Linux Unit Tests + strategy: + matrix: + configuration: [ 'Debug', 'Release' ] + runs-on: ubuntu-latest + steps: + - name: Install Node 12.X + uses: actions/setup-node@v1 + with: + node-version: 12.x + + - name: Setup dotnet 3.1.X uses: actions/setup-dotnet@v1 with: - dotnet-version: ${{ matrix.dotnet }} + dotnet-version: 3.1.x - name: Checkout uses: actions/checkout@v1 + - name: Build + run: dotnet build -c ${{ matrix.configuration }}NoService + + - name: Run Unit Tests + run: sudo dotnet test tgstation-server.sln --no-build --filter FullyQualifiedName!~IntegrationTest -l "console;verbosity=detailed;noprogress=true" -c ${{ matrix.configuration }}NoService --collect:"XPlat Code Coverage" --settings build/coverlet.runsettings -r ./TestResults + + - name: Store Code Coverage + uses: actions/upload-artifact@v2 + with: + name: linux-unit-test-coverage-${{ matrix.configuration }} + path: ./TestResults/ + + windows-unit-tests: + name: Windows Unit Tests + strategy: + matrix: + configuration: [ 'Debug', 'Release' ] + runs-on: windows-latest + steps: + - name: Checkout + uses: actions/checkout@v1 + - name: Build run: dotnet build -c ${{ matrix.configuration }} - name: Run Unit Tests - run: sudo dotnet test tgstation-server.sln --no-build --filter FullyQualifiedName!~IntegrationTests -l "console;verbosity=detailed;noprogress=true" -c ${{ matrix.configuration }} /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:CoverletOutput="./unit_tests.xml" + run: dotnet test tgstation-server.sln --no-build --filter FullyQualifiedName!~IntegrationTest -l "console;verbosity=detailed;noprogress=true" -c ${{ matrix.configuration }} --collect:"XPlat Code Coverage" --settings build/coverlet.runsettings -r ./TestResults - - name: Publish Integration Test Artifacts - run: | - cd tests/Tgstation.Server.tests - dotnet publish -c ${{ matrix.configuration }} -o Artifacts --no-build - - - name: Store Integration Test Artifacts + - name: Store Code Coverage uses: actions/upload-artifact@v2 with: - name: integration-test-bins - path: tests/Tgstation.Server.Tests/Artifacts/ + name: windows-unit-test-coverage-${{ matrix.configuration }} + path: ./TestResults/ - - name: Upload Code Coverage - uses: codecov/codecov-action@v1 - with: - file: ./unit_tests.xml - flags: unittests - fail_ci_if_error: true - - integration-tests: - name: Integration Tests - needs: [server-unit-tests, dmapi-build] + linux-integration-tests: + name: Linux Integration Tests + needs: dmapi-build services: # We start all dbs here so we can just code the stuff once postgres: image: postgres + ports: + - 5432:5432 env: POSTGRES_PASSWORD: postgres # Set health checks to wait until postgres has started @@ -78,6 +148,8 @@ jobs: --health-retries 5 mariadb: image: mariadb + ports: + - 3306:3306 env: MYSQL_ROOT_PASSWORD: mariadb options: >- @@ -87,6 +159,8 @@ jobs: --health-retries=3 mysql: image: mysql:5.7.31 + ports: + - 3307:3306 env: MYSQL_ROOT_PASSWORD: mysql options: >- @@ -97,136 +171,329 @@ jobs: strategy: matrix: database-type: [ 'Sqlite', 'PostgresSql', 'MariaDB', 'MySql' ] - basic-watchdog: [ 'yes', 'no' ] + watchdog-type: [ 'Basic', 'System' ] + configuration: [ 'Debug', 'Release' ] runs-on: ubuntu-latest steps: - - name: Install Native Dependencies - run: | - sudo dpkg add-architecture i386 - sudo apt-get update - sudo apt-get install -y libc6-i386 libstdc++6:i386 gdb + - name: Disable ptrace_scope + run: echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope - - name: Disable ptrace_scope - run: echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope + - name: Install Native Dependencies + run: | + sudo dpkg --add-architecture i386 + sudo apt-get update + sudo apt-get install -y libc6-i386 libstdc++6:i386 gdb - - name: Setup dotnet - uses: actions/setup-dotnet@v1 - with: - dotnet-version: ${{ matrix.dotnet }} + - name: Install Node 12.X + uses: actions/setup-node@v1 + with: + node-version: 12.x - - name: Set Sqlite Connection Info - if: ${{ matrix.database-type == 'Sqlite' }} - run: | - echo "::set-env name=TGS4_TEST_DATABASE_TYPE::Sqlite" - echo "::set-env name=TGS4_TEST_CONNECTION_STRING::Data Source=TravisTestDB.sqlite3;Mode=ReadWriteCreate" + - name: Setup dotnet + uses: actions/setup-dotnet@v1 + with: + dotnet-version: ${{ matrix.dotnet }} - - name: Set PostgresSql Connection Info - if: ${{ matrix.database-type == 'PostgresSql' }} - run: | - echo "::set-env name=TGS4_TEST_DATABASE_TYPE::PostgresSql" - echo "::set-env name=TGS4_TEST_CONNECTION_STRING::Application Name=tgstation-server;Port=5432;Host=postgres;Username=postgres;Password=postgres;Database=TGS_Test" + - name: Set Sqlite Connection Info + if: ${{ matrix.database-type == 'Sqlite' }} + run: | + echo "::set-env name=TGS4_TEST_DATABASE_TYPE::Sqlite" + echo "::set-env name=TGS4_TEST_CONNECTION_STRING::Data Source=TravisTestDB.sqlite3;Mode=ReadWriteCreate" - - name: Set MariaDB Connection Info - if: ${{ matrix.database-type == 'MariaDB' }} - run: | - echo "::set-env name=TGS4_TEST_DATABASE_TYPE::MariaDB" - echo "::set-env name=TGS4_TEST_CONNECTION_STRING::server=mariadb;uid=root;pwd=mariadb;database=tgs_test" + - name: Set PostgresSql Connection Info + if: ${{ matrix.database-type == 'PostgresSql' }} + run: | + echo "::set-env name=TGS4_TEST_DATABASE_TYPE::PostgresSql" + echo "::set-env name=TGS4_TEST_CONNECTION_STRING::Application Name=tgstation-server;Host=127.0.0.1;Username=postgres;Password=postgres;Database=TGS_Test" - - name: Set MySQL Connection Info - if: ${{ matrix.database-type == 'MySql' }} - run: | - echo "::set-env name=TGS4_TEST_DATABASE_TYPE::MySql" - echo "::set-env name=TGS4_TEST_CONNECTION_STRING::server=mysql;uid=root;pwd=mysql;database=tgs_test" - echo "::set-env name=Database__ServerVersion::5.7.31" + - name: Set MariaDB Connection Info + if: ${{ matrix.database-type == 'MariaDB' }} + run: | + echo "::set-env name=TGS4_TEST_DATABASE_TYPE::MariaDB" + echo "::set-env name=TGS4_TEST_CONNECTION_STRING::Server=127.0.0.1;uid=root;pwd=mariadb;database=tgs_test" - - name: Set General__UseBasicWatchdog - if: ${{ matrix.basic-watchdog == 'yes' }} - run: echo "::set-env name=General__UseBasicWatchdog::true" + - name: Set MySQL Connection Info + if: ${{ matrix.database-type == 'MySql' }} + run: | + echo "::set-env name=TGS4_TEST_DATABASE_TYPE::MySql" + echo "::set-env name=TGS4_TEST_CONNECTION_STRING::Server=127.0.0.1;Port=3307;uid=root;pwd=mysql;database=tgs_test" + echo "::set-env name=Database__ServerVersion::5.7.31" - - name: Checkout - uses: actions/checkout@v1 + - name: Set General__UseBasicWatchdog + if: ${{ matrix.watchdog-type == 'Basic' }} + run: echo "::set-env name=General__UseBasicWatchdog::true" - - name: Set TGS4_TEST_PULL_REQUEST_NUMBER - if: ${{ github.event_name == 'pull_request' }} - run: echo "::set-env name=TGS4_TEST_PULL_REQUEST_NUMBER::${{ github.event.issue.number }}" + - name: Checkout + uses: actions/checkout@v1 - - name: Retrieve Integration Test Artifacts - uses: actions/download-artifact@v2 - with: - name: integration-test-bins - path: tests/Tgstation.Server.Tests/Artifacts + - name: Set TGS4_TEST_PULL_REQUEST_NUMBER + if: ${{ github.event_name == 'pull_request' }} + run: echo "::set-env name=TGS4_TEST_PULL_REQUEST_NUMBER::${{ github.event.number }}" - - name: Run Integration Test - run: | - cd tests/Tgstation.Server.Tests - dotnet test Artifacts/Tgstation.Server.Tests.dll -l "console;verbosity=detailed;noprogress=true" -c ${{ matrix.configuration }} /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:CoverletOutput="./integration_tests.xml" + - name: Run Integration Test + run: | + cd tests/Tgstation.Server.Tests + sleep 10 + dotnet test -c ${{ matrix.configuration }} -l "console;verbosity=detailed;noprogress=true" --collect:"XPlat Code Coverage" --settings ../../build/coverlet.runsettings -r ./TestResults - - name: Upload Code Coverage - uses: codecov/codecov-action@v1 - with: - file: ./integration_tests.xml - flags: integration - fail_ci_if_error: true + - name: Store Code Coverage + uses: actions/upload-artifact@v2 + with: + name: linux-integration-test-coverage-${{ matrix.configuration }}-${{ matrix.watchdog-type }}-${{ matrix.database-type }} + path: tests/Tgstation.Server.Tests/TestResults/ - docker-build: - name: Build Docker Image - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v1 + - name: Package Server Console + if: ${{ matrix.configuration == 'Release' && matrix.watchdog-type == 'System' && matrix.database-type == 'MariaDB' }} + run: | + cd src/Tgstation.Server.Host.Console + dotnet publish -c ${{ matrix.configuration }} -o ../../Artifacts/Console + cd ../Tgstation.Server.Host + dotnet publish -c ${{ matrix.configuration }} --no-build -o ../../Artifacts/Console/lib/Default - - name: Build Docker Image - run: docker build . -f build/Dockerfile + - name: Store Server Console + if: ${{ matrix.configuration == 'Release' && matrix.watchdog-type == 'System' && matrix.database-type == 'MariaDB' }} + uses: actions/upload-artifact@v2 + with: + name: ServerConsole + path: Artifacts/Console/ - dmapi-build: - name: Build DMAPI + windows-integration-test: + name: Windows Integration Test + needs: dmapi-build env: - BYOND_MAJOR: 513 - BYOND_MINOR: 1527 + TGS4_TEST_CONNECTION_STRING: Server=(localdb)\MSSQLLocalDB;Integrated Security=true;Initial Catalog=TGS_Test;Application Name=tgstation-server + TGS4_TEST_DATABASE_TYPE: SqlServer + TGS4_TEST_DUMP_API_SPEC: yes + strategy: + matrix: + watchdog-type: [ 'Basic', 'System' ] + configuration: [ 'Debug', 'Release' ] + runs-on: windows-latest + steps: + - name: Set General__UseBasicWatchdog + if: ${{ matrix.watchdog-type == 'Basic' }} + run: echo "::set-env name=General__UseBasicWatchdog::true" + + - name: Checkout + uses: actions/checkout@v1 + + - name: Set TGS4_TEST_PULL_REQUEST_NUMBER + if: ${{ github.event_name == 'pull_request' }} + run: echo "::set-env name=TGS4_TEST_PULL_REQUEST_NUMBER::${{ github.event.number }}" + + - name: Run Integration Test + run: | + cd tests/Tgstation.Server.Tests + Start-Sleep -Seconds 10 + dotnet test -c ${{ matrix.configuration }} -l "console;verbosity=detailed;noprogress=true" --collect:"XPlat Code Coverage" --settings ../../build/coverlet.runsettings -r ./TestResults + + - name: Store Code Coverage + uses: actions/upload-artifact@v2 + with: + name: windows-integration-test-coverage-${{ matrix.configuration }}-${{ matrix.watchdog-type }} + path: tests/Tgstation.Server.Tests/TestResults/ + + - name: Store OpenAPI Spec + if: ${{ matrix.configuration == 'Release' && matrix.watchdog-type == 'System' }} + uses: actions/upload-artifact@v2 + with: + name: openapi-spec + path: C:/swagger.json + + - name: Package Server Console + if: ${{ matrix.configuration == 'Release' && matrix.watchdog-type == 'Basic' }} + run: | + cd src/Tgstation.Server.Host.Service + dotnet publish -c ${{ matrix.configuration }} -o ../../Artifacts/Service + cd ../Tgstation.Server.Host + dotnet publish -c ${{ matrix.configuration }} --no-build -o ../../Artifacts/Service/lib/Default + + - name: Store Server Service + if: ${{ matrix.configuration == 'Release' && matrix.watchdog-type == 'Basic' }} + uses: actions/upload-artifact@v2 + with: + name: ServerService + path: Artifacts/Service/ + + validate-openapi-spec: + name: OpenAPI Spec Validation + needs: windows-integration-test + runs-on: windows-latest + steps: + - name: Install IBM OpenAPI Validator + run: npm i -g ibm-openapi-validator + + - name: Checkout + uses: actions/checkout@v1 + + - name: Retrieve OpenAPI Spec + uses: actions/download-artifact@v2 + with: + name: openapi-spec + path: ./swagger.json + + - name: Lint OpenAPI Spec + run: npx lint-openapi -p -c build/OpenApiValidationSettings.json ./swagger.json + + upload-code-coverage: + name: Upload Code Coverage + needs: [linux-unit-tests, linux-integration-tests, windows-unit-tests, windows-integration-test] runs-on: ubuntu-latest steps: - - name: Install x86 libc Dependencies - run: | - sudo dpkg add-architecture i386 - sudo apt-get update - sudo apt-get install -y libc6-i386 libstdc++6:i386 + - name: Retrieve Linux Unit Test Coverage (Debug) + uses: actions/download-artifact@v2 + with: + name: linux-unit-test-coverage-Debug + path: ./code_coverage/unit_tests/linux_unit_tests_debug - - name: Cache BYOND - id: cache-byond - uses: actions/cache@v2 - with: - path: byond - key: ${{ env.BYOND_MAJOR }}.${{ env.BYOND_MINOR }} + - name: Retrieve Linux Unit Test Coverage (Release) + uses: actions/download-artifact@v2 + with: + name: linux-unit-test-coverage-Release + path: ./code_coverage/unit_tests/linux_unit_tests_release - - name: Install BYOND - if: steps.cache-byond.outputs.cache-hit != 'true' - run: | - echo "Setting up BYOND." - mkdir -p "$HOME/BYOND-${{ env.BYOND_MAJOR }}.${{ env.BYOND_MINOR }}" - cd "$HOME/BYOND-${BYOND_MAJOR}.${BYOND_MINOR}" - curl "http://www.byond.com/download/build/${{ env.BYOND_MAJOR }}/${{ env.BYOND_MAJOR }}.${{ env.BYOND_MINOR }}_byond_linux.zip" -o byond.zip - unzip byond.zip - cd byond - make here - cd ~/ - exit 0 + - name: Retrieve Linux Integration Test Coverage (Debug, Basic, Sqlite) + uses: actions/download-artifact@v2 + with: + name: linux-integration-test-coverage-Debug-Basic-Sqlite + path: ./code_coverage/integration_tests/linux_integration_tests_debug_basic_sqlite - - name: Build DMAPI Test Project - run: | - set -e - retval=1 - source $HOME/BYOND-${{ env.BYOND_MAJOR }}.${{ env.BYOND_MINOR }}/byond/bin/byondsetup + - name: Retrieve Linux Integration Test Coverage (Release, Basic, Sqlite) + uses: actions/download-artifact@v2 + with: + name: linux-integration-test-coverage-Release-Basic-Sqlite + path: ./code_coverage/integration_tests/linux_integration_tests_release_basic_sqlite - if hash DreamMaker 2>/dev/null - then - DreamMaker $DMEName 2>&1 | tee result.log - retval=$? - if ! grep '\- 0 errors, 0 warnings' result.log - then - retval=1 - fi - else - echo "Couldn't find the DreamMaker executable, aborting." - retval=2 - fi - exit $retval + - name: Retrieve Linux Integration Test Coverage (Debug, System, Sqlite) + uses: actions/download-artifact@v2 + with: + name: linux-integration-test-coverage-Debug-System-Sqlite + path: ./code_coverage/integration_tests/linux_integration_tests_debug_system_sqlite + + - name: Retrieve Linux Integration Test Coverage (Release, System, Sqlite) + uses: actions/download-artifact@v2 + with: + name: linux-integration-test-coverage-Release-System-Sqlite + path: ./code_coverage/integration_tests/linux_integration_tests_release_system_sqlite + + - name: Retrieve Linux Integration Test Coverage (Debug, Basic, PostgresSql) + uses: actions/download-artifact@v2 + with: + name: linux-integration-test-coverage-Debug-Basic-PostgresSql + path: ./code_coverage/integration_tests/linux_integration_tests_debug_basic_postgressql + + - name: Retrieve Linux Integration Test Coverage (Release, Basic, PostgresSql) + uses: actions/download-artifact@v2 + with: + name: linux-integration-test-coverage-Release-Basic-PostgresSql + path: ./code_coverage/integration_tests/linux_integration_tests_release_basic_postgressql + + - name: Retrieve Linux Integration Test Coverage (Debug, System, PostgresSql) + uses: actions/download-artifact@v2 + with: + name: linux-integration-test-coverage-Debug-System-PostgresSql + path: ./code_coverage/integration_tests/linux_integration_tests_debug_system_postgressql + + - name: Retrieve Linux Integration Test Coverage (Release, System, PostgresSql) + uses: actions/download-artifact@v2 + with: + name: linux-integration-test-coverage-Release-System-PostgresSql + path: ./code_coverage/integration_tests/linux_integration_tests_release_system_mariadb + + - name: Retrieve Linux Integration Test Coverage (Debug, Basic, MariaDB) + uses: actions/download-artifact@v2 + with: + name: linux-integration-test-coverage-Debug-Basic-MariaDB + path: ./code_coverage/integration_tests/linux_integration_tests_debug_basic_mariadb + + - name: Retrieve Linux Integration Test Coverage (Release, Basic, MariaDB) + uses: actions/download-artifact@v2 + with: + name: linux-integration-test-coverage-Release-Basic-MariaDB + path: ./code_coverage/integration_tests/linux_integration_tests_release_basic_mariadb + + - name: Retrieve Linux Integration Test Coverage (Debug, System, MariaDB) + uses: actions/download-artifact@v2 + with: + name: linux-integration-test-coverage-Debug-System-MariaDB + path: ./code_coverage/integration_tests/linux_integration_tests_debug_system_mariadb + + - name: Retrieve Linux Integration Test Coverage (Release, System, MariaDB) + uses: actions/download-artifact@v2 + with: + name: linux-integration-test-coverage-Release-System-MariaDB + path: ./code_coverage/integration_tests/linux_integration_tests_release_system_mysql + + - name: Retrieve Linux Integration Test Coverage (Debug, Basic, MySql) + uses: actions/download-artifact@v2 + with: + name: linux-integration-test-coverage-Debug-Basic-MySql + path: ./code_coverage/integration_tests/linux_integration_tests_debug_basic_mysql + + - name: Retrieve Linux Integration Test Coverage (Release, Basic, MySql) + uses: actions/download-artifact@v2 + with: + name: linux-integration-test-coverage-Release-Basic-MySql + path: ./code_coverage/integration_tests/linux_integration_tests_release_basic_mysql + + - name: Retrieve Linux Integration Test Coverage (Debug, System, MySql) + uses: actions/download-artifact@v2 + with: + name: linux-integration-test-coverage-Debug-System-MySql + path: ./code_coverage/integration_tests/linux_integration_tests_debug_system_mysql + + - name: Retrieve Linux Integration Test Coverage (Release, System, MySql) + uses: actions/download-artifact@v2 + with: + name: linux-integration-test-coverage-Release-System-MySql + path: ./code_coverage/integration_tests/linux_integration_tests_release_system_mysql + + - name: Retrieve Windows Unit Test Coverage (Debug) + uses: actions/download-artifact@v2 + with: + name: windows-unit-test-coverage-Debug + path: ./code_coverage/unit_tests/windows_unit_tests_debug + + - name: Retrieve Windows Unit Test Coverage (Release) + uses: actions/download-artifact@v2 + with: + name: windows-unit-test-coverage-Release + path: ./code_coverage/unit_tests/windows_unit_tests_release + + - name: Retrieve Windows Integration Test Coverage (Debug, Basic) + uses: actions/download-artifact@v2 + with: + name: windows-integration-test-coverage-Debug-Basic + path: ./code_coverage/integration_tests/windows_integration_tests_debug_basic + + - name: Retrieve Windows Integration Test Coverage (Release, Basic) + uses: actions/download-artifact@v2 + with: + name: windows-integration-test-coverage-Release-Basic + path: ./code_coverage/integration_tests/windows_integration_tests_release_basic + + - name: Retrieve Windows Integration Test Coverage (Debug, System) + uses: actions/download-artifact@v2 + with: + name: windows-integration-test-coverage-Debug-System + path: ./code_coverage/integration_tests/windows_integration_tests_debug_system + + - name: Retrieve Windows Integration Test Coverage (Release, System) + uses: actions/download-artifact@v2 + with: + name: windows-integration-test-coverage-Release-System + path: ./code_coverage/integration_tests/windows_integration_tests_release_system + + - name: Upload Unit Test Coverage to CodeCov + uses: codecov/codecov-action@v1 + with: + directory: ./code_coverage/unit_tests + flags: unittests + fail_ci_if_error: true + + - name: Upload Integration Test Coverage to CodeCov + uses: codecov/codecov-action@v1 + with: + directory: ./code_coverage/integration_tests + flags: integration + fail_ci_if_error: true diff --git a/appveyor.yml b/appveyor.yml index 13d2da0ad0..9303b2b6c8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,8 +2,6 @@ version: '{build}' pull_requests: do_not_increment_build_number: true environment: - TGS4_TEST_TEMP_DIRECTORY: C:/tgs4_test - TGS4_TEST_DATABASE_TYPE: SqlServer TGS4_TEST_DUMP_API_SPEC: yes TGS4_TEST_CONNECTION_STRING: Server=(local)\SQL2017;Initial Catalog=TGS_Test;User ID=sa;Password=Password12! TGS4_TEST_GITHUB_TOKEN: @@ -16,10 +14,8 @@ environment: TGS4_TEST_IRC_CHANNEL: \#botbus TGS4_RELEASE_NOTES_TOKEN: secure: lJNGAXwiB5HlWdthz3K4PetqpTG5IEAyRgKaiKxFMQ8HW8CcOjRtB97B05op7BsK - branches: only: - - dev - master skip_tags: true image: Visual Studio 2019 @@ -53,33 +49,8 @@ build: publish_nuget: true publish_nuget_symbols: true use_snupkg_format: true -test_script: - - OpenCover.Console.exe -returntargetcode -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -c %CONFIGURATION% --logger:trx;LogFileName=results.trx /p:DebugType=full tests/Tgstation.Server.Api.Tests/Tgstation.Server.Api.Tests.csproj" -filter:"+[Tgstation.Server*]* -[Tgstation.Server.Api.Tests*]*" -output:".\api_coverage.xml" -oldstyle - - ps: $wc = New-Object 'System.Net.WebClient' - - ps: $wc.UploadFile("https://ci.appveyor.com/api/testresults/mstest/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\tests\Tgstation.Server.Api.Tests\TestResults\results.trx)) - - OpenCover.Console.exe -returntargetcode -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -c %CONFIGURATION% --logger:trx;LogFileName=results.trx /p:DebugType=full tests/Tgstation.Server.Client.Tests/Tgstation.Server.Client.Tests.csproj" -filter:"+[Tgstation.Server*]* -[Tgstation.Server.Client.Tests*]*" -output:".\client_coverage.xml" -oldstyle - - ps: $wc = New-Object 'System.Net.WebClient' - - ps: $wc.UploadFile("https://ci.appveyor.com/api/testresults/mstest/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\tests\Tgstation.Server.Client.Tests\TestResults\results.trx)) - - OpenCover.Console.exe -returntargetcode -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -c %CONFIGURATION% --logger:trx;LogFileName=results.trx /p:DebugType=full tests/Tgstation.Server.Host.Tests/Tgstation.Server.Host.Tests.csproj" -filter:"+[Tgstation.Server*]* -[Tgstation.Server.Host.Tests*]* -[Tgstation.Server.Host]Tgstation.Server.Host.Database.Migrations*" -output:".\host_coverage.xml" -oldstyle - - ps: $wc = New-Object 'System.Net.WebClient' - - ps: $wc.UploadFile("https://ci.appveyor.com/api/testresults/mstest/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\tests\Tgstation.Server.Host.Tests\TestResults\results.trx)) - - OpenCover.Console.exe -returntargetcode -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -c %CONFIGURATION% --logger:trx;LogFileName=results.trx /p:DebugType=full tests/Tgstation.Server.Host.Console.Tests/Tgstation.Server.Host.Console.Tests.csproj" -filter:"+[Tgstation.Server*]* -[Tgstation.Server.Host.Console.Tests*]*" -output:".\console_coverage.xml" -oldstyle - - ps: $wc = New-Object 'System.Net.WebClient' - - ps: $wc.UploadFile("https://ci.appveyor.com/api/testresults/mstest/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\tests\Tgstation.Server.Host.Console.Tests\TestResults\results.trx)) - - set path=%ProgramFiles(x86)%\Microsoft Visual Studio\2019\TestAgent\Common7\IDE\CommonExtensions\Microsoft\TestWindow;%path% - - vstest.console /logger:trx;LogFileName=results.trx "tests\Tgstation.Server.Host.Service.Tests\bin\%CONFIGURATION%\net472\Tgstation.Server.Host.Service.Tests.dll" /inIsolation /Platform:x64 - - ps: $wc = New-Object 'System.Net.WebClient' - - ps: $wc.UploadFile("https://ci.appveyor.com/api/testresults/mstest/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\TestResults\results.trx)) - - OpenCover.Console.exe -returntargetcode -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -c %CONFIGURATION% --logger:trx;LogFileName=results.trx /p:DebugType=full tests/Tgstation.Server.Host.Watchdog.Tests/Tgstation.Server.Host.Watchdog.Tests.csproj" -filter:"+[Tgstation.Server*]* -[Tgstation.Server.Host.Watchdog.Tests*]*" -output:".\watchdog_coverage.xml" -oldstyle - - ps: $wc = New-Object 'System.Net.WebClient' - - ps: $wc.UploadFile("https://ci.appveyor.com/api/testresults/mstest/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\tests\Tgstation.Server.Host.Watchdog.Tests\TestResults\results.trx)) - - OpenCover.Console.exe -returntargetcode -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -c %CONFIGURATION% --logger:trx;LogFileName=results.trx --logger:console;noprogress=true /p:DebugType=full tests/Tgstation.Server.Tests/Tgstation.Server.Tests.csproj" -filter:"+[Tgstation.Server*]* -[Tgstation.Server.Tests*]* -[Tgstation.Server.Host]Tgstation.Server.Host.Database.Migrations..*" -output:".\server_coverage.xml" -oldstyle - - ps: $wc = New-Object 'System.Net.WebClient' - - ps: $wc.UploadFile("https://ci.appveyor.com/api/testresults/mstest/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\tests\Tgstation.Server.Tests\TestResults\results.trx)) - - lint-openapi -p -c build/OpenApiValidationSettings.json C:/swagger.json after_test: - ps: Move-Item -path C:/swagger.json swagger.json - - ps: build/UploadCoverage.ps1 #host updater - dotnet publish src/Tgstation.Server.Host/Tgstation.Server.Host.csproj -o artifacts/ServerHost -c %CONFIGURATION% #console diff --git a/build/UploadCoverage.ps1 b/build/UploadCoverage.ps1 deleted file mode 100644 index a74244feee..0000000000 --- a/build/UploadCoverage.ps1 +++ /dev/null @@ -1,7 +0,0 @@ -codecov -f api_coverage.xml --flag unittests -codecov -f client_coverage.xml --flag unittests -codecov -f host_coverage.xml --flag unittests -codecov -f console_coverage.xml --flag unittests -codecov -f watchdog_coverage.xml --flag unittests -#codecov -f service.coveragexml --flag unittests -codecov -f server_coverage.xml --flag integration diff --git a/build/coverlet.runsettings b/build/coverlet.runsettings new file mode 100644 index 0000000000..783e8323cc --- /dev/null +++ b/build/coverlet.runsettings @@ -0,0 +1,13 @@ + + + + + + + opencover + false + + + + + diff --git a/src/Tgstation.Server.Host/Components/Byond/ByondManager.cs b/src/Tgstation.Server.Host/Components/Byond/ByondManager.cs index 5e1e0312f5..72ea830c82 100644 --- a/src/Tgstation.Server.Host/Components/Byond/ByondManager.cs +++ b/src/Tgstation.Server.Host/Components/Byond/ByondManager.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; @@ -257,7 +257,7 @@ namespace Tgstation.Server.Host.Components.Byond var versionKey = VersionKey(versionToUse, true); var binPathForVersion = ioManager.ConcatPath(versionKey, BinPath); - logger.LogTrace("Creating ByondExecutableLock lock for version {0}", requiredVersion); + logger.LogTrace("Creating ByondExecutableLock lock for version {0}", versionToUse); return new ByondExecutableLock( ioManager, semaphore, diff --git a/src/Tgstation.Server.Host/System/PosixProcessFeatures.cs b/src/Tgstation.Server.Host/System/PosixProcessFeatures.cs index f808e588de..293fc880fe 100644 --- a/src/Tgstation.Server.Host/System/PosixProcessFeatures.cs +++ b/src/Tgstation.Server.Host/System/PosixProcessFeatures.cs @@ -1,10 +1,7 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Mono.Unix; using Mono.Unix.Native; using System; -using System.Globalization; -using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; using Tgstation.Server.Api.Models; @@ -79,29 +76,8 @@ namespace Tgstation.Server.Host.System } /// - public async Task GetExecutingUsername(global::System.Diagnostics.Process process, CancellationToken cancellationToken) - { - if (process == null) - throw new ArgumentNullException(nameof(process)); - - // Need to read /proc/[pid]/status - // http://man7.org/linux/man-pages/man5/proc.5.html - // https://unix.stackexchange.com/questions/102676/why-is-uid-information-not-in-proc-x-stat - var pid = process.Id; - var statusFile = ioManager.ConcatPath("/proc", pid.ToString(CultureInfo.InvariantCulture), "status"); - var statusBytes = await ioManager.ReadAllBytes(statusFile, cancellationToken).ConfigureAwait(false); - var statusText = Encoding.UTF8.GetString(statusBytes); - var splits = statusText.Split('\n', StringSplitOptions.RemoveEmptyEntries); - var entry = splits.FirstOrDefault(x => x.Trim().StartsWith("Uid:", StringComparison.Ordinal)); - if (entry == default) - return "UNKNOWN"; - - return entry - .Substring(4) - .Split(' ', StringSplitOptions.RemoveEmptyEntries) - .FirstOrDefault(x => !String.IsNullOrWhiteSpace(x)) - ?? "UNPARSABLE"; - } + public Task GetExecutingUsername(global::System.Diagnostics.Process process, CancellationToken cancellationToken) + => throw new NotSupportedException(); /// public async Task CreateDump(global::System.Diagnostics.Process process, string outputFile, CancellationToken cancellationToken) diff --git a/tests/DMAPI/BasicOperation/Test.dm b/tests/DMAPI/BasicOperation/Test.dm index a603a099be..066c9eceac 100644 --- a/tests/DMAPI/BasicOperation/Test.dm +++ b/tests/DMAPI/BasicOperation/Test.dm @@ -19,7 +19,9 @@ var/datum/tgs_version/dmapi_version = new /datum/tgs_version(TGS_DMAPI_VERSION) if(!active_version.Equals(dmapi_version)) text2file("DMAPI version [TGS_DMAPI_VERSION] does not match active API version [active_version.raw_parameter]", "test_fail_reason.txt") - + + world.log << "sleep2" + sleep(50) world.log << "Terminating..." world.TgsEndProcess() diff --git a/tests/Tgstation.Server.Api.Tests/Tgstation.Server.Api.Tests.csproj b/tests/Tgstation.Server.Api.Tests/Tgstation.Server.Api.Tests.csproj index 81b42afb96..4ac3e5c0c5 100644 --- a/tests/Tgstation.Server.Api.Tests/Tgstation.Server.Api.Tests.csproj +++ b/tests/Tgstation.Server.Api.Tests/Tgstation.Server.Api.Tests.csproj @@ -8,9 +8,9 @@ - - runtime; build; native; contentfiles; analyzers; buildtransitive + all + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/Tgstation.Server.Client.Tests/Tgstation.Server.Client.Tests.csproj b/tests/Tgstation.Server.Client.Tests/Tgstation.Server.Client.Tests.csproj index 0585c62165..1ce9b9982d 100644 --- a/tests/Tgstation.Server.Client.Tests/Tgstation.Server.Client.Tests.csproj +++ b/tests/Tgstation.Server.Client.Tests/Tgstation.Server.Client.Tests.csproj @@ -8,9 +8,9 @@ - - runtime; build; native; contentfiles; analyzers; buildtransitive + all + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/Tgstation.Server.Host.Console.Tests/Tgstation.Server.Host.Console.Tests.csproj b/tests/Tgstation.Server.Host.Console.Tests/Tgstation.Server.Host.Console.Tests.csproj index a53fb435d8..c37b05c82f 100644 --- a/tests/Tgstation.Server.Host.Console.Tests/Tgstation.Server.Host.Console.Tests.csproj +++ b/tests/Tgstation.Server.Host.Console.Tests/Tgstation.Server.Host.Console.Tests.csproj @@ -8,9 +8,9 @@ - - runtime; build; native; contentfiles; analyzers; buildtransitive + all + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/Tgstation.Server.Host.Service.Tests/Tgstation.Server.Host.Service.Tests.csproj b/tests/Tgstation.Server.Host.Service.Tests/Tgstation.Server.Host.Service.Tests.csproj index 68cbe52649..c47523526f 100644 --- a/tests/Tgstation.Server.Host.Service.Tests/Tgstation.Server.Host.Service.Tests.csproj +++ b/tests/Tgstation.Server.Host.Service.Tests/Tgstation.Server.Host.Service.Tests.csproj @@ -14,9 +14,9 @@ - - runtime; build; native; contentfiles; analyzers; buildtransitive + all + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/Tgstation.Server.Host.Tests/System/TestProcessFeatures.cs b/tests/Tgstation.Server.Host.Tests/System/TestProcessFeatures.cs index cfa6173cce..aca9cae1f1 100644 --- a/tests/Tgstation.Server.Host.Tests/System/TestProcessFeatures.cs +++ b/tests/Tgstation.Server.Host.Tests/System/TestProcessFeatures.cs @@ -27,8 +27,8 @@ namespace Tgstation.Server.Host.System.Tests [TestMethod] public async Task TestGetUsername() { - if (!String.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("TRAVIS"))) - Assert.Inconclusive("This test doesn't work on TRAVIS CI!"); + if (!new PlatformIdentifier().IsWindows) + Assert.Inconclusive("This test is buggy on linux and not required"); var username = await features.GetExecutingUsername(global::System.Diagnostics.Process.GetCurrentProcess(), default); Assert.IsTrue(username.Contains(Environment.UserName), $"Exepcted a string containing \"{Environment.UserName}\", got \"{username}\""); diff --git a/tests/Tgstation.Server.Host.Tests/Tgstation.Server.Host.Tests.csproj b/tests/Tgstation.Server.Host.Tests/Tgstation.Server.Host.Tests.csproj index 243e758b8c..60aba1cdb0 100644 --- a/tests/Tgstation.Server.Host.Tests/Tgstation.Server.Host.Tests.csproj +++ b/tests/Tgstation.Server.Host.Tests/Tgstation.Server.Host.Tests.csproj @@ -8,9 +8,9 @@ - - runtime; build; native; contentfiles; analyzers; buildtransitive + all + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/Tgstation.Server.Host.Watchdog.Tests/Tgstation.Server.Host.Watchdog.Tests.csproj b/tests/Tgstation.Server.Host.Watchdog.Tests/Tgstation.Server.Host.Watchdog.Tests.csproj index 0c9e91bb71..c4cfd002c5 100644 --- a/tests/Tgstation.Server.Host.Watchdog.Tests/Tgstation.Server.Host.Watchdog.Tests.csproj +++ b/tests/Tgstation.Server.Host.Watchdog.Tests/Tgstation.Server.Host.Watchdog.Tests.csproj @@ -14,9 +14,9 @@ - - runtime; build; native; contentfiles; analyzers; buildtransitive + all + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/Tgstation.Server.Tests/Instance/DeploymentTest.cs b/tests/Tgstation.Server.Tests/Instance/DeploymentTest.cs index 6e63bf7b55..7772e32343 100644 --- a/tests/Tgstation.Server.Tests/Instance/DeploymentTest.cs +++ b/tests/Tgstation.Server.Tests/Instance/DeploymentTest.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; using Tgstation.Server.Api.Models; using Tgstation.Server.Client.Components; +using Tgstation.Server.Host.System; namespace Tgstation.Server.Tests.Instance { @@ -32,6 +33,12 @@ namespace Tgstation.Server.Tests.Instance await repositoryTask; // by alphabetization rules, it should discover api_free here + if (!new PlatformIdentifier().IsWindows) + await dreamMakerClient.Update(new DreamMaker + { + ProjectName = "tests/DMAPI/ApiFree/api_free" + }, cancellationToken); + var updatedDD = await dreamDaemonClient.Update(new DreamDaemon { StartupTimeout = 5 diff --git a/tests/Tgstation.Server.Tests/Instance/WatchdogTest.cs b/tests/Tgstation.Server.Tests/Instance/WatchdogTest.cs index f7fce8c6e3..8af1be7c16 100644 --- a/tests/Tgstation.Server.Tests/Instance/WatchdogTest.cs +++ b/tests/Tgstation.Server.Tests/Instance/WatchdogTest.cs @@ -1,4 +1,4 @@ -using Byond.TopicSender; +using Byond.TopicSender; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -437,7 +437,7 @@ namespace Tgstation.Server.Tests.Instance var result = await bts.SendTopic(IPAddress.Loopback, "tgs_integration_test_special_tactics=1", 1337, cancellationToken); Assert.AreEqual("ack", result.StringData); - await Task.Delay(10000, cancellationToken); + await Task.Delay(20000, cancellationToken); } catch (OperationCanceledException) { diff --git a/tests/Tgstation.Server.Tests/IntegrationTest.cs b/tests/Tgstation.Server.Tests/IntegrationTest.cs index f2669bcfc9..7efaace32c 100644 --- a/tests/Tgstation.Server.Tests/IntegrationTest.cs +++ b/tests/Tgstation.Server.Tests/IntegrationTest.cs @@ -176,7 +176,10 @@ namespace Tgstation.Server.Tests using var server = new TestingServer(); using var hardTimeoutCts = new CancellationTokenSource(); - hardTimeoutCts.CancelAfter(new TimeSpan(0, 9, 45)); + + var maximumTestDuration = new TimeSpan(0, 12, 0); + + hardTimeoutCts.CancelAfter(maximumTestDuration - new TimeSpan(0, 0, 15)); var hardTimeoutCancellationToken = hardTimeoutCts.Token; hardTimeoutCancellationToken.Register(() => { @@ -184,7 +187,7 @@ namespace Tgstation.Server.Tests }); using var softTimeoutCts = CancellationTokenSource.CreateLinkedTokenSource(hardTimeoutCancellationToken); - softTimeoutCts.CancelAfter(new TimeSpan(0, 9, 15)); + softTimeoutCts.CancelAfter(maximumTestDuration - new TimeSpan(0, 0, 45)); var softTimeoutCancellationToken = softTimeoutCts.Token; bool tooLateForSoftTimeout = false; softTimeoutCancellationToken.Register(() => diff --git a/tests/Tgstation.Server.Tests/Tgstation.Server.Tests.csproj b/tests/Tgstation.Server.Tests/Tgstation.Server.Tests.csproj index 6f8f253315..ebea335bde 100644 --- a/tests/Tgstation.Server.Tests/Tgstation.Server.Tests.csproj +++ b/tests/Tgstation.Server.Tests/Tgstation.Server.Tests.csproj @@ -8,9 +8,9 @@ - - runtime; build; native; contentfiles; analyzers; buildtransitive + all + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tgstation-server.sln b/tgstation-server.sln index 39cb8ff54e..aff47c7971 100644 --- a/tgstation-server.sln +++ b/tgstation-server.sln @@ -156,7 +156,6 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BasicOperation", "BasicOperation", "{F32B9514-AAD9-429D-841A-ED810FC2598C}" ProjectSection(SolutionItems) = preProject tests\DMAPI\BasicOperation\basic_operation_test.dme = tests\DMAPI\BasicOperation\basic_operation_test.dme - tests\DMAPI\BasicOperation\build_byond.sh = tests\DMAPI\BasicOperation\build_byond.sh tests\DMAPI\BasicOperation\Config.dm = tests\DMAPI\BasicOperation\Config.dm tests\DMAPI\BasicOperation\Test.dm = tests\DMAPI\BasicOperation\Test.dm EndProjectSection