From 9173c964c0596df41997e46f932f53b8b61572b3 Mon Sep 17 00:00:00 2001 From: Ben Henning Date: Thu, 11 Feb 2021 16:06:05 -0800 Subject: [PATCH] Fix part of #1861: [RunAllTests] Update Bazel CI workflow to run all Oppia tests (#1904) * Update Bazel CI workflow Build all Oppia targets in Bazel rather than just the binary target. * Update main.yml Reset the workflow name so that it doesn't need to be renamed in GitHub settings. * Introduce remote caching in Bazel. This uses a remote storage service with a local file encrypted using git-secret to act as the authentication key for Bazel to read & write artifacts to the service for caching purposes. * Add debug line. * Disable workflows + fix debug line. * More debugging. * More debugging. * Work around GitHub hiding secret since we're debugging. * Use base64 to properly encode newlines in GPG keys. * Remove debug lines before changing back to correct GPG key. * Switch to production key. * Fix env variable reference. Lock-down actions workflows via codeowners. * Install git-secret to default location. * Add details. Debug $PATH. * Fix pathing for git-secret. * Dummy commit to re-trigger actions. * Undo commit to see if this one shows up. * Fix git-secret pathing try 2. * New commit to re-trigger action. * Path debugging. * Workaround to get GitHub to show changes. * Update runner to use Bash. Reference: https://github.community/t/github-path-does-not-add-to-the-path/143992. * Restore binary-only build, other builds, and introduce new workflow for building all Bazel targets. * Remove debug lines. * Rename & remove keep_going. * Compute matrix containing all test targets. This will allow us to distribute parallelization responsibilities partly to GitHub actions to hopefully have slightly better throughput. See https://github.blog/changelog/2020-04-15-github-actions-new-workflow-features/ for reference on how this mechanism works. * Simplify, fix some issues, and debug instead of run. * Turn on actual testing. * Lower parallelization since GitHub started cancelling tasks. * Try 15 parallel jobs instead. * Turn off fail-fast instead of limiting parallelization. Fail fast seems to be the reason why the tests aren't completing, not quota (since if too many jobs are started, the extras should just be queued until resources open up). * Simplify workflow & allow it to be required. Also, introduce bazelrc file to simplify the CI CLIs interacting with Bazel. * Add test change to investigate computing affected targets. * Another test change to compute affected targets. * Update workflow to use future script compute_affected_tests.sh. Also, ignore Bazel directories in Git (to ease local development). * Add script to compute affected targets. This script is primarily meant to be used for CI. * Execute tests in parallel to build. This creates a new job to compute affected targets alongside the build. This may result in the initial build being a bit slower, but subsequent commits should be fast if remote caching is enabled. This will also result in better performance for forks that can't use remote caching. * Script clean-ups. Also, re-trigger actions. * Try to ensure develop branch is available for change analysis. * Add automatic workflow cancellation. Also, add support to explicitly run all tests if '[RunAllTests]' is in the PR title. * Attempt to make conditional matrix computation work. * Remove join since it was used incorrectly. * Add support for testing when Bazel, BUILD, and WORKSPACE files change. One consequence is the current Bazel file structure is very tight, so any changes will likely run the whole suite. This will get better over time. Also, show test logs for all test runs. * Fix broken tests by adding missing dep library. * Finalize PR. 1. Expand codeowners to include all workflow files. 2. Remove test comments in Kotlin files. 3. Re-enable all workflows. 4. Attempt to fix tests broken on actions but not locally by adding more thread synchronization points. * Lint fix. * Fix timing issues and JDK 9-specific regression. See comment thread in #1904 for more context. * Restore workflow names + introduce test check. The new test check workflow will be a static job that will be required to pass. One failing test is being introduced to verify that this check fails as expected. The original workflow names are being restored so that they don't need to be renamed in GitHub settings (since that would introduce a discontinuity in CI service & require multiple migratiaon PRs to fix). * Update StateFragmentLocalTest.kt Remove fail-on-purpose test since it verified what it needed to: the new test status check job is working as expected. * Address reviewer comments. * Fix most tests broken in Bazel after syncing. * Gitignore + fix broken test. The test failure here only happens when using JDK9+ (which doesn't happen in the Gradle world, or on CI). The .gitignore is since we can't yet specify a .bazelproject in a shareable way. * Lint fixes. * Post-merge clean-up. * Fix broken post-merge test. * Remove unnecessary codeowners per earlier codeowners setup. * Fix ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest. * Disable image region selection tests. These tests can't correctly pass on Robolectric until #1611 is fixed, so disabling them for the time being to avoid the image loading flake happening on CI (but not locally). Note that chances are a fix will still be needed for the flake, but that can be addressed later. * Disable 2 previously missed tests. * Post-merge lint fix. * Add missing dependency. Verified all tests build & pass both for JDK 9 & 11. Hopefully they will work as expected on CI. * Add missing codeowners for new files. * Post-merge fixes. This fixes some tests that were broken after recent PRs, and fixed a visibility error introduced in #2663. * Move Bazel tests to new workflow. This will make it easier to restart failures without having to also restart unrelated tests. --- .github/CODEOWNERS | 4 + .github/workflows/main.yml | 58 +++++++-- .github/workflows/unit_tests.yml | 118 ++++++++++++++++++ .github/workflows/workflow_canceller.yml | 28 +++++ .gitignore | 5 + .gitsecret/keys/pubring.kbx | Bin 0 -> 3939 bytes .gitsecret/keys/pubring.kbx~ | Bin 0 -> 1980 bytes .gitsecret/keys/trustdb.gpg | Bin 0 -> 1200 bytes .gitsecret/paths/mapping.cfg | 1 + .../res/layout-land/submitted_answer_item.xml | 1 + .../main/res/layout/submitted_answer_item.xml | 1 + .../app/player/state/StateFragmentTest.kt | 12 +- .../player/state/StateFragmentLocalTest.kt | 114 ++++++++++++++--- ...kflow-remote-cache-credentials.json.secret | Bin 0 -> 2543 bytes domain/BUILD.bazel | 54 +++++--- ...enominatorEqualToRuleClassifierProvider.kt | 3 +- ...artExactlyEqualToRuleClassifierProvider.kt | 3 +- ...ntegerPartEqualToRuleClassifierProvider.kt | 3 +- ...sNoFractionalPartRuleClassifierProvider.kt | 3 +- ...sNumeratorEqualToRuleClassifierProvider.kt | 3 +- ...AndInSimplestFormRuleClassifierProvider.kt | 3 +- ...putIsEquivalentToRuleClassifierProvider.kt | 3 +- ...tIsExactlyEqualToRuleClassifierProvider.kt | 3 +- ...nputIsGreaterThanRuleClassifierProvider.kt | 3 +- ...onInputIsLessThanRuleClassifierProvider.kt | 3 +- ...tainsAtLeastOneOfRuleClassifierProvider.kt | 3 +- ...ntainAtLeastOneOfRuleClassifierProvider.kt | 3 +- ...ectionInputEqualsRuleClassifierProvider.kt | 3 +- ...tIsProperSubsetOfRuleClassifierProvider.kt | 3 +- ...ithUnitsIsEqualToRuleClassifierProvider.kt | 3 +- ...itsIsEquivalentToRuleClassifierProvider.kt | 3 +- ...aterThanOrEqualToRuleClassifierProvider.kt | 3 +- ...nputIsGreaterThanRuleClassifierProvider.kt | 3 +- ...nclusivelyBetweenRuleClassifierProvider.kt | 3 +- ...LessThanOrEqualToRuleClassifierProvider.kt | 3 +- ...icInputIsLessThanRuleClassifierProvider.kt | 3 +- ...IsWithinToleranceRuleClassifierProvider.kt | 3 +- .../RatioInputEqualsRuleClassifierProvider.kt | 3 +- ...sNumberOfTermsEqualToClassifierProvider.kt | 3 +- ...InputIsEquivalentRuleClassifierProvider.kt | 3 +- ...seSensitiveEqualsRuleClassifierProvider.kt | 3 +- ...tInputFuzzyEqualsRuleClassifierProvider.kt | 3 +- ...xtInputStartsWithRuleClassifierProvider.kt | 3 +- .../loguploader/FakeLogUploader.kt | 35 ++++++ .../domain/oppialogger/OppiaLoggerTest.kt | 15 +-- .../analytics/AnalyticsControllerTest.kt | 16 +-- .../LogUploadWorkManagerInitializerTest.kt | 38 +----- .../loguploader/LogUploadWorkerTest.kt | 35 ++++-- scripts/compute_affected_tests.sh | 77 ++++++++++++ testing/BUILD.bazel | 9 ++ third_party/BUILD.bazel | 1 + 51 files changed, 572 insertions(+), 134 deletions(-) create mode 100644 .github/workflows/unit_tests.yml create mode 100644 .github/workflows/workflow_canceller.yml create mode 100644 .gitsecret/keys/pubring.kbx create mode 100644 .gitsecret/keys/pubring.kbx~ create mode 100644 .gitsecret/keys/trustdb.gpg create mode 100644 .gitsecret/paths/mapping.cfg create mode 100644 config/oppia-dev-workflow-remote-cache-credentials.json.secret create mode 100644 domain/src/main/java/org/oppia/android/domain/testing/oppialogger/loguploader/FakeLogUploader.kt create mode 100755 scripts/compute_affected_tests.sh diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 54596a3ba2a..5c57263b1c7 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -45,6 +45,10 @@ gradlew.bat @BenHenning /.github/*.md @BenHenning /.github/ISSUE_TEMPLATE @BenHenning +# Git secret files & related configurations. +/.gitsecret/ @BenHenning +*.secret @BenHenning + # CI configuration. /.github/workflows/ @BenHenning diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f2f4453ae59..689631594ec 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,7 +17,7 @@ on: jobs: linters: name: Lint Tests - runs-on: ${{ matrix.os }} + runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-18.04] @@ -65,7 +65,7 @@ jobs: robolectric_tests: name: Robolectric Tests (Non-App Modules) - runs-on: ${{ matrix.os }} + runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-18.04] @@ -122,7 +122,7 @@ jobs: app_tests: name: Robolectric Tests - App Module (Non-Flaky) - runs-on: ${{ matrix.os }} + runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-18.04] @@ -158,32 +158,66 @@ jobs: os: [ubuntu-18.04] steps: - uses: actions/checkout@v2 - - name: Set up bazel - uses: jwlawson/actions-setup-bazel@v1 - with: - bazel-version: '3.4.1' - name: Clone Oppia Bazel run: git clone https://github.com/oppia/bazel.git $HOME/oppia-bazel - name: Set up JDK 9 uses: actions/setup-java@v1 with: java-version: 9 - - name: Extract Android Tools + - name: Extract Android tools run: | mkdir -p $GITHUB_WORKSPACE/tmp/android_tools cd $HOME/oppia-bazel unzip bazel-tools.zip tar -xf $HOME/oppia-bazel/android_tools.tar.gz -C $GITHUB_WORKSPACE/tmp/android_tools - - name: Unzip Bazel Binary and Build Oppia + # See https://git-secret.io/installation for details on installing git-secret. Note that the + # apt-get method isn't used since it's much slower to update & upgrade apt before installation + # versus just directly cloning & installing the project. Further, the specific version + # shouldn't matter since git-secret relies on a future-proof storage mechanism for secrets. + # This also uses a different directory to install git-secret to avoid requiring root access + # when running the git secret command. + - name: Install git-secret (non-fork only) + if: github.repository == 'oppia/oppia-android' + shell: bash + run: | + cd $HOME + mkdir -p $HOME/gitsecret + git clone https://github.com/sobolevn/git-secret.git git-secret + cd git-secret && make build + PREFIX="$HOME/gitsecret" make install + echo "$HOME/gitsecret" >> $GITHUB_PATH + echo "$HOME/gitsecret/bin" >> $GITHUB_PATH + - name: Decrypt secrets (non-fork only) + if: github.repository == 'oppia/oppia-android' + env: + GIT_SECRET_GPG_PRIVATE_KEY: ${{ secrets.GIT_SECRET_GPG_PRIVATE_KEY }} + run: | + cd $HOME + # NOTE TO DEVELOPERS: Make sure to never print this key directly to stdout! + echo $GIT_SECRET_GPG_PRIVATE_KEY | base64 --decode > ./git_secret_private_key.gpg + gpg --import ./git_secret_private_key.gpg + cd $GITHUB_WORKSPACE + git secret reveal + - name: Unzip Bazel binary run: | cd $HOME/oppia-bazel unzip bazel-build.zip cd $GITHUB_WORKSPACE chmod a+x $HOME/oppia-bazel/bazel - $HOME/oppia-bazel/bazel build //:oppia --android_databinding_use_v3_4_args --experimental_android_databinding_v2 --override_repository=android_tools=$GITHUB_WORKSPACE/tmp/android_tools --java_header_compilation=false --noincremental_dexing --define=android_standalone_dexing_tool=d8_compat_dx - cp $GITHUB_WORKSPACE/bazel-bin/oppia.apk /home/runner/work/oppia-android/oppia-android/ + # Note that caching only works on non-forks. + - name: Build Oppia binary (with caching, non-fork only) + if: github.repository == 'oppia/oppia-android' + env: + BAZEL_REMOTE_CACHE_URL: ${{ secrets.BAZEL_REMOTE_CACHE_URL }} + run: | + $HOME/oppia-bazel/bazel build --override_repository=android_tools=$GITHUB_WORKSPACE/tmp/android_tools --remote_http_cache=$BAZEL_REMOTE_CACHE_URL --google_credentials=./config/oppia-dev-workflow-remote-cache-credentials.json -- //:oppia + - name: Build Oppia binary (without caching, fork only) + if: github.repository != 'oppia/oppia-android' + run: | + $HOME/oppia-bazel/bazel build --override_repository=android_tools=$GITHUB_WORKSPACE/tmp/android_tools -- //:oppia + - name: Copy Oppia APK for uploading + run: cp $GITHUB_WORKSPACE/bazel-bin/oppia.apk /home/runner/work/oppia-android/oppia-android/ - uses: actions/upload-artifact@v2 with: name: oppia-bazel-apk path: /home/runner/work/oppia-android/oppia-android/oppia.apk - - uses: actions/checkout@v2 diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml new file mode 100644 index 00000000000..fa5a270d9e9 --- /dev/null +++ b/.github/workflows/unit_tests.yml @@ -0,0 +1,118 @@ +name: Unit Tests (Robolectric - Bazel) + +# Controls when the action will run. Triggers the workflow on pull request +# events or push events in the develop branch. +on: + workflow_dispatch: + pull_request: + push: + branches: + # Push events on develop branch + - develop + +jobs: + bazel_compute_affected_targets: + name: Compute affected tests + runs-on: ubuntu-18.04 + outputs: + matrix: ${{ steps.compute-test-matrix-from-affected.outputs.matrix || steps.compute-test-matrix-from-all.outputs.matrix }} + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Clone Oppia Bazel + run: git clone https://github.com/oppia/bazel.git $HOME/oppia-bazel + - name: Unzip Bazel binary + run: | + cd $HOME/oppia-bazel + unzip bazel-build.zip + cd $GITHUB_WORKSPACE + chmod a+x $HOME/oppia-bazel/bazel + - name: Compute test matrix based on affected targets + id: compute-test-matrix-from-affected + if: "!contains(github.event.pull_request.title, '[RunAllTests]')" + # https://unix.stackexchange.com/a/338124 for reference on creating a JSON-friendly + # comma-separated list of test targets for the matrix. + run: | + TEST_TARGET_LIST=$(bash ./scripts/compute_affected_tests.sh $HOME/oppia-bazel/bazel | sed 's/^\|$/"/g' | paste -sd, -) + echo "Affected tests (note that this might be all tests if on the develop branch): $TEST_TARGET_LIST" + echo "::set-output name=matrix::{\"test-target\":[$TEST_TARGET_LIST]}" + - name: Compute test matrix based on all tests + id: compute-test-matrix-from-all + if: "contains(github.event.pull_request.title, '[RunAllTests]')" + run: | + TEST_TARGET_LIST=$($HOME/oppia-bazel/bazel query "kind(test, //...)" | sed 's/^\|$/"/g' | paste -sd, -) + echo "Affected tests (note that this might be all tests if on the develop branch): $TEST_TARGET_LIST" + echo "::set-output name=matrix::{\"test-target\":[$TEST_TARGET_LIST]}" + + bazel_run_test: + name: Run Bazel Test + needs: bazel_compute_affected_targets + runs-on: ubuntu-18.04 + strategy: + fail-fast: false + matrix: ${{fromJson(needs.bazel_compute_affected_targets.outputs.matrix)}} + steps: + - uses: actions/checkout@v2 + - name: Clone Oppia Bazel + run: git clone https://github.com/oppia/bazel.git $HOME/oppia-bazel + - name: Set up JDK 9 + uses: actions/setup-java@v1 + with: + java-version: 9 + - name: Extract Android tools + run: | + mkdir -p $GITHUB_WORKSPACE/tmp/android_tools + cd $HOME/oppia-bazel + unzip bazel-tools.zip + tar -xf $HOME/oppia-bazel/android_tools.tar.gz -C $GITHUB_WORKSPACE/tmp/android_tools + # See explanation in bazel_build_app for how this is installed. + - name: Install git-secret (non-fork only) + if: github.repository == 'oppia/oppia-android' + shell: bash + run: | + cd $HOME + mkdir -p $HOME/gitsecret + git clone https://github.com/sobolevn/git-secret.git git-secret + cd git-secret && make build + PREFIX="$HOME/gitsecret" make install + echo "$HOME/gitsecret" >> $GITHUB_PATH + echo "$HOME/gitsecret/bin" >> $GITHUB_PATH + - name: Decrypt secrets (non-fork only) + if: github.repository == 'oppia/oppia-android' + env: + GIT_SECRET_GPG_PRIVATE_KEY: ${{ secrets.GIT_SECRET_GPG_PRIVATE_KEY }} + run: | + cd $HOME + # NOTE TO DEVELOPERS: Make sure to never print this key directly to stdout! + echo $GIT_SECRET_GPG_PRIVATE_KEY | base64 --decode > ./git_secret_private_key.gpg + gpg --import ./git_secret_private_key.gpg + cd $GITHUB_WORKSPACE + git secret reveal + - name: Unzip Bazel binary + run: | + cd $HOME/oppia-bazel + unzip bazel-build.zip + cd $GITHUB_WORKSPACE + chmod a+x $HOME/oppia-bazel/bazel + - name: Run Oppia Test (with caching, non-fork only) + if: github.repository == 'oppia/oppia-android' + env: + BAZEL_REMOTE_CACHE_URL: ${{ secrets.BAZEL_REMOTE_CACHE_URL }} + run: $HOME/oppia-bazel/bazel test --override_repository=android_tools=$GITHUB_WORKSPACE/tmp/android_tools --remote_http_cache=$BAZEL_REMOTE_CACHE_URL --google_credentials=./config/oppia-dev-workflow-remote-cache-credentials.json -- ${{ matrix.test-target }} + - name: Run Oppia Test (without caching, fork only) + if: github.repository != 'oppia/oppia-android' + env: + BAZEL_REMOTE_CACHE_URL: ${{ secrets.BAZEL_REMOTE_CACHE_URL }} + run: $HOME/oppia-bazel/bazel test --override_repository=android_tools=$GITHUB_WORKSPACE/tmp/android_tools -- ${{ matrix.test-target }} + + # Reference: https://github.community/t/127354/7. + check_test_results: + name: Check Bazel Test Results + needs: bazel_run_test + if: ${{ always() }} + runs-on: ubuntu-18.04 + steps: + - name: Check tests passed + if: ${{ needs.bazel_run_test.result != 'success' }} + run: exit 1 diff --git a/.github/workflows/workflow_canceller.yml b/.github/workflows/workflow_canceller.yml new file mode 100644 index 00000000000..fd6ac56313a --- /dev/null +++ b/.github/workflows/workflow_canceller.yml @@ -0,0 +1,28 @@ +name: Automatic Workflow Canceller + +# This workflow should be triggered in one of three situations: +# 1. Manual workflow dispatch via https://github.com/oppia/oppia-android/actions. +# 2. Upon creation of a PR & updates to that PR. +# 3. Whenever the develop branch is changed (e.g. after a PR is merged). +# +# Note that the action being used here automatically accounts for the current branch & the commit +# hash of the tip of the branch to ensure it doesn't cancel previous workflows that aren't related +# to the branch being evaluated. +on: + workflow_dispatch: + pull_request: + push: + branches: + # Push events on develop branch + - develop + +jobs: + cancel: + name: Cancel Previous Runs + runs-on: ubuntu-18.04 + steps: + # See https://github.com/styfle/cancel-workflow-action for details on this workflow. + - uses: styfle/cancel-workflow-action@0.6.0 + with: + workflow_id: main.yml + access_token: ${{ github.token }} diff --git a/.gitignore b/.gitignore index 76abf6584c3..7575c3465f8 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,8 @@ utility/build gradle gradlew gradlew.bat +.gitsecret/keys/random_seed +!*.secret +config/oppia-dev-workflow-remote-cache-credentials.json +bazel-* +.bazelproject diff --git a/.gitsecret/keys/pubring.kbx b/.gitsecret/keys/pubring.kbx new file mode 100644 index 0000000000000000000000000000000000000000..8727b699585657656d91e6509e24e6007522b945 GIT binary patch literal 3939 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�)-m94x}b%+B-&0bu52XJZAk z2y(Eqae^U2U?vb)31jtlsWFYh^{q2mCm!rN-LK@?*eV#?^Uk(t&3 z#Wziz4Tf*ThO`LJT2q$g1JVXc<>7a+0SzOxSKH^)-CaEA@&0s(95=4a|aqRCITs)9^&RwMgf z42$i-l&fp3Y)?%JZ0}sw*i;}y7FBEs&Z&*vFsqPt7~Dh6y&e$8rGsHzLBVy>Iu^l9 zU4-5|tAC*1NYu5$wY^s+4b}++p`Nkyd6=94lq6H&tvk6Rq0+@LK0sBm08B^G02=>; zY?kaNu@c01?0u(&amSf!K!H)ir(z9?V)jefKvJiA^9Am0*!YJADIC^1NnXpja1e3k z1*++aG$WI%{}uubWq&l69LP; z4-2+lA)7|aAKut=NtWy%*%hNQ%6K{rYlb?J{w;Q-HoH6G0v9eBguF^T?Tg29IBilX zn+ZAkfKimimiJuCeIynolU)7U!W{kBKI$MSZUlStW2(ywReXhlHS=;b2f9Sg!{ut) zAl+VzzZ|!=L?NGhyE(!zj;U$uQB>v$?X`SFBIeF>pw~_+316PW!w)+ec}Ty3#$2*mfJjQwp`W8xRByI-;s?2wLqXpxXJttZd@n0{Wn(Wg`9`T!mfvPBIewd zZ-0*?Lf{uAiyj>&rBF!yQ?4%91Yz3D*2L)iY3Oa0g~b-4FbMiEPg?&~6vaW3fRXyh zU(d8yu1S+c`ZLVCTb{Sx+&~=an-(SVTygs2>gXIa3A$I#+8#z0SMwMduACwXVcnOo zTV>x&q<-hUR=42OE?S%isxn6Kw8@4jJzc4^zd9>y&o2=v!U`L9^XDwmDC{*}u!ak= zmhV<>4VaRI^Yo|yHu|h!vg)`-={u4!oI+MqS|lj~?)mx~4q+Vhb-+XFIZkFYIX}eTKCqFIpl}Hk2=IY%FNOv+Apyn;$4g@@RVCmL9uk+aXdx4O6}Nne!aX9h@tY^Zp27bHyBLWd~moB zSPQaFi%>f4ol0$1QJO{}zRC&h($ literal 0 HcmV?d00001 diff --git a/.gitsecret/keys/trustdb.gpg b/.gitsecret/keys/trustdb.gpg new file mode 100644 index 0000000000000000000000000000000000000000..59fe4e06e4007254bfb5639d1d9a827cca7f6d07 GIT binary patch literal 1200 zcmZQfFGy!*W@Ke#Vql2h+8@Dy9WZiX7sn7CRfiEIV1dza84VXu2#lr!%F+P<`kw@C literal 0 HcmV?d00001 diff --git a/.gitsecret/paths/mapping.cfg b/.gitsecret/paths/mapping.cfg new file mode 100644 index 00000000000..75e37c7661f --- /dev/null +++ b/.gitsecret/paths/mapping.cfg @@ -0,0 +1 @@ +config/oppia-dev-workflow-remote-cache-credentials.json:c02f95d3829f9a7fb3757170ade432efa43d562d2e7c208372ec9d0f4a45da1a diff --git a/app/src/main/res/layout-land/submitted_answer_item.xml b/app/src/main/res/layout-land/submitted_answer_item.xml index 913916b4a95..a746e86c345 100644 --- a/app/src/main/res/layout-land/submitted_answer_item.xml +++ b/app/src/main/res/layout-land/submitted_answer_item.xml @@ -20,6 +20,7 @@ (0)) + testCoroutineDispatchers.runCurrent() onView( RecyclerViewMatcher.atPositionOnView( R.id.hints_and_solution_recycler_view, 0, R.id.hint_summary_container ) ).perform(click()) testCoroutineDispatchers.runCurrent() + onView(isRoot()).check( matches( not( @@ -763,6 +800,7 @@ class StateFragmentLocalTest { onView(withId(R.id.hints_and_solution_recycler_view)) .inRoot(isDialog()) .perform(scrollToPosition(/* position= */ solutionIndex * 2)) + testCoroutineDispatchers.runCurrent() onView(allOf(withId(R.id.reveal_solution_button), isDisplayed())) .inRoot(isDialog()) .check(matches(isDisplayed())) @@ -815,6 +853,7 @@ class StateFragmentLocalTest { onView(withId(R.id.hints_and_solution_recycler_view)) .inRoot(isDialog()) .perform(scrollToPosition(/* position= */ solutionIndex * 2)) + testCoroutineDispatchers.runCurrent() onView(allOf(withId(R.id.reveal_solution_button), isDisplayed())) .inRoot(isDialog()) .check(matches(isDisplayed())) @@ -838,9 +877,11 @@ class StateFragmentLocalTest { onView(withId(R.id.hints_and_solution_recycler_view)) .inRoot(isDialog()) .perform(scrollToPosition(/* position= */ solutionIndex * 2)) + testCoroutineDispatchers.runCurrent() onView(allOf(withId(R.id.reveal_solution_button), isDisplayed())) .inRoot(isDialog()) .perform(click()) + testCoroutineDispatchers.runCurrent() onView(withText("This will reveal the solution. Are you sure?")) .inRoot(isDialog()) @@ -1487,14 +1528,55 @@ class StateFragmentLocalTest { } // Go to previous state and then come back to current state - private fun moveToPreviousAndBackToCurrentState() { + private fun moveToPreviousAndBackToCurrentStateWithSubmitButton() { + // The previous navigation button is bundled with the submit button sometimes, and specifically + // for tests that are currently on a state with a submit button after the first state. + onView(withId(R.id.state_recycler_view)).perform(scrollToViewType(SUBMIT_ANSWER_BUTTON)) + testCoroutineDispatchers.runCurrent() onView(withId(R.id.previous_state_navigation_button)).perform(click()) testCoroutineDispatchers.runCurrent() + onView(withId(R.id.state_recycler_view)).perform(scrollToViewType(NEXT_NAVIGATION_BUTTON)) + testCoroutineDispatchers.runCurrent() onView(withId(R.id.next_state_navigation_button)).perform(click()) testCoroutineDispatchers.runCurrent() } + /** + * Returns a [ViewAssertion] that can be used to check the specified matcher applies the specified + * number of times for children against the view under test. If the count does not exactly match, + * the assertion will fail. + */ + private fun matchesChildren(matcher: Matcher, times: Int): ViewAssertion { + return matches( + object : TypeSafeMatcher() { + override fun describeTo(description: Description?) { + description + ?.appendDescriptionOf(matcher) + ?.appendText(" occurs times: $times in child views") + } + + override fun matchesSafely(view: View?): Boolean { + if (view !is ViewGroup) { + throw PerformException.Builder() + .withCause(IllegalStateException("Expected to match against view group, not: $view")) + .build() + } + val matchingCount = view.children.filter(matcher::matches).count() + if (matchingCount != times) { + throw PerformException.Builder() + .withActionDescription("Expected to match $matcher against $times children") + .withViewDescription("$view") + .withCause( + IllegalStateException("Matched $matchingCount times in $view (expected $times)") + ) + .build() + } + return true + } + }) + } + // TODO(#59): Figure out a way to reuse modules instead of needing to re-declare them. // TODO(#1675): Add NetworkModule once data module is migrated off of Moshi. @Singleton diff --git a/config/oppia-dev-workflow-remote-cache-credentials.json.secret b/config/oppia-dev-workflow-remote-cache-credentials.json.secret new file mode 100644 index 0000000000000000000000000000000000000000..2aa2fc7d0fe832b376a6de32720cbed7b693f5c1 GIT binary patch literal 2543 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 FFt=NW{1X5G literal 0 HcmV?d00001 diff --git a/domain/BUILD.bazel b/domain/BUILD.bazel index 88a69e91f23..aebc7016253 100755 --- a/domain/BUILD.bazel +++ b/domain/BUILD.bazel @@ -9,7 +9,10 @@ load("//domain:domain_test.bzl", "domain_test") kt_android_library( name = "domain", - srcs = glob(["src/main/java/org/oppia/android/domain/**/*.kt"]), + srcs = glob( + ["src/main/java/org/oppia/android/domain/**/*.kt"], + exclude = ["src/main/java/org/oppia/android/domain/testing/**/*.kt"], + ), assets = glob(["src/main/assets/**"]), assets_dir = "src/main/assets/", custom_package = "org.oppia.android.domain", @@ -22,10 +25,34 @@ kt_android_library( ], ) +kt_android_library( + name = "testing", + testonly = True, + srcs = glob(["src/main/java/org/oppia/android/domain/testing/**/*.kt"]), + deps = [ + ":domain", + "//third_party:androidx_work_work-runtime-ktx", + ], +) + +# TODO(#2143): Move InteractionObjectTestBuilder to a testing package outside the test folder. +kt_android_library( + name = "interaction_object_test_builder", + testonly = True, + srcs = [ + "src/test/java/org/oppia/android/domain/classify/InteractionObjectTestBuilder.kt", + ], + deps = [ + "//model", + ], +) + # keep sorted TEST_DEPS = [ ":dagger", ":domain", + ":interaction_object_test_builder", + ":testing", "//data:persistent_cache_store", "//model", "//testing", @@ -271,6 +298,15 @@ domain_test( deps = TEST_DEPS, ) +domain_test( + name = "ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest", + srcs = [ + "src/test/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest.kt", + ], + test_class = "org.oppia.android.domain.classify.rules.itemselectioninput.ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest", + deps = TEST_DEPS, +) + domain_test( name = "MultipleChoiceInputEqualsRuleClassifierProviderTest", srcs = [ @@ -316,15 +352,6 @@ domain_test( deps = TEST_DEPS, ) -domain_test( - name = "ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest", - srcs = [ - "src/test/java/org/oppia/android/domain/classify/rules/textinput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest.kt", - ], - test_class = "org.oppia.android.domain.classify.rules.textinput.ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProviderTest", - deps = TEST_DEPS, -) - domain_test( name = "TextInputEqualsRuleClassifierProviderTest", srcs = [ @@ -429,13 +456,6 @@ domain_test( deps = TEST_DEPS, ) -domain_test( - name = "StoryProgressTestHelperTest", - srcs = ["src/test/java/org/oppia/android/domain/topic/StoryProgressTestHelperTest.kt"], - test_class = "org.oppia.android.domain.topic.StoryProgressTestHelperTest", - deps = TEST_DEPS, -) - domain_test( name = "TopicControllerTest", srcs = ["src/test/java/org/oppia/android/domain/topic/TopicControllerTest.kt"], diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasDenominatorEqualToRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasDenominatorEqualToRuleClassifierProvider.kt index 920d80da61f..0e64186bf88 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasDenominatorEqualToRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasDenominatorEqualToRuleClassifierProvider.kt @@ -13,7 +13,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/FractionInput/directives/fraction-input-rules.service.ts#L55 */ -internal class FractionInputHasDenominatorEqualToRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class FractionInputHasDenominatorEqualToRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.MultiTypeSingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasFractionalPartExactlyEqualToRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasFractionalPartExactlyEqualToRuleClassifierProvider.kt index abd7a5e524d..0cf0436d126 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasFractionalPartExactlyEqualToRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasFractionalPartExactlyEqualToRuleClassifierProvider.kt @@ -13,7 +13,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/FractionInput/directives/fraction-input-rules.service.ts#L61 */ -internal class FractionInputHasFractionalPartExactlyEqualToRuleClassifierProvider +// TODO(#1580): Re-restrict access using Bazel visibilities +class FractionInputHasFractionalPartExactlyEqualToRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasIntegerPartEqualToRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasIntegerPartEqualToRuleClassifierProvider.kt index d24052e7e67..936de86e002 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasIntegerPartEqualToRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasIntegerPartEqualToRuleClassifierProvider.kt @@ -13,7 +13,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/FractionInput/directives/fraction-input-rules.service.ts#L48 */ -internal class FractionInputHasIntegerPartEqualToRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class FractionInputHasIntegerPartEqualToRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.MultiTypeSingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasNoFractionalPartRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasNoFractionalPartRuleClassifierProvider.kt index 53be10e46a0..58f9c867e79 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasNoFractionalPartRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasNoFractionalPartRuleClassifierProvider.kt @@ -13,7 +13,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/FractionInput/directives/fraction-input-rules.service.ts#L58 */ -internal class FractionInputHasNoFractionalPartRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class FractionInputHasNoFractionalPartRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.NoInputInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasNumeratorEqualToRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasNumeratorEqualToRuleClassifierProvider.kt index c4b57344f10..6ac6548b17b 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasNumeratorEqualToRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputHasNumeratorEqualToRuleClassifierProvider.kt @@ -13,7 +13,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/FractionInput/directives/fraction-input-rules.service.ts#L52 */ -internal class FractionInputHasNumeratorEqualToRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class FractionInputHasNumeratorEqualToRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.MultiTypeSingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsEquivalentToAndInSimplestFormRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsEquivalentToAndInSimplestFormRuleClassifierProvider.kt index f4796933679..b9d7669259e 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsEquivalentToAndInSimplestFormRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsEquivalentToAndInSimplestFormRuleClassifierProvider.kt @@ -16,7 +16,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/FractionInput/directives/fraction-input-rules.service.ts#L32 */ -internal class FractionInputIsEquivalentToAndInSimplestFormRuleClassifierProvider +// TODO(#1580): Re-restrict access using Bazel visibilities +class FractionInputIsEquivalentToAndInSimplestFormRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsEquivalentToRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsEquivalentToRuleClassifierProvider.kt index 3f327c293f3..2fb33b8a49e 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsEquivalentToRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsEquivalentToRuleClassifierProvider.kt @@ -15,7 +15,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/FractionInput/directives/fraction-input-rules.service.ts#L29 */ -internal class FractionInputIsEquivalentToRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class FractionInputIsEquivalentToRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsExactlyEqualToRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsExactlyEqualToRuleClassifierProvider.kt index f6bf11e37c6..6d598462f21 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsExactlyEqualToRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsExactlyEqualToRuleClassifierProvider.kt @@ -13,7 +13,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/FractionInput/directives/fraction-input-rules.service.ts#L38 */ -internal class FractionInputIsExactlyEqualToRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class FractionInputIsExactlyEqualToRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsGreaterThanRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsGreaterThanRuleClassifierProvider.kt index 7f6134b77c2..b97634272a6 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsGreaterThanRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsGreaterThanRuleClassifierProvider.kt @@ -14,7 +14,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/FractionInput/directives/fraction-input-rules.service.ts#L45 */ -internal class FractionInputIsGreaterThanRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class FractionInputIsGreaterThanRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsLessThanRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsLessThanRuleClassifierProvider.kt index 2af4756865e..7daa45360ee 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsLessThanRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/fractioninput/FractionInputIsLessThanRuleClassifierProvider.kt @@ -14,7 +14,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/FractionInput/directives/fraction-input-rules.service.ts#L42 */ -internal class FractionInputIsLessThanRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class FractionInputIsLessThanRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputContainsAtLeastOneOfRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputContainsAtLeastOneOfRuleClassifierProvider.kt index ccecf8cf291..970e1a039c2 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputContainsAtLeastOneOfRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputContainsAtLeastOneOfRuleClassifierProvider.kt @@ -13,7 +13,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/ItemSelectionInput/directives/item-selection-input-rules.service.ts#L32 */ -internal class ItemSelectionInputContainsAtLeastOneOfRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class ItemSelectionInputContainsAtLeastOneOfRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvider.kt index d832f865683..b463656e257 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvider.kt @@ -13,7 +13,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/ItemSelectionInput/directives/item-selection-input-rules.service.ts#L41 */ -internal class ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvider +// TODO(#1580): Re-restrict access using Bazel visibilities +class ItemSelectionInputDoesNotContainAtLeastOneOfRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputEqualsRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputEqualsRuleClassifierProvider.kt index 4323babbcbf..2a0be24f078 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputEqualsRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputEqualsRuleClassifierProvider.kt @@ -13,7 +13,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/ItemSelectionInput/directives/item-selection-input-rules.service.ts#L24 */ -internal class ItemSelectionInputEqualsRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class ItemSelectionInputEqualsRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputIsProperSubsetOfRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputIsProperSubsetOfRuleClassifierProvider.kt index fd0b82bfdca..6be952bf6a3 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputIsProperSubsetOfRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/itemselectioninput/ItemSelectionInputIsProperSubsetOfRuleClassifierProvider.kt @@ -13,7 +13,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/ItemSelectionInput/directives/item-selection-input-rules.service.ts#L50 */ -internal class ItemSelectionInputIsProperSubsetOfRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class ItemSelectionInputIsProperSubsetOfRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/numberwithunits/NumberWithUnitsIsEqualToRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/numberwithunits/NumberWithUnitsIsEqualToRuleClassifierProvider.kt index 2d041af1383..b9c3fc9647f 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/numberwithunits/NumberWithUnitsIsEqualToRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/numberwithunits/NumberWithUnitsIsEqualToRuleClassifierProvider.kt @@ -15,7 +15,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/NumberWithUnits/directives/number-with-units-rules.service.ts#L34 */ -internal class NumberWithUnitsIsEqualToRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class NumberWithUnitsIsEqualToRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/numberwithunits/NumberWithUnitsIsEquivalentToRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/numberwithunits/NumberWithUnitsIsEquivalentToRuleClassifierProvider.kt index e5d66332c9d..2572709908f 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/numberwithunits/NumberWithUnitsIsEquivalentToRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/numberwithunits/NumberWithUnitsIsEquivalentToRuleClassifierProvider.kt @@ -15,7 +15,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/NumberWithUnits/directives/number-with-units-rules.service.ts#L48 */ -internal class NumberWithUnitsIsEquivalentToRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class NumberWithUnitsIsEquivalentToRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsGreaterThanOrEqualToRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsGreaterThanOrEqualToRuleClassifierProvider.kt index 6416890a774..b6b2d3877af 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsGreaterThanOrEqualToRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsGreaterThanOrEqualToRuleClassifierProvider.kt @@ -11,7 +11,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/NumericInput/directives/numeric-input-rules.service.ts#L33 */ -internal class NumericInputIsGreaterThanOrEqualToRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class NumericInputIsGreaterThanOrEqualToRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsGreaterThanRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsGreaterThanRuleClassifierProvider.kt index 981f9064ae5..d1980129de1 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsGreaterThanRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsGreaterThanRuleClassifierProvider.kt @@ -11,7 +11,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/NumericInput/directives/numeric-input-rules.service.ts#L27 */ -internal class NumericInputIsGreaterThanRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class NumericInputIsGreaterThanRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsInclusivelyBetweenRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsInclusivelyBetweenRuleClassifierProvider.kt index 3205c34c470..942f774aeee 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsInclusivelyBetweenRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsInclusivelyBetweenRuleClassifierProvider.kt @@ -12,7 +12,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/NumericInput/directives/numeric-input-rules.service.ts#L36 */ -internal class NumericInputIsInclusivelyBetweenRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class NumericInputIsInclusivelyBetweenRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.DoubleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsLessThanOrEqualToRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsLessThanOrEqualToRuleClassifierProvider.kt index 5685ae912be..122139a32c2 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsLessThanOrEqualToRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsLessThanOrEqualToRuleClassifierProvider.kt @@ -11,7 +11,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/NumericInput/directives/numeric-input-rules.service.ts#L30 */ -internal class NumericInputIsLessThanOrEqualToRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class NumericInputIsLessThanOrEqualToRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsLessThanRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsLessThanRuleClassifierProvider.kt index 2d737b89b3a..dfef211d916 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsLessThanRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsLessThanRuleClassifierProvider.kt @@ -11,7 +11,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/NumericInput/directives/numeric-input-rules.service.ts#L24 */ -internal class NumericInputIsLessThanRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class NumericInputIsLessThanRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsWithinToleranceRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsWithinToleranceRuleClassifierProvider.kt index 3097fe02137..63c38aa8116 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsWithinToleranceRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/numericinput/NumericInputIsWithinToleranceRuleClassifierProvider.kt @@ -12,7 +12,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/NumericInput/directives/numeric-input-rules.service.ts#L41 */ -internal class NumericInputIsWithinToleranceRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class NumericInputIsWithinToleranceRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.DoubleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/ratioinput/RatioInputEqualsRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/ratioinput/RatioInputEqualsRuleClassifierProvider.kt index e27bb871863..cd25fb88cbf 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/ratioinput/RatioInputEqualsRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/ratioinput/RatioInputEqualsRuleClassifierProvider.kt @@ -11,7 +11,8 @@ import javax.inject.Inject * Provider for a classifier that determines whether two object are equal per the ratio input * interaction. */ -internal class RatioInputEqualsRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class RatioInputEqualsRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/ratioinput/RatioInputHasNumberOfTermsEqualToClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/ratioinput/RatioInputHasNumberOfTermsEqualToClassifierProvider.kt index e7428765bdf..ef0697a3b68 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/ratioinput/RatioInputHasNumberOfTermsEqualToClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/ratioinput/RatioInputHasNumberOfTermsEqualToClassifierProvider.kt @@ -10,7 +10,8 @@ import javax.inject.Inject /** * Provider for a classifier that determines whether two object have an equal number of terms. */ -internal class RatioInputHasNumberOfTermsEqualToClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class RatioInputHasNumberOfTermsEqualToClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.MultiTypeSingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/ratioinput/RatioInputIsEquivalentRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/ratioinput/RatioInputIsEquivalentRuleClassifierProvider.kt index 2c6f24b7b52..3cdf2010e15 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/ratioinput/RatioInputIsEquivalentRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/ratioinput/RatioInputIsEquivalentRuleClassifierProvider.kt @@ -12,7 +12,8 @@ import javax.inject.Inject * Provider for a classifier that determines whether two object are equal by converting them into * their lowest form as per the ratio input interaction. */ -internal class RatioInputIsEquivalentRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class RatioInputIsEquivalentRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/textinput/TextInputCaseSensitiveEqualsRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/textinput/TextInputCaseSensitiveEqualsRuleClassifierProvider.kt index 61646b51790..ac9245f0ab3 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/textinput/TextInputCaseSensitiveEqualsRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/textinput/TextInputCaseSensitiveEqualsRuleClassifierProvider.kt @@ -13,7 +13,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/TextInput/directives/text-input-rules.service.ts#L59 */ -internal class TextInputCaseSensitiveEqualsRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class TextInputCaseSensitiveEqualsRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/textinput/TextInputFuzzyEqualsRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/textinput/TextInputFuzzyEqualsRuleClassifierProvider.kt index 7cef1505cdb..45a840cf78f 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/textinput/TextInputFuzzyEqualsRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/textinput/TextInputFuzzyEqualsRuleClassifierProvider.kt @@ -12,7 +12,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/TextInput/directives/text-input-rules.service.ts#L29. */ -internal class TextInputFuzzyEqualsRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class TextInputFuzzyEqualsRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/classify/rules/textinput/TextInputStartsWithRuleClassifierProvider.kt b/domain/src/main/java/org/oppia/android/domain/classify/rules/textinput/TextInputStartsWithRuleClassifierProvider.kt index e1bf898eca2..5c7869994d9 100644 --- a/domain/src/main/java/org/oppia/android/domain/classify/rules/textinput/TextInputStartsWithRuleClassifierProvider.kt +++ b/domain/src/main/java/org/oppia/android/domain/classify/rules/textinput/TextInputStartsWithRuleClassifierProvider.kt @@ -13,7 +13,8 @@ import javax.inject.Inject * * https://github.com/oppia/oppia/blob/37285a/extensions/interactions/TextInput/directives/text-input-rules.service.ts#L64 */ -internal class TextInputStartsWithRuleClassifierProvider @Inject constructor( +// TODO(#1580): Re-restrict access using Bazel visibilities +class TextInputStartsWithRuleClassifierProvider @Inject constructor( private val classifierFactory: GenericRuleClassifier.Factory ) : RuleClassifierProvider, GenericRuleClassifier.SingleInputMatcher { diff --git a/domain/src/main/java/org/oppia/android/domain/testing/oppialogger/loguploader/FakeLogUploader.kt b/domain/src/main/java/org/oppia/android/domain/testing/oppialogger/loguploader/FakeLogUploader.kt new file mode 100644 index 00000000000..b2a02324827 --- /dev/null +++ b/domain/src/main/java/org/oppia/android/domain/testing/oppialogger/loguploader/FakeLogUploader.kt @@ -0,0 +1,35 @@ +package org.oppia.android.domain.testing.oppialogger.loguploader + +import androidx.work.PeriodicWorkRequest +import androidx.work.WorkManager +import org.oppia.android.util.logging.LogUploader +import java.util.UUID +import javax.inject.Inject +import javax.inject.Singleton + +/** A test specific fake for the log uploader. */ +@Singleton +class FakeLogUploader @Inject constructor() : LogUploader { + private val eventRequestIdList = mutableListOf() + private val exceptionRequestIdList = mutableListOf() + + override fun enqueueWorkRequestForEvents( + workManager: WorkManager, + workRequest: PeriodicWorkRequest + ) { + eventRequestIdList.add(workRequest.id) + } + + override fun enqueueWorkRequestForExceptions( + workManager: WorkManager, + workRequest: PeriodicWorkRequest + ) { + exceptionRequestIdList.add(workRequest.id) + } + + /** Returns the most recent work request id that's stored in the [eventRequestIdList]. */ + fun getMostRecentEventRequestId() = eventRequestIdList.last() + + /** Returns the most recent work request id that's stored in the [exceptionRequestIdList]. */ + fun getMostRecentExceptionRequestId() = exceptionRequestIdList.last() +} diff --git a/domain/src/test/java/org/oppia/android/domain/oppialogger/OppiaLoggerTest.kt b/domain/src/test/java/org/oppia/android/domain/oppialogger/OppiaLoggerTest.kt index 03807c911a5..9f591202db4 100644 --- a/domain/src/test/java/org/oppia/android/domain/oppialogger/OppiaLoggerTest.kt +++ b/domain/src/test/java/org/oppia/android/domain/oppialogger/OppiaLoggerTest.kt @@ -13,13 +13,6 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.oppia.android.app.model.EventLog -import org.oppia.android.domain.oppialogger.analytics.TEST_EXPLORATION_ID -import org.oppia.android.domain.oppialogger.analytics.TEST_QUESTION_ID -import org.oppia.android.domain.oppialogger.analytics.TEST_SKILL_ID -import org.oppia.android.domain.oppialogger.analytics.TEST_SKILL_LIST_ID -import org.oppia.android.domain.oppialogger.analytics.TEST_STORY_ID -import org.oppia.android.domain.oppialogger.analytics.TEST_SUB_TOPIC_ID -import org.oppia.android.domain.oppialogger.analytics.TEST_TOPIC_ID import org.oppia.android.testing.RobolectricModule import org.oppia.android.testing.TestDispatcherModule import org.oppia.android.testing.TestLogReportingModule @@ -33,6 +26,14 @@ import org.robolectric.annotation.LooperMode import javax.inject.Inject import javax.inject.Singleton +private const val TEST_TOPIC_ID = "test_topicId" +private const val TEST_STORY_ID = "test_storyId" +private const val TEST_EXPLORATION_ID = "test_explorationId" +private const val TEST_QUESTION_ID = "test_questionId" +private const val TEST_SKILL_ID = "test_skillId" +private const val TEST_SKILL_LIST_ID = "test_skillListId" +private const val TEST_SUB_TOPIC_ID = 1 + @RunWith(AndroidJUnit4::class) @LooperMode(LooperMode.Mode.PAUSED) @Config(manifest = Config.NONE) diff --git a/domain/src/test/java/org/oppia/android/domain/oppialogger/analytics/AnalyticsControllerTest.kt b/domain/src/test/java/org/oppia/android/domain/oppialogger/analytics/AnalyticsControllerTest.kt index 3b45bf92e98..c7b96930266 100644 --- a/domain/src/test/java/org/oppia/android/domain/oppialogger/analytics/AnalyticsControllerTest.kt +++ b/domain/src/test/java/org/oppia/android/domain/oppialogger/analytics/AnalyticsControllerTest.kt @@ -54,14 +54,14 @@ import org.robolectric.annotation.LooperMode import javax.inject.Inject import javax.inject.Singleton -const val TEST_TIMESTAMP = 1556094120000 -const val TEST_TOPIC_ID = "test_topicId" -const val TEST_STORY_ID = "test_storyId" -const val TEST_EXPLORATION_ID = "test_explorationId" -const val TEST_QUESTION_ID = "test_questionId" -const val TEST_SKILL_ID = "test_skillId" -const val TEST_SKILL_LIST_ID = "test_skillListId" -const val TEST_SUB_TOPIC_ID = 1 +private const val TEST_TIMESTAMP = 1556094120000 +private const val TEST_TOPIC_ID = "test_topicId" +private const val TEST_STORY_ID = "test_storyId" +private const val TEST_EXPLORATION_ID = "test_explorationId" +private const val TEST_QUESTION_ID = "test_questionId" +private const val TEST_SKILL_ID = "test_skillId" +private const val TEST_SKILL_LIST_ID = "test_skillListId" +private const val TEST_SUB_TOPIC_ID = 1 @RunWith(AndroidJUnit4::class) @LooperMode(LooperMode.Mode.PAUSED) diff --git a/domain/src/test/java/org/oppia/android/domain/oppialogger/loguploader/LogUploadWorkManagerInitializerTest.kt b/domain/src/test/java/org/oppia/android/domain/oppialogger/loguploader/LogUploadWorkManagerInitializerTest.kt index dea0334695a..e4a7a40f1c0 100644 --- a/domain/src/test/java/org/oppia/android/domain/oppialogger/loguploader/LogUploadWorkManagerInitializerTest.kt +++ b/domain/src/test/java/org/oppia/android/domain/oppialogger/loguploader/LogUploadWorkManagerInitializerTest.kt @@ -9,8 +9,6 @@ import androidx.work.Configuration import androidx.work.Constraints import androidx.work.Data import androidx.work.NetworkType -import androidx.work.PeriodicWorkRequest -import androidx.work.WorkManager import androidx.work.testing.SynchronousExecutor import androidx.work.testing.WorkManagerTestInitHelper import com.google.common.truth.Truth.assertThat @@ -25,8 +23,8 @@ import org.junit.runner.RunWith import org.oppia.android.domain.oppialogger.EventLogStorageCacheSize import org.oppia.android.domain.oppialogger.ExceptionLogStorageCacheSize import org.oppia.android.domain.oppialogger.OppiaLogger -import org.oppia.android.domain.oppialogger.analytics.AnalyticsController import org.oppia.android.domain.oppialogger.exceptions.ExceptionsController +import org.oppia.android.domain.testing.oppialogger.loguploader.FakeLogUploader import org.oppia.android.testing.FakeEventLogger import org.oppia.android.testing.FakeExceptionLogger import org.oppia.android.testing.RobolectricModule @@ -43,10 +41,8 @@ import org.oppia.android.util.logging.LogUploader import org.oppia.android.util.networking.NetworkConnectionUtil import org.robolectric.annotation.Config import org.robolectric.annotation.LooperMode -import java.util.UUID import javax.inject.Inject import javax.inject.Singleton -import kotlin.collections.last @RunWith(AndroidJUnit4::class) @LooperMode(LooperMode.Mode.PAUSED) @@ -59,9 +55,6 @@ class LogUploadWorkManagerInitializerTest { @Inject lateinit var logUploadWorkManagerInitializer: LogUploadWorkManagerInitializer - @Inject - lateinit var analyticsController: AnalyticsController - @Inject lateinit var exceptionsController: ExceptionsController @@ -227,32 +220,3 @@ class LogUploadWorkManagerInitializerTest { fun inject(logUploadWorkRequestTest: LogUploadWorkManagerInitializerTest) } } - -/** A test specific fake for the log uploader. */ -@Singleton -class FakeLogUploader @Inject constructor() : - LogUploader { - - private val eventRequestIdList = mutableListOf() - private val exceptionRequestIdList = mutableListOf() - - override fun enqueueWorkRequestForEvents( - workManager: WorkManager, - workRequest: PeriodicWorkRequest - ) { - eventRequestIdList.add(workRequest.id) - } - - override fun enqueueWorkRequestForExceptions( - workManager: WorkManager, - workRequest: PeriodicWorkRequest - ) { - exceptionRequestIdList.add(workRequest.id) - } - - /** Returns the most recent work request id that's stored in the [eventRequestIdList]. */ - fun getMostRecentEventRequestId() = eventRequestIdList.last() - - /** Returns the most recent work request id that's stored in the [exceptionRequestIdList]. */ - fun getMostRecentExceptionRequestId() = exceptionRequestIdList.last() -} diff --git a/domain/src/test/java/org/oppia/android/domain/oppialogger/loguploader/LogUploadWorkerTest.kt b/domain/src/test/java/org/oppia/android/domain/oppialogger/loguploader/LogUploadWorkerTest.kt index 791f6c9d96e..9bc3bc3bf0b 100644 --- a/domain/src/test/java/org/oppia/android/domain/oppialogger/loguploader/LogUploadWorkerTest.kt +++ b/domain/src/test/java/org/oppia/android/domain/oppialogger/loguploader/LogUploadWorkerTest.kt @@ -27,9 +27,8 @@ import org.oppia.android.domain.oppialogger.EventLogStorageCacheSize import org.oppia.android.domain.oppialogger.ExceptionLogStorageCacheSize import org.oppia.android.domain.oppialogger.OppiaLogger import org.oppia.android.domain.oppialogger.analytics.AnalyticsController -import org.oppia.android.domain.oppialogger.analytics.TEST_TIMESTAMP -import org.oppia.android.domain.oppialogger.analytics.TEST_TOPIC_ID import org.oppia.android.domain.oppialogger.exceptions.ExceptionsController +import org.oppia.android.domain.testing.oppialogger.loguploader.FakeLogUploader import org.oppia.android.testing.FakeEventLogger import org.oppia.android.testing.FakeExceptionLogger import org.oppia.android.testing.RobolectricModule @@ -49,6 +48,9 @@ import org.robolectric.annotation.LooperMode import javax.inject.Inject import javax.inject.Singleton +private const val TEST_TIMESTAMP = 1556094120000 +private const val TEST_TOPIC_ID = "test_topicId" + @RunWith(AndroidJUnit4::class) @LooperMode(LooperMode.Mode.PAUSED) @Config(manifest = Config.NONE) @@ -157,13 +159,32 @@ class LogUploadWorkerTest { .build() workManager.enqueue(request) testCoroutineDispatchers.runCurrent() - val workInfo = workManager.getWorkInfoById(request.id) - val exceptionGot = fakeExceptionLogger.getMostRecentException() + val workInfo = workManager.getWorkInfoById(request.id) + val loggedException = fakeExceptionLogger.getMostRecentException() + val loggedExceptionStackTraceElems = loggedException.stackTrace.extractRelevantDetails() + val expectedExceptionStackTraceElems = exception.stackTrace.extractRelevantDetails() assertThat(workInfo.get().state).isEqualTo(WorkInfo.State.SUCCEEDED) - assertThat(exceptionGot.message).isEqualTo("TEST") - assertThat(exceptionGot.stackTrace).isEqualTo(exception.stackTrace) - assertThat(exceptionGot.cause).isEqualTo(null) + assertThat(loggedException.message).isEqualTo("TEST") + assertThat(loggedException.cause).isEqualTo(null) + // The following can't be an exact match for the stack trace since new properties are added to + // stack trace elements in newer versions of Java (such as module name). + assertThat(loggedExceptionStackTraceElems).isEqualTo(expectedExceptionStackTraceElems) + } + + /** + * Returns a list of lists of each relevant element of a [StackTraceElement] to be used for + * comparison in a way that's consistent across JDK versions. + */ + private fun Array.extractRelevantDetails(): List> { + return this.map { element -> + return@map listOf( + element.fileName, + element.methodName, + element.lineNumber, + element.className + ) + } } private fun setUpTestApplicationComponent() { diff --git a/scripts/compute_affected_tests.sh b/scripts/compute_affected_tests.sh new file mode 100755 index 00000000000..e264b37d824 --- /dev/null +++ b/scripts/compute_affected_tests.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +# Compute the list of tests that are affected by changes on this branch (including in the working +# directory). This script is useful to verify that only the tests that could break due to a change +# are actually verified as passing. Note that this script does not actually run any of the tests. +# +# Usage: +# bash scripts/compute_affected_tests.sh +# +# This script is based on https://github.com/bazelbuild/bazel/blob/d96e1cd/scripts/ci/ci.sh and the +# documentation at https://docs.bazel.build/versions/master/query.html. Note that this script will +# automatically list all tests if it's run on the develop branch (the idea being that test +# considerations on the develop branch should always consider all targets). + +BAZEL_BINARY=$1 + +# Reference: https://stackoverflow.com/a/6245587. +current_branch=$(git branch --show-current) + +if [[ "$current_branch" != "develop" ]]; then + # Compute all files that have been changed on this branch. https://stackoverflow.com/a/9294015 for + # constructing the arrays. + commit_range=HEAD..$(git merge-base origin/develop HEAD) + changed_committed_files=($(git diff --name-only $commit_range)) + changed_staged_files=($(git diff --name-only --cached)) + changed_unstaged_files=($(git diff --name-only)) + # See https://stackoverflow.com/a/35484355 for how this works. + changed_untracked_files=($(git ls-files --others --exclude-standard)) + + changed_files_with_potential_duplicates=( + "${changed_committed_files[@]}" + "${changed_staged_files[@]}" + "${changed_unstaged_files[@]}" + "${changed_untracked_files[@]}" + ) + + # De-duplicate files: https://unix.stackexchange.com/q/377812. + changed_files=($(printf "%s\n" "${changed_files_with_potential_duplicates[@]}" | sort -u)) + + # Filter all of the source files among those that are actually included in Bazel builds. + changed_bazel_files=() + for changed_file in "${changed_files[@]}"; do + changed_bazel_files+=($($BAZEL_BINARY query --noshow_progress $changed_file 2> /dev/null)) + done + + # Compute the list of affected tests based on source files. + source_affected_targets="$($BAZEL_BINARY query --noshow_progress --universe_scope=//... --order_output=no "kind(test, allrdeps(set(${changed_bazel_files[@]})))" 2>/dev/null)" + + # Compute the list of files to consider for BUILD-level changes (this uses the base file list as a + # reference since Bazel's query won't find matching targets for utility bzl files that can still + # affect the build). https://stackoverflow.com/a/44107086 for reference on changing case matching. + shopt -s nocasematch + changed_bazel_support_files=() + for changed_file in "${changed_files[@]}"; do + if [[ "$changed_file" =~ ^.+?\.bazel$ ]] || [[ "$changed_file" =~ ^.+?\.bzl$ ]] || [[ "$changed_file" == "WORKSPACE" ]]; then + changed_bazel_support_files+=("$changed_file") + fi + done + shopt -u nocasematch + + # Compute the list of affected tests based on BUILD/Bazel/WORKSPACE files. These are generally + # framed as: if a BUILD file changes, run all tests transitively connected to it. + # Reference for joining an array to string: https://stackoverflow.com/a/53839433. + printf -v changed_bazel_support_files_list '%s,' "${changed_bazel_support_files[@]}" + build_affected_targets=$($BAZEL_BINARY query --noshow_progress --universe_scope=//... --order_output=no "filter('^[^@]', kind(test, allrdeps(siblings(rbuildfiles(${changed_bazel_support_files_list%,})))))" 2>/dev/null) + + all_affected_targets_with_potential_duplicated=( + "${source_affected_targets[@]}" + "${build_affected_targets[@]}" + ) + + # Print all of the affected targets without duplicates. + printf "%s\n" "${all_affected_targets_with_potential_duplicated[@]}" | sort -u +else + # Print all test targets. + $BAZEL_BINARY query --noshow_progress "kind(test, //...)" 2>/dev/null +fi diff --git a/testing/BUILD.bazel b/testing/BUILD.bazel index 25fd4736b7e..2ad57cd6a11 100644 --- a/testing/BUILD.bazel +++ b/testing/BUILD.bazel @@ -11,6 +11,7 @@ load("//testing:testing_test.bzl", "testing_test") # Library for general-purpose testing fakes. kt_android_library( name = "testing", + testonly = True, srcs = glob(["src/main/java/org/oppia/android/testing/**/*.kt"]), custom_package = "org.oppia.android.testing", manifest = "src/main/AndroidManifest.xml", @@ -26,6 +27,7 @@ kt_android_library( "//third_party:androidx_test_runner", "//third_party:com_google_truth_truth", "//third_party:junit_junit", + "//third_party:nl_dionsegijn_konfetti", "//third_party:org_jetbrains_kotlin_kotlin-reflect", "//third_party:org_jetbrains_kotlinx_kotlinx-coroutines-test", "//third_party:org_mockito_mockito-core", @@ -82,6 +84,13 @@ testing_test( deps = TEST_DEPS, ) +testing_test( + name = "StoryProgressTestHelperTest", + srcs = ["src/test/java/org/oppia/android/testing/story/StoryProgressTestHelperTest.kt"], + test_class = "org.oppia.android.testing.story.StoryProgressTestHelperTest", + deps = TEST_DEPS, +) + testing_test( name = "FakeOppiaClockTest", srcs = ["src/test/java/org/oppia/android/testing/time/FakeOppiaClockTest.kt"], diff --git a/third_party/BUILD.bazel b/third_party/BUILD.bazel index 159685a3c55..7fcf410315b 100644 --- a/third_party/BUILD.bazel +++ b/third_party/BUILD.bazel @@ -46,6 +46,7 @@ android_library( android_library( name = "robolectric_android-all", + visibility = ["//visibility:public"], exports = [ "@robolectric//bazel:android-all", ],