Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request]: Introduce support for code coverage & enforcement (GSoC'24 4.1) #5343

Closed
BenHenning opened this issue Feb 17, 2024 · 20 comments
Assignees
Labels
enhancement End user-perceivable enhancements.

Comments

@BenHenning
Copy link
Member

BenHenning commented Feb 17, 2024

Is your feature request related to a problem? Please describe.

The team cannot currently monitor and enforce minimum code coverage (as a proxy for functional behavioral coverage) in automated tests.

Describe the solution you'd like

Suggested milestones

  • Milestone 1: Introduce a new script to compute a per-unit code coverage percentage for a single file.

    • Deliverable 1: Introduce a new scripting utility that can run code coverage for a specific Bazel test target, interpret the results, and return a proto for data processing.
    • Deliverable 2: Introduce a new utility which can, given the proto from the deliverable 1 utility, generate a rich-text code coverage report in one of two formats:
      1. Markdown (for easy copying to GitHub)
      2. HTML (for easy local viewing)
    • Deliverable 3: Update the test exemption check script & its exemption format such that each file now has two possible states:
      1. Exempt from having a test file (the current exemption behavior).
      2. An override of the code coverage to meet a specific minimum (which can be 0%).
  • Milestone 2: Integrate code coverage checking.

    • Deliverable 1: Introduce a new script that uses the utility from deliverable 1 to perform code coverage analysis for a single target and the utility from deliverable 2 to optionally generate and output a rich-text report file for the test run. This script should always output the computed code coverage for a given file, and have a configuration option to fail if it's below a specified threshold.
    • Deliverable 2: Introduce a new CI workflow which, similarly to the existing unit test workflow, runs a series of buckets for code coverage analysis using the new script from milestone 1. Report generation should be enabled & reports uploaded as artifacts. Code coverage should only run after tests are passing (on a per-bucket basis if possible).
    • Deliverable 3: Fix/replace the cancellation workflow to ensure re-runs of CI correctly and quickly terminate all existing workflows that are running.
    • Deliverable 4: Introduce a wiki page explaining how to use the code coverage tool, provide advice on how to write tests with good behavioral coverage, and explain the limitations of the code coverage tool (i.e. all the cases it does not correctly count coverage for a specific line).
    • Deliverable 5: File issues for all cases where the code coverage tool misses or incorrectly counts code coverage for future work.
Technical hints / guidance

Top-level components needed for code-coverage support

  • coverage.proto: Describes the new scripting data structures needed for code coverage.
  • CoverageRunner.kt: A new scripting utility for running code coverage for a selected target.
  • CoverageReporter.kt: A new scripting utility for generating an HTML report of code coverage.
  • RunCoverage.kt: A new script for running code coverage locally.
  • scripts/src/java/org/oppia/android/scripts/testfile/TestFileCheck.kt: Existing utility that needs to be updated to include support for code coverage enforcement.
  • scripts/src/java/org/oppia/android/scripts/proto/script_exemptions.proto: Existing exemptions definition that needs to be updated per the TestFileCheck changes.
  • .github/workflows/unit_tests.yml: Existing CI workflow that needs to be updated in order to support code coverage.
  • .github/workflows/workflow_canceller.yml: Existing CI workflow that needs to be fixed.
  • (Other files for wiki changes).

Some key technical notes

  • This spec overview does not include details for the Yaml or wiki changes.
  • The test file exemptions textproto file will need to be rebuilt. The simplest way to do this would be to update TestFileCheck to include a text proto regenerate argument (as used in other scripts).
  • workflow_canceller.yml changes may required manually introducing support for workflow cancellation, or finding an available open source utility that works correctly for dynamic matrix jobs.
  • unit_tests.yml will probably be extended to introduce a new job that blocks on the test run (in the same way as check_tests) except it (note that this may require a new script not spec'ed out in this overview):
      1. Intreprets the same matrix data as the main test run but omits the failing tests using the outputs from the test runs themselves.
      1. Starts a new test matrix that runs the RunCoverage.kt script for each affected file corresponding to each affected test. For example, if StateFragmentTest.kt is one of the affected tests, then RunCoverage would be run for StateFragment.kt (which would then correspond to StateFragmentTest per its behavior).
    • Note that the min enforced coverage for now should be something very modest, like 10%. This number will be increased in future changes outside the scope of this project (as the number may not be believable until we understand the limitations of what can be covered by JaCoCo).
  • BazelClient.kt may need to be updated to include a function for running coverage on a specific target & output the standard output lines from that (which can then be parsed to get the report to generate the CoverageReport proto object).
  • All new components require new corresponding test files. All updated components will need their tests updated based on the changes to those components.

Suggested files to add/change

coverage.proto:

message CoverageReport {
  string bazel_test_target = 1; // The Bazel test target that was run.
  repeated CoveredFile covered_file = 2; // Files with some coverage in this report.
}

message CoveredFile {
  string file_path = 1; // Relative to the project root.
  string file_sha1_hash = 2; // SHA-1 hash of the file content at the time of report (to guard against changes).
  repeated CoveredLine covered_line = 3; // Lines of code covered in the report.
}

message CoveredLine {
  int32 line_number = 1; // 0-starting line number of the covered line.
  Coverage coverage = 2; // Detected coverage.
  
  enum Coverage {
    FULL, // This line was fully covered by the test.
    PARTIAL, // This line was partially covered by the test, indicating some branches not being covered.
    NONE // This line was not executed during the test.
  }
}

CoverageReporter.kt:

class CoverageReporter {
  fun generateRichTextReport(report: CoverageReport, format: ReportFormat): String
  fun computeCoverageRatio(file: String, report: CoverageReport): Float // Returns in [0, 1].
  
  enum class ReportFormat {
    MARKDOWN,
    HTML
  }
}

CoverageRunner.kt:

class CoverageRunner {
  // Uses bazel coverage to run code coverage on the specified test target & interprets the results to generate and return a CoverageReport.
  fun runWithCoverageAsync(bazelTestTarget: String): Deferred<CoverageReport>
}

RunCoverage.kt:

// Usage:
//   bazel run //scripts:run_coverage -- <repo_root> <relative_test_file> <report_output_dir> [min_coverage=<int_perc>] [format=markdown,html]
//
// Examples:
//   bazel run //scripts:run_coverage -- $(pwd) utility/src/main/java/org/oppia/android/util/math/MathTokenizer.kt $(pwd)/reports
//   bazel run //scripts:run_coverage -- $(pwd) utility/src/main/java/org/oppia/android/util/math/MathTokenizer.kt $(pwd)/reports min_coverage=20
//   bazel run //scripts:run_coverage -- $(pwd) utility/src/main/java/org/oppia/android/util/math/MathTokenizer.kt $(pwd)/reports format=markdown
//   bazel run //scripts:run_coverage -- $(pwd) utility/src/main/java/org/oppia/android/util/math/MathTokenizer.kt $(pwd)/reports format=html
//   bazel run //scripts:run_coverage -- $(pwd) utility/src/main/java/org/oppia/android/util/math/MathTokenizer.kt $(pwd)/reports min_coverage=20 format=markdown,html
//
// The script:
// 1. Finds the corresponding test file specific to the file to be checked.
//   a. If the file has no test & isn't exempted, the script should fail.
//   b. If the file has no test & is exempted, the script should output as such.
// 2. Uses CoverageRunner to run the corresponding test file to generate a report.
// 3. Outputs code coverage percentage based on the report.
//   a. If the file has a code coverage percentage exemption, it's also outputted at this point.
// 4. If formats are specified, CoverageReporter should be used to generate reports for each specified format in the destination report_output_dir directory.
// 5. If min_coverage is specified, compares the computed code coverage with the minimum specified. The script should fail iff the file has less than the minimum specified coverage.
fun main(vararg args: String)

class RunCoverage {
  fun runCoverage(targetFile: String, outputFormats: List<CoverageReporter.ReportFormat>)
}

script_exemptions.proto:

// The old TestFileExemptions proto (for reference).
message TestFileExemptionsOld {
  repeated string exempted_file_path = 1;
}

message TestFileExemptions {
  repeated TestFileExemption test_file_exemption = 1;
  
  message TestFileExemption {
    string exempted_file_path = 1;
    oneof exemption_type {
      bool test_file_not_required = 2;
      int32 override_min_coverage_percent_required = 3;
    }
  }
}

Describe alternatives you've considered

No response

Additional context

This is the high-level tracking issue corresponding to https://github.com/oppia/oppia/wiki/Google-Summer-of-Code-2024#41-code-coverage-support-and-enforcement.

Note that this project includes work that relate to the following issues: #1497, #1726, #1727, and #1728.

@BenHenning BenHenning added enhancement End user-perceivable enhancements. triage needed labels Feb 17, 2024
@BenHenning BenHenning self-assigned this Feb 17, 2024
@oppia oppia locked and limited conversation to collaborators Feb 17, 2024
@BenHenning
Copy link
Member Author

NB: This issue is locked to ensure that it only contains updates for requirements. If you have questions regarding this project, please use its corresponding discussion category: https://github.com/oppia/oppia-android/discussions/categories/gsoc-q-a-4-1-code-coverage-support.

@BenHenning
Copy link
Member Author

NB: The main issue comment has been updated to include the technical details directly rather than a link to a Gist (so that we can easily change this if needed). None of the technical requirements have actually changed.

@oppia oppia unlocked this conversation May 8, 2024
@Rd4dev
Copy link
Collaborator

Rd4dev commented Jun 4, 2024

Milestone 1

✅ PR 1.1 - #5423

Introduce RunCoverage and CoverageRunner utilities to run code coverage for a specific bazel test target.

Starting Date Creation Date Merge Date
27-05-2024 01-06-2024 03-06-2024

Tasks

Task Due Date
✅ Setup the workspace with bazel 6.5.0. 27-05-2024
✅ Introduce RunCoverage script. 27-05-2024
✅ Introduce CoverageRunner utility to call Bazel command. 28-05-2024
✅ Add implementation in BazelClient to execute Bazel coverage command. 29-05-2024
✅ Add tests for execution of Bazel coverage command through RunCoverage script. 01-06-2024

As per Schedule Slip

✅ PR 1.2 - #5426

Updating the test exemption script.

Starting Date Creation Date Merge Date
01-06-2024 03-06-2024 05-06-2024

Revised Dates

Starting Date Creation Date Merge Date
17-06-2024 18-06-2024 20-06-2024

Tasks

Task Original Due Date Revised Due Date
✅ Update the test exemption check script proto. 01-06-2024 17-06-2024
✅ Update the exemption_type data. 02-06-2024 17-06-2024
✅ Add / Update tests for TestFileCheckTest scripts as required. 03-06-2024 18-06-2024

✅ PR 1.3 - #5433

Update / Implement script to run code coverage for a specific file replacing test target argument.

Starting Date Creation Date Merge Date
03-06-2024 08-06-2024 10-06-2024

Revised Dates

Starting Date Creation Date Merge Date
19-06-2024 20-06-2024 22-06-2024

Tasks

Task Original Due Date Revised Due Date
✅ Update the script to take in a file as argument instead of target. 03-06-2024 19-06-2024
✅ Check with the exempted test file list to log the coverage ratio to 0%. 03-06-2024 19-06-2024
✅ Add functionality to map the file name to related test targets. 04-06-2024 19-06-2024
✅ Include execution for related Test and LocalTest Targets. 06-06-2024 20-06-2024
✅ Add tests for execution of Bazel coverage command with filename. 08-06-2024 20-06-2024

✅ PR 1.4 - #5439

Interpreting the results and building proto for data processing.

Starting Date Creation Date Merge Date
08-06-2024 13-06-2024 15-06-2024

Revised Dates

Starting Date Creation Date Merge Date
21-06-2024 23-06-2024 25-06-2024

Tasks

Task Original Due Date Revised Due Date
✅ Extract the coverage data path from the results. 08-06-2024 21-06-2024
✅ Introduce coverage.proto to store the produced coverage data. 08-06-2024 21-06-2024
✅ Parse the coverage data and store them to the proto. 10-06-2024 21-06-2024
✅ Isolate the coverage data to only contain the target coverage data. 11-06-2024 22-06-2024
✅ Include coverage data to proto for any related tests - 'LocalTest'. 12-06-2024 22-06-2024
✅ Add tests to validate acquired coverage data stored in the proto. 13-06-2024 23-06-2024

✅ PR 1.5 - #5443

Introduce CoverageReporter utility and generate the code coverage report.

Starting Date Creation Date Merge Date
13-06-2024 20-06-2024 22-06-2024

Revised Dates

Starting Date Creation Date Merge Date
24-06-2024 28-06-2024 30-06-2024

Tasks

Task Original Due Date Revised Due Date
✅ Introduce CoverageReporter utility to generate the code coverage report. 13-06-2024 24-06-2024
✅ Compute the coverage Ratio. 13-06-2024 24-06-2024
✅ Generate Markdown report with proto. 15-06-2024 25-06-2024
✅ Generate HTML report with proto. 18-06-2024 27-06-2024
✅ Add tests to validate the Markdown and HTML report generation and coverage ratios. 20-06-2024 28-06-2024

Buffer Time

To work on reviews and code changes.

Starting Date Creation Date Merge Date
22-06-2024 26-06-2024 28-06-2024

Midpoint Evaluation

Code Reviews and Evaluations

Starting Date Creation Date Merge Date
28-06-2024 08-07-2024 12-07-2024

Milestone 2

✅ PR 2.1 - #5459

Implement Aggregate Coverage Analysis for many:1 relationship files

Starting Date Creation Date Merge Date
12-07-2024 15-07-2024 19-07-2024

Tasks

Task Due Date
✅ Aggregate by calculating multiple resultant coverage reports into one single report 12-07-2024
✅ Generate Markdown reports with the aggregated coverage report. 13-07-2024
✅ Generate Markdown reports with the aggregated coverage report. 14-07-2024
✅ Update test cases to validate many to one relationship coverage analysis 15-07-2024

✅ PR 2.2 - #5461

Enable Coverage Generation for a list of files

Starting Date Creation Date Merge Date
16-07-2024 23-07-2024 27-07-2024

Tasks

Task Due Date
✅ Let the command-line args take in a list of string (files). 16-07-2024
✅ Update the implementation to handle mapping of multiple files to appropriate targets. 17-07-2024
✅ Update the implementation to generate proto with multiple file inputs. 19-07-2024
✅ Update the implementation to generate markdown with multiple file inputs. 21-07-2024
✅ Update the implementation to generate html with multiple file inputs. 22-07-2024
✅ Update the test cases to handle multiple file inputs and outputs. 23-07-2024

✅ PR 2.3 - #5465

Introduce new CI workflow for code coverage

Starting Date Creation Date Merge Date
24-07-2024 30-07-2024 03-08-2024

Tasks

Task Due Date
✅ Introduce a new CI workflow that utilizes the coverage script. 24-07-2024
✅ Configure it to run it with and without cache. 25-07-2024
✅ Configure it to run as a series of buckets. 27-07-2024
✅ Configure it to fail if it's below the threshold. 28-07-2024
✅ Configure it to generate markdown reports. 29-07-2024
✅ (Updated) Run Coverage Check only after Unit Test Pass. 30-07-2024
✅ Analyze the new runs. 30-07-2024

✅ PR 2.4 - #5469

Upload generated markdown report as comment

Starting Date Creation Date Merge Date
31-07-2024 02-08-2024 06-08-2024

Tasks

Task Due Date
✅ Modify the workflow to upload markdown report as a comment. 01-08-2024
✅ (Updated) Combine generated reports from each run into one final report. 01-08-2024
✅ Review and refine markdown upload implementation. 02-08-2024

✅ PR 2.5 - #5466

Fix/replace cancellation workflow

Starting Date Creation Date Merge Date
03-08-2024 07-08-2024 10-08-2024

Tasks

Task Due Date
✅ Identify issues with the current cancellation workflow. 03-08-2024
✅ Execute and analyze cancellation with styfle - PR #2890. 05-08-2024
✅ Develop replacement or fix for the cancellation workflow. 06-08-2024
✅ Validate the new cancellation workflow. 07-08-2024

PR 2.6 - #5483

Create wiki page explaining code coverage usage, limitations, file issues for coverage gaps, and test writing tips

Starting Date Creation Date Merge Date
08-08-2024 10-08-2024 12-08-2024

Tasks

Task Due Date
✅ Introduce new wiki page for "how to use the code coverage tool". 08-08-2024
✅ Introduce new wiki page for "how to write tests with good behavioral coverage". 09-08-2024
✅ Introduce new wiki page for "Limitations of the code coverage tool". 10-08-2024
✅ File issues for missing / incorrect code coverages. 10-08-2024
Old Milestone 2 Timeline # Milestone 2

PR 2.1

Introduce new CI workflow for code coverage

Starting Date Creation Date Merge Date
12-07-2024 22-07-2024 24-07-2024

Tasks

Task Due Date
⬜ Introduce a new CI workflow that utilizes the coverage script. 13-07-2024
⬜ Configure it to run it with and without cache. 15-07-2024
⬜ Configure it to run as a series of buckets. 18-07-2024
⬜ Configure it to fail if it's below the threshold. 20-07-2024
⬜ Configure it to generate markdown reports. 22-07-2024
⬜ Analyze the new runs. 22-07-2024

PR 2.2

Upload generated markdown report as comment

Starting Date Creation Date Merge Date
22-07-2024 26-07-2024 28-07-2024

Tasks

Task Due Date
⬜ Modify the workflow to upload markdown report as a comment. 24-07-2024
⬜ Test markdown report upload feature. 25-07-2024
⬜ Review and refine markdown upload implementation. 26-07-2024

PR 2.3

Fix/replace cancellation workflow

Starting Date Creation Date Merge Date
26-07-2024 01-08-2024 03-08-2024

Tasks

Task Due Date
⬜ Identify issues with the current cancellation workflow. 26-07-2024
⬜ Execute and analyze cancellation with styfle - PR #2890. 28-07-2024
⬜ Develop replacement or fix for the cancellation workflow. 30-07-2024
⬜ Validate the new cancellation workflow. 01-08-2024

PR 2.4

Create wiki page explaining code coverage usage, limitations, file issues for coverage gaps, and test writing tips

Starting Date Creation Date Merge Date
01-08-2024 04-08-2024 06-08-2024

Tasks

Task Due Date
⬜ Introduce new wiki page for "how to use the code coverage tool". 01-08-2024
⬜ Introduce new wiki page for "how to write tests with good behavioral coverage". 02-08-2024
⬜ Introduce new wiki page for "Limitations of the code coverage tool". 03-08-2024
⬜ File issues for missing / incorrect code coverages. 04-08-2024

Buffer Time

To work on reviews and code changes.

Starting Date Creation Date Merge Date
06-08-2024 10-08-2024 12-08-2024

Final Evaluation

Code Reviews and Evaluations

Starting Date Creation Date Merge Date
12-08-2024 26-08-2024 03-09-2024

Spare Intervals

Spare intervals to fix any further issues.

Starting Date Creation Date Merge Date
03-09-2024 N/A End of GSoC period

@DubeySandeep
Copy link
Member

@Rd4dev The dates for milestone 1(creation date, some due date), can you please fix those? Also, I don't see any update on the milestone/PRs task, can you please actively update this table? (whenever you complete a task or get a PR merged)

@Rd4dev
Copy link
Collaborator

Rd4dev commented Jun 5, 2024

@DubeySandeep Corrected the dates and updated the table to reflect the current progress, will ensure it remains up to date in the future.

@BenHenning
Copy link
Member Author

Continuing the discussion from #4886 regarding why some app and testing module tests seem to fail to run in coverage. Copying in my comment from that thread:

Thanks @Rd4dev. It's interesting to see the differences with Gradle.

I spent some time today trying a bunch of different things to try and even get a newer version of JaCoCo running. It would be a lot to summarize, so here's the very high-level:

  • We can build a deploy version of our Robolectric tests, but actually directly running them via JVM CLI is quite hard because there's a lot of environment setup stuff Bazel does behind the scenes.

  • It is possible to set up a custom Java toolchain to replace the built-in one that comes with Bazel (so that we can swap out the JaCoCo binary it points to).

  • Swapping out JaCoCo is hard. Bazel builds its own wrapper around the JaCoCo library rather than using its CLI, so we'd have to build our own version of that which points to a newer JaCoCo library.

  • The above isn't too much of an issue, except Bazel is in a weird mid-migration state where it's moving its remote_java_tools dependencies to a separate repo, but it's in between state is essentially:

    • Bazel itself instruments remote_java_tools when building (since rules_java still just points to the native Java rules as they haven't yet been fully migrated to Starlark).
    • Bazel does the above by pointing to remote_java_tools prebuilt deployments which are generated using a script that points back to Bazel in order to create the deployable Jars for its package.

That's as far as I've made it to updating JaCoCo even for a light test. Essentially next steps would be:

  • Build a custom remote_java_tools deployment that contains a newer version of JaCoCo.
  • Upload this somewhere (like a GitHub fork).
  • Update my local checkout of Bazel to point to these new packages & rebuild.
  • Use the locally built Bazel binary to try and run coverage.

It would probably be much easier to try and create a similar failure case outside of Bazel entirely (i.e. using direct javac and JaCoCo's CLIs), but without a better sense of what the root issue is that will presumably be hard to come up with. Hopefully I can make headway on the above to at least try to use a newer version of JaCoCo to see if that makes any difference on the failures.

Will add any other findings I have here.

@BenHenning
Copy link
Member Author

I found that, interestingly, two things:

  1. Coverage is failing for some groups of tests outside of app module.
  2. All app module tests that have their own explicit test targets work with coverage.

This is leading me to believe that there may be a problem with the top-level test targets that are defined, by default, for tests with no dedicated BUILD files. I need to dig a bit more to confirm this (& maybe come up with some explanation as to why), but if this is right then the pathway to fixing it is at least fairly straightforward.

@BenHenning
Copy link
Member Author

BenHenning commented Jun 20, 2024

Okay I'm almost certain this is the problem area, though I'm still unsure why. The following command passes for me (running all non-top-level tests):

bazel coverage //{app,domain,testing,utility,data,scripts}/src/...

However, this fails:

bazel coverage --keep_going //domain/...

This fails with 84 targets that don't build. I took a specific example: MultipleChoiceInputEqualsRuleClassifierProviderTest. This test fails to build with coverage as-is, but moving it to its own target causes it to pass.

I'm now going to investigate the differences between the local declaration and top-level declaration for this test to see if it's something that's actually fixable.

Edit: Ah, this is interesting. I'm trying a different classifier:

bazel coverage //domain:src/test/java/org/oppia/android/domain/classify/rules/imageClickInput/ImageClickInputIsInRegionRuleClassifierProviderTest

I get the following build error:

INFO: From KotlinCompile @//domain/src/main/java/org/oppia/android/domain/classify/rules/dragAndDropSortInput:drag_and_drop_sort_input_providers_kt { kt: 4, java: 0, srcjars: 0 } for k8:
Jun 20, 2024 11:10:10 PM worker request 0
SEVERE: Uncaught exception
java.io.IOException: Error while instrumenting /tmp/pwd7199928558572205927/_kotlinc/domain_src_main_java_org_oppia_android_domain_classify_rules_dragAndDropSortInput-drag_and_drop_sort_input_providers_kt_jvm/classes/org/oppia/android/domain/classify/rules/dragAndDropSortInput/DragDropSortInputHasElementXAtPositionYClassifierProvider$createRuleClassifier$$inlined$createDoubleInputClassifier$2.class with JaCoCo 0.8.9.202303300400/461ebf3.
        at org.jacoco.core.instr.Instrumenter.instrumentError(Instrumenter.java:162)
        at org.jacoco.core.instr.Instrumenter.instrument(Instrumenter.java:111)
        at org.jacoco.core.instr.Instrumenter.instrument(Instrumenter.java:136)
        at org.jacoco.core.instr.Instrumenter.instrument(Instrumenter.java:156)
        at io.bazel.kotlin.builder.tasks.jvm.JacocoInstrumentationKt$instrumentRecursively$visitor$1.visitFile(JacocoInstrumentation.kt:66)
        at io.bazel.kotlin.builder.tasks.jvm.JacocoInstrumentationKt$instrumentRecursively$visitor$1.visitFile(JacocoInstrumentation.kt:52)
        at java.base/java.nio.file.Files.walkFileTree(Files.java:2725)
        at java.base/java.nio.file.Files.walkFileTree(Files.java:2797)
        at io.bazel.kotlin.builder.tasks.jvm.JacocoInstrumentationKt.instrumentRecursively(JacocoInstrumentation.kt:73)
        at io.bazel.kotlin.builder.tasks.jvm.JacocoInstrumentationKt.createCoverageInstrumentedJar(JacocoInstrumentation.kt:21)
        at io.bazel.kotlin.builder.tasks.jvm.KotlinJvmTaskExecutor$execute$1$1$6.invoke(KotlinJvmTaskExecutor.kt:112)
        at io.bazel.kotlin.builder.tasks.jvm.KotlinJvmTaskExecutor$execute$1$1$6.invoke(KotlinJvmTaskExecutor.kt:112)
        at io.bazel.kotlin.builder.toolchain.CompilationTaskContext.execute(CompilationTaskContext.kt:153)
        at io.bazel.kotlin.builder.toolchain.CompilationTaskContext.execute(CompilationTaskContext.kt:145)
        at io.bazel.kotlin.builder.tasks.jvm.KotlinJvmTaskExecutor$execute$1.invoke(KotlinJvmTaskExecutor.kt:112)
        at io.bazel.kotlin.builder.tasks.jvm.KotlinJvmTaskExecutor$execute$1.invoke(KotlinJvmTaskExecutor.kt:54)
        at io.bazel.kotlin.builder.toolchain.CompilationTaskContext.execute(CompilationTaskContext.kt:153)
        at io.bazel.kotlin.builder.toolchain.CompilationTaskContext.execute(CompilationTaskContext.kt:145)
        at io.bazel.kotlin.builder.tasks.jvm.KotlinJvmTaskExecutor.execute(KotlinJvmTaskExecutor.kt:54)
        at io.bazel.kotlin.builder.tasks.KotlinBuilder.executeJvmTask(KotlinBuilder.kt:209)
        at io.bazel.kotlin.builder.tasks.KotlinBuilder.build(KotlinBuilder.kt:102)
        at io.bazel.kotlin.builder.tasks.CompileKotlin.invoke(CompileKotlin.kt:27)
        at io.bazel.worker.PersistentWorker$workTo$1.invoke(PersistentWorker.kt:97)
        at io.bazel.worker.PersistentWorker$workTo$1.invoke(PersistentWorker.kt:97)
        at io.bazel.worker.WorkerContext$TaskContext.resultOf(WorkerContext.kt:128)
        at io.bazel.worker.WorkerContext.doTask(WorkerContext.kt:156)
        at io.bazel.worker.PersistentWorker$start$1$1$producer$1$1.invoke$lambda$0(PersistentWorker.kt:70)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.lang.IllegalStateException: Cannot process instrumented class org/oppia/android/domain/classify/rules/dragAndDropSortInput/DragDropSortInputHasElementXAtPositionYClassifierProvider$createRuleClassifier$$inlined$createDoubleInputClassifier$2. Please supply original non-instrumented classes.
        at org.jacoco.core.internal.instr.InstrSupport.assertNotInstrumented(InstrSupport.java:238)
        at org.jacoco.core.internal.instr.ClassInstrumenter.visitMethod(ClassInstrumenter.java:65)
        at org.jacoco.core.internal.flow.ClassProbesAdapter.visitMethod(ClassProbesAdapter.java:66)
        at com.google.testing.coverage.jarjar.org.objectweb.asm.ClassReader.readMethod(ClassReader.java:1353)
        at com.google.testing.coverage.jarjar.org.objectweb.asm.ClassReader.accept(ClassReader.java:744)
        at com.google.testing.coverage.jarjar.org.objectweb.asm.ClassReader.accept(ClassReader.java:424)
        at org.jacoco.core.instr.Instrumenter.instrument(Instrumenter.java:91)
        at org.jacoco.core.instr.Instrumenter.instrument(Instrumenter.java:109)
        ... 31 more

I didn't notice this before, but I find it especially noteworthy that the failure is tied to DragDropSortInputHasElementXAtPositionYClassifierProvider which is completely unrelated to the test that I'm trying to build. I find this interesting because it's an entirely different target, so I'm not sure why it's trying to build the other target (even if they're both umodularized top-level defined domain tests).

Running the coverage request multiple times tends to fail with a different test each time. I'm also noticing a bunch of compile targets are kicking off when running coverage when they really shouldn't.

Edit 2: Ah, I misread the above. These are production libraries that are failing in the context of the test build, not other tests. That sounds more like some sort of package conflict is happening since so many tests are packed in the same top-level package for unmodularized tests. Still digging.

@BenHenning
Copy link
Member Author

BenHenning commented Jun 20, 2024

So I've tried a few things to try and fix this: replacing the '/' part of the top-level test names with '_' (in case there are directory pathing assumptions being made somewhere in the coverage pipeline), forcing a modularized test into a subdirectory (for the same check), and bring closer parity between top-level unmodularized (failing) tests with modularized (passing tests). Despite these, I still can't find an obvious reason why prod targets are failing in the context of non-modularized tests.

It very much seems like there's some sort of instrumentation duplication happening for production targets shared across tests. It's not obvious to me why this is happening, nor is it that modularized multi-test packages build & run fine (but not the top-level unmodularized tests). It could be a number of tests thing, but that implies a (scary) hidden limitation of the coverage pipeline. Alternatively, there could just be some sort of highly specific pathing assumption happening somewhere that I can't easily isolate.

The best path forward is probably to finish the modularization work. The good news is that those PRs are very close to being ready to go into review (since they were shortly after #4886 in the Bazel PR chain). The bad news is that these are very large and complex PRs that will probably require significant time to bring back into review.

I'm going to see if we can at least disable the broken tests for coverage for now, but I'm not sure if that's actually possible.

Edit: Per bazelbuild/bazel#21520 it seems we are not able to easily selectively disable certain tests for code coverage. :( I think that means we must work to bring in modularization in order to address this. I will dig to see just how difficult that effort will be.

@Rd4dev
Copy link
Collaborator

Rd4dev commented Jun 21, 2024

I'm going to see if we can at least disable the broken tests for coverage for now, but I'm not sure if that's actually possible.

Hey @BenHenning,

If disabling the broken tests directly through Bazel isn't an option, could we consider using our existing test_files_exemption to add a field for exempting tests from coverage? Since we already check for exemptions at the beginning and skip execution if a file is exempted, we could apply the same logic to coverage checks. This wouldn't fix the underlying issue but if skipping those coverages is something we can do then, I am wondering if this could serve as a temporary workaround to skip the problematic coverage executions.

@BenHenning
Copy link
Member Author

I'm going to see if we can at least disable the broken tests for coverage for now, but I'm not sure if that's actually possible.

Hey @BenHenning,

If disabling the broken tests directly through Bazel isn't an option, could we consider using our existing test_files_exemption to add a field for exempting tests from coverage? Since we already check for exemptions at the beginning and skip execution if a file is exempted, we could apply the same logic to coverage checks. This wouldn't fix the underlying issue but if skipping those coverages is something we can do then, I am wondering if this could serve as a temporary workaround to skip the problematic coverage executions.

I think that's a good backup option @Rd4dev. I want to see if it's possible to bring forward the changes that would ultimately unblock the work (since we want them, anyway), but if that ends up being infeasible I think your approach is the best option.

BenHenning added a commit that referenced this issue Jun 24, 2024
…tion format (#5426)

<!-- READ ME FIRST: Please fill in the explanation section below and
check off every point from the Essential Checklist! -->
## Explanation
<!--
- Explain what your PR does. If this PR fixes an existing bug, please
include
- "Fixes #bugnum:" in the explanation so that GitHub can auto-close the
issue
  - when this PR is merged.
  -->

Fixes part of #5343

**Project**
[PR 1.2 of Project 4.1]
This PR is based on develop as it had no other dependency with other
PRs.

### Changes Implemented
This PR implements updates to enhance the handling of file exemptions
and code coverage settings:

1. Updates `script_exemptions.proto` to support two possible states:
   - Exemption from requiring a test file (current behavior).
- Override of the minimum code coverage to meet a specific percentage
(including 0%).

2. Aligns `test_file_exemptions.textproto` with the new proto format.

3. Modifies `TestFileCheck.kt` to integrate the updated proto format.

## Project Context
In Project 4.1, we are introducing code coverage capabilities where
certain files may require exemptions from the default minimum code
coverage percentage. These exemptions can now be managed in
`test_file_exemptions.textproto` by setting the
`override_min_coverage_percentage`.

## Implementation Details
Initially, I explored using the `TodoOpenCheck` regeneration structure
to implement these changes. However, due to significant differences in
regeneration requirements (creating a new proto format to regenerate the
exemptions list), conflicts arose with
`generate_test_file_assets_list_from_text_protos`.

Given that the regeneration process is solely aimed at rebuilding the
textproto file and no longer serves any other purpose in this project, I
opted to manually compile a list of exempted files and used it to
generate the new proto format. I then transferred this newly generated
format to the textproto file. The regeneration implementation can be
found in my [local test_exemption
branch](Rd4dev@189a1da#diff-fd100a053f2b965df76d989b0d97b5400c051c7fff9507afc0d891cfaf36e238R925)

Post-generation, the regeneration functionality was removed, as it no
longer aligns with the project's needs. Further validation and
adjustments, if necessary, will be discussed with Ben and implemented.


## Essential Checklist
<!-- Please tick the relevant boxes by putting an "x" in them. -->
- [x] The PR title and explanation each start with "Fix #bugnum: " (If
this PR fixes part of an issue, prefix the title with "Fix part of
#bugnum: ...".)
- [x] Any changes to
[scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets)
files have their rationale included in the PR explanation.
- [x] The PR follows the [style
guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide).
- [x] The PR does not contain any unnecessary code changes from Android
Studio
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)).
- [x] The PR is made from a branch that's **not** called "develop" and
is up-to-date with "develop".
- [x] The PR is **assigned** to the appropriate reviewers
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)).

## For UI-specific PRs only
<!-- Delete these section if this PR does not include UI-related
changes. -->
If your PR includes UI-related changes, then:
- Add screenshots for portrait/landscape for both a tablet & phone of
the before & after UI changes
- For the screenshots above, include both English and pseudo-localized
(RTL) screenshots (see [RTL
guide](https://github.com/oppia/oppia-android/wiki/RTL-Guidelines))
- Add a video showing the full UX flow with a screen reader enabled (see
[accessibility
guide](https://github.com/oppia/oppia-android/wiki/Accessibility-A11y-Guide))
- For PRs introducing new UI elements or color changes, both light and
dark mode screenshots must be included
- Add a screenshot demonstrating that you ran affected Espresso tests
locally & that they're passing

---------

Co-authored-by: Ben Henning <[email protected]>
BenHenning added a commit that referenced this issue Jun 24, 2024
… specific bazel test target (#5423)

<!-- READ ME FIRST: Please fill in the explanation section below and
check off every point from the Essential Checklist! -->
## Explanation
<!--
- Explain what your PR does. If this PR fixes an existing bug, please
include
- "Fixes #bugnum:" in the explanation so that GitHub can auto-close the
issue
  - when this PR is merged.
  -->

Fixes part of #5343 

### Project
[PR 1.1 of Project 4.1]

### This PR introduces 2 utilities:
1. **RunCoverageForTestTarget** - A new script for running code coverage
locally
2. **CoverageRunner** - A new scripting utility for running code
coverage for a selected target

### Source:
- The RunCoverageForTestTarget script takes in a test target as an
argument.
- The CoverageRunner executes the bazel coverage command asynchronously
utilizing bazelClient.
- Implementation is added to BazelClient to execute code coverage
commands.
- The getCoverage() from CoverageRunner returns a list of string
containing the output result.
- The result is parsed via parseCoverageDataFile() to extract the
coverage.dat file path.

The extracted coverage.dat file will then be used to acquire the actual
coverage data.

### Tests:
- Tests are introduced for RunCoverageForTestTarget and CoverageRunner
utilities.
- To test the execution, sample test files are generated and utilized
for testing.
- Sample test files include - 
  - [sourceFile.kt, BUILD.bazel], 
  - [testFile.kt,BUILD.bazel], 
  - WORKSPACE 
  in their appropriate subpackages
- To add functionality to introduce source and test files with content
TestBazelWorkspace utility is utilized.
- The addSourceAndTestFileWithContent() in TestBazelWorkspace utility
achieves this.
- Tests are added for
  - BazelClientTest
  - TestBazelWorkspaceTest

## Essential Checklist
<!-- Please tick the relevant boxes by putting an "x" in them. -->
- [x] The PR title and explanation each start with "Fix #bugnum: " (If
this PR fixes part of an issue, prefix the title with "Fix part of
#bugnum: ...".)
- [x] Any changes to
[scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets)
files have their rationale included in the PR explanation.
- [x] The PR follows the [style
guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide).
- [x] The PR does not contain any unnecessary code changes from Android
Studio
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)).
- [x] The PR is made from a branch that's **not** called "develop" and
is up-to-date with "develop".
- [x] The PR is **assigned** to the appropriate reviewers
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)).

## For UI-specific PRs only
<!-- Delete these section if this PR does not include UI-related
changes. -->
If your PR includes UI-related changes, then:
- Add screenshots for portrait/landscape for both a tablet & phone of
the before & after UI changes
- For the screenshots above, include both English and pseudo-localized
(RTL) screenshots (see [RTL
guide](https://github.com/oppia/oppia-android/wiki/RTL-Guidelines))
- Add a video showing the full UX flow with a screen reader enabled (see
[accessibility
guide](https://github.com/oppia/oppia-android/wiki/Accessibility-A11y-Guide))
- For PRs introducing new UI elements or color changes, both light and
dark mode screenshots must be included
- Add a screenshot demonstrating that you ran affected Espresso tests
locally & that they're passing

---------

Co-authored-by: Ben Henning <[email protected]>
@BenHenning
Copy link
Member Author

So I spent a lot of time this week trying to get up to a point of verifying this result, but I couldn't quite get one of the modularization PRs building again (the prerequisites #4920 and #4978 took a long time to get working). I'll need to revisit this when I next have availability (in July).

@Rd4dev
Copy link
Collaborator

Rd4dev commented Jul 17, 2024

So I spent a lot of time this week trying to get up to a point of verifying this result, but I couldn't quite get one of the modularization PRs building again (the prerequisites #4920 and #4978 took a long time to get working). I'll need to revisit this when I next have availability (in July).

Hey @BenHenning,

I tried to see if I could make any conversion to package-specific targets, but I'm not sure if I did it correctly or if the coverage results are accurate. I wanted to update you on how things went (in case any of this could be useful for future reference).

domain module

As mentioned earlier, I first tried to run the coverage for the domain module's MultipleChoiceInputEqualsRuleClassifierProviderTest with the top-level package label version, but it failed to retrieve coverage.

//domain:src/test/java/org/oppia/android/domain/classify/rules/multiplechoiceinput/MultipleChoiceInputEqualsRuleClassifierProviderTest

This fails with 84 targets that don't build. I took a specific example: MultipleChoiceInputEqualsRuleClassifierProviderTest. This test fails to build with coverage as-is, but moving it to its own target causes it to pass.

So, I tried to refactor it to package-relative label, and that yielded a desirable output with coverage data containing coverages for the source file MultipleChoiceInputEqualsRuleClassifierProvider.kt (since the source files already had their own targets, it was straightforward).

//domain/src/test/java/org/oppia/android/domain/classify/rules/multiplechoiceinput:MultipleChoiceInputEqualsRuleClassifierProviderTest
Coveragae Result
SF:domain/src/main/java/org/oppia/android/domain/classify/rules/multiplechoiceinput/MultipleChoiceInputEqualsRuleClassifierProvider.kt
FN:17,org/oppia/android/domain/classify/rules/multiplechoiceinput/MultipleChoiceInputEqualsRuleClassifierProvider::<init> (Lorg/oppia/android/domain/classify/rules/GenericRuleClassifier$Factory;)V
FN:22,org/oppia/android/domain/classify/rules/multiplechoiceinput/MultipleChoiceInputEqualsRuleClassifierProvider::createRuleClassifier ()Lorg/oppia/android/domain/classify/RuleClassifier;
FN:33,org/oppia/android/domain/classify/rules/multiplechoiceinput/MultipleChoiceInputEqualsRuleClassifierProvider::matches (IILorg/oppia/android/domain/classify/ClassificationContext;)Z
FNDA:1,org/oppia/android/domain/classify/rules/multiplechoiceinput/MultipleChoiceInputEqualsRuleClassifierProvider::<init> (Lorg/oppia/android/domain/classify/rules/GenericRuleClassifier$Factory;)V
FNDA:1,org/oppia/android/domain/classify/rules/multiplechoiceinput/MultipleChoiceInputEqualsRuleClassifierProvider::createRuleClassifier ()Lorg/oppia/android/domain/classify/RuleClassifier;
FNDA:1,org/oppia/android/domain/classify/rules/multiplechoiceinput/MultipleChoiceInputEqualsRuleClassifierProvider::matches (IILorg/oppia/android/domain/classify/ClassificationContext;)Z
FNF:3
FNH:3
BRDA:33,0,0,1
BRDA:33,0,1,1
BRF:2
BRH:2
DA:17,1
DA:18,1
DA:22,1
DA:23,1
DA:24,1
DA:33,1
LH:6
LF:6
end_of_record

app module

Then, I tried replicating the same behavior for SplashActivity, which was more complex :| so I skipped that and instead tried doing FractionParsingUiError.kt in the app module. While the top-level package label coverage run failed, converting it to a package-relative label it eventually passed the coverage run,

$ bazel coverage //app/src/test/java/org/oppia/android/app/parser:FractionParsingUiErrorTest --instrumentation_filter=//app/...

image

BUT the coverage data didn't have the desired output. Specifically, the coverage result should provide the coverage data related to the source file, i.e., for FractionParsingUiErrorTest.kt, it should point to -> SF: FractionParsingUiError.kt, but it was not there. Instead, it had coverage data related to FractionParsingUiErrorTest.

Coverage Results (Lengthy Report Inside)
cat /home/rddev/.cache/bazel/_bazel_rddev/81159660e9f0a21d3064c6805850402d/execroot/__main__/bazel-out/k8-fastbuild/testlogs/app/src/test/java/org/oppia/android/app/parser/FractionParsingUiErrorTest/coverage.dat
SF:app/src/main/java/org/oppia/android/app/activity/ActivityComponent.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/ActivityComponentFactory.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/ActivityIntentFactories.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/ActivityScope.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/InjectableAppCompatActivity.kt
FN:19,org/oppia/android/app/activity/InjectableAppCompatActivity::<init> ()V
FN:29,org/oppia/android/app/activity/InjectableAppCompatActivity::attachBaseContext (Landroid/content/Context;)V
FN:48,org/oppia/android/app/activity/InjectableAppCompatActivity::createFragmentComponent (Landroidx/fragment/app/Fragment;)Lorg/oppia/android/app/fragment/FragmentComponent;
FN:92,org/oppia/android/app/activity/InjectableAppCompatActivity::ensureLayoutDirection ()V
FN:26,org/oppia/android/app/activity/InjectableAppCompatActivity::getActivityComponent ()Lorg/oppia/android/app/activity/ActivityComponent;
FN:52,org/oppia/android/app/activity/InjectableAppCompatActivity::getAppLanguageActivityInjector ()Lorg/oppia/android/app/translation/AppLanguageActivityInjector;
FN:38,org/oppia/android/app/activity/InjectableAppCompatActivity::onCreate (Landroid/os/Bundle;)V
FN:43,org/oppia/android/app/activity/InjectableAppCompatActivity::onCreate (Landroid/os/Bundle;Landroid/os/PersistableBundle;)V
FN:55,org/oppia/android/app/activity/InjectableAppCompatActivity::onInitializeActivityComponent (Landroid/content/Context;)V
FN:67,org/oppia/android/app/activity/InjectableAppCompatActivity::onInitializeLocalization (Landroid/content/Context;)Landroid/content/res/Configuration;
FN:26,org/oppia/android/app/activity/InjectableAppCompatActivity::setActivityComponent (Lorg/oppia/android/app/activity/ActivityComponent;)V
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::<init> ()V
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::attachBaseContext (Landroid/content/Context;)V
FNDA:0,org/oppia/android/app/activity/InjectableAppCompatActivity::createFragmentComponent (Landroidx/fragment/app/Fragment;)Lorg/oppia/android/app/fragment/FragmentComponent;
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::ensureLayoutDirection ()V
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::getActivityComponent ()Lorg/oppia/android/app/activity/ActivityComponent;
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::getAppLanguageActivityInjector ()Lorg/oppia/android/app/translation/AppLanguageActivityInjector;
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::onCreate (Landroid/os/Bundle;)V
FNDA:0,org/oppia/android/app/activity/InjectableAppCompatActivity::onCreate (Landroid/os/Bundle;Landroid/os/PersistableBundle;)V
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::onInitializeActivityComponent (Landroid/content/Context;)V
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::onInitializeLocalization (Landroid/content/Context;)Landroid/content/res/Configuration;
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::setActivityComponent (Lorg/oppia/android/app/activity/ActivityComponent;)V
FNF:11
FNH:9
BRDA:26,0,0,1
BRDA:26,0,1,0
BRDA:29,0,0,0
BRDA:29,0,1,1
BRDA:29,0,2,0
BRDA:29,0,3,1
BRDA:34,0,0,0
BRDA:34,0,1,1
BRDA:76,0,0,0
BRDA:76,0,1,1
BRDA:76,0,2,0
BRDA:76,0,3,1
BRF:12
BRH:6
DA:19,1
DA:20,1
DA:26,1
DA:29,1
DA:30,0
DA:32,1
DA:33,1
DA:34,1
DA:35,1
DA:38,1
DA:39,1
DA:40,1
DA:43,0
DA:44,0
DA:45,0
DA:48,0
DA:49,0
DA:52,1
DA:55,1
DA:56,1
DA:57,1
DA:67,1
DA:68,1
DA:69,1
DA:70,1
DA:71,1
DA:73,1
DA:74,1
DA:76,1
DA:77,1
DA:78,1
DA:92,1
DA:93,1
LH:27
LF:33
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity.kt
FN:13,org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity::<init> ()V
FN:16,org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity::initializeMixin (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;)V
FNDA:1,org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity::<init> ()V
FNDA:1,org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity::initializeMixin (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;)V
FNF:2
FNH:2
DA:13,1
DA:16,1
DA:17,1
LH:3
LF:3
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity.kt
FN:13,org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity::<init> ()V
FN:16,org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity::initializeMixin (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;)V
FNDA:0,org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity::<init> ()V
FNDA:0,org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity::initializeMixin (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;)V
FNF:2
FNH:0
DA:13,0
DA:16,0
DA:17,0
LH:0
LF:3
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/route/ActivityRouter.kt
FN:13,org/oppia/android/app/activity/route/ActivityRouter::<init> (Landroidx/appcompat/app/AppCompatActivity;Ljava/util/Map;Lorg/oppia/android/util/logging/ConsoleLogger;)V
FN:20,org/oppia/android/app/activity/route/ActivityRouter::routeToScreen (Lorg/oppia/android/app/model/DestinationScreen;)V
FNDA:1,org/oppia/android/app/activity/route/ActivityRouter::<init> (Landroidx/appcompat/app/AppCompatActivity;Ljava/util/Map;Lorg/oppia/android/util/logging/ConsoleLogger;)V
FNDA:0,org/oppia/android/app/activity/route/ActivityRouter::routeToScreen (Lorg/oppia/android/app/model/DestinationScreen;)V
FNF:2
FNH:1
BRDA:20,0,0,-
BRDA:20,0,1,-
BRDA:25,0,0,-
BRDA:25,0,1,-
BRF:4
BRH:0
DA:13,1
DA:14,1
DA:15,1
DA:16,1
DA:20,0
DA:21,0
DA:22,0
DA:23,0
DA:25,0
DA:26,0
DA:28,0
DA:30,0
LH:4
LF:12
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/route/Route.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/route/RouteKey.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationComponent.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationInjectorProvider.kt
FN:29,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getAppLanguageApplicationInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/app/translation/AppLanguageApplicationInjector;
FN:37,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getConsoleLoggerInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/logging/ConsoleLoggerInjector;
FN:26,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getDataProvidersInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/data/DataProvidersInjector;
FN:35,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getDispatcherInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/threading/DispatcherInjector;
FN:33,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getLocaleApplicationInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/domain/locale/LocaleApplicationInjector;
FN:31,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getOppiaClockInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/system/OppiaClockInjector;
FNDA:1,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getAppLanguageApplicationInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/app/translation/AppLanguageApplicationInjector;
FNDA:0,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getConsoleLoggerInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/logging/ConsoleLoggerInjector;
FNDA:1,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getDataProvidersInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/data/DataProvidersInjector;
FNDA:0,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getDispatcherInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/threading/DispatcherInjector;
FNDA:1,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getLocaleApplicationInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/domain/locale/LocaleApplicationInjector;
FNDA:0,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getOppiaClockInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/system/OppiaClockInjector;
FNF:6
FNH:3
DA:26,1
DA:29,1
DA:31,0
DA:33,1
DA:35,0
DA:37,0
LH:3
LF:6
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationStartupListenerModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/testing/TestingBuildFlavorModule.kt
FN:11,org/oppia/android/app/application/testing/TestingBuildFlavorModule::<init> ()V
FN:14,org/oppia/android/app/application/testing/TestingBuildFlavorModule::provideTestingBuildFlavor ()Lorg/oppia/android/app/model/BuildFlavor;
FNDA:1,org/oppia/android/app/application/testing/TestingBuildFlavorModule::<init> ()V
FNDA:0,org/oppia/android/app/application/testing/TestingBuildFlavorModule::provideTestingBuildFlavor ()Lorg/oppia/android/app/model/BuildFlavor;
FNF:2
FNH:1
DA:11,1
DA:12,1
DA:14,0
LH:2
LF:3
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/FragmentComponent.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/FragmentComponentBuilderInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/FragmentComponentFactory.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/FragmentScope.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment.kt
FN:14,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::<init> ()V
FN:31,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FN:22,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::getBottomSheetFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FN:25,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::onAttach (Landroid/content/Context;)V
FN:22,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::setBottomSheetFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::<init> ()V
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::getBottomSheetFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::onAttach (Landroid/content/Context;)V
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::setBottomSheetFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNF:5
FNH:0
DA:14,0
DA:15,0
DA:22,0
DA:25,0
DA:26,0
DA:27,0
DA:28,0
DA:31,0
DA:32,0
LH:0
LF:9
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/InjectableDialogFragment.kt
FN:14,org/oppia/android/app/fragment/InjectableDialogFragment::<init> ()V
FN:29,org/oppia/android/app/fragment/InjectableDialogFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FN:20,org/oppia/android/app/fragment/InjectableDialogFragment::getFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FN:23,org/oppia/android/app/fragment/InjectableDialogFragment::onAttach (Landroid/content/Context;)V
FN:20,org/oppia/android/app/fragment/InjectableDialogFragment::setFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNDA:0,org/oppia/android/app/fragment/InjectableDialogFragment::<init> ()V
FNDA:0,org/oppia/android/app/fragment/InjectableDialogFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableDialogFragment::getFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableDialogFragment::onAttach (Landroid/content/Context;)V
FNDA:0,org/oppia/android/app/fragment/InjectableDialogFragment::setFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNF:5
FNH:0
DA:14,0
DA:20,0
DA:23,0
DA:24,0
DA:25,0
DA:26,0
DA:29,0
DA:30,0
LH:0
LF:8
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/InjectableFragment.kt
FN:14,org/oppia/android/app/fragment/InjectableFragment::<init> ()V
FN:29,org/oppia/android/app/fragment/InjectableFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FN:20,org/oppia/android/app/fragment/InjectableFragment::getFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FN:23,org/oppia/android/app/fragment/InjectableFragment::onAttach (Landroid/content/Context;)V
FN:20,org/oppia/android/app/fragment/InjectableFragment::setFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNDA:0,org/oppia/android/app/fragment/InjectableFragment::<init> ()V
FNDA:0,org/oppia/android/app/fragment/InjectableFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableFragment::getFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableFragment::onAttach (Landroid/content/Context;)V
FNDA:0,org/oppia/android/app/fragment/InjectableFragment::setFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNF:5
FNH:0
DA:14,0
DA:20,0
DA:23,0
DA:24,0
DA:25,0
DA:26,0
DA:29,0
DA:30,0
LH:0
LF:8
end_of_record
SF:app/src/main/java/org/oppia/android/app/shim/IntentFactoryShim.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/shim/IntentFactoryShimModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/shim/ViewBindingShim.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/shim/ViewBindingShimModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/spotlight/SpotlightManager.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/spotlight/SpotlightNavigationListener.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/spotlight/SpotlightShape.kt
FN:6,org/oppia/android/app/spotlight/SpotlightShape$Circle::<init> ()V
FN:9,org/oppia/android/app/spotlight/SpotlightShape$RoundedRectangle::<init> ()V
FNDA:0,org/oppia/android/app/spotlight/SpotlightShape$Circle::<init> ()V
FNDA:0,org/oppia/android/app/spotlight/SpotlightShape$RoundedRectangle::<init> ()V
FNF:2
FNH:0
DA:6,0
DA:9,0
LH:0
LF:2
end_of_record
SF:app/src/main/java/org/oppia/android/app/spotlight/SpotlightTarget.kt
FN:14,org/oppia/android/app/spotlight/SpotlightTarget::<init> (Landroid/view/View;Ljava/lang/String;Lorg/oppia/android/app/spotlight/SpotlightShape;Lorg/oppia/android/app/model/Spotlight$FeatureCase;)V
FN:14,org/oppia/android/app/spotlight/SpotlightTarget::<init> (Landroid/view/View;Ljava/lang/String;Lorg/oppia/android/app/spotlight/SpotlightShape;Lorg/oppia/android/app/model/Spotlight$FeatureCase;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
FN:66,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorCentreX ()F
FN:70,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorCentreY ()F
FN:58,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorHeight ()I
FN:44,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorLeft ()F
FN:51,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorTop ()F
FN:62,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorWidth ()I
FN:15,org/oppia/android/app/spotlight/SpotlightTarget::getAnchor ()Landroid/view/View;
FN:30,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorCentreX ()F
FN:32,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorCentreY ()F
FN:26,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorHeight ()I
FN:22,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorLeft ()F
FN:24,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorTop ()F
FN:28,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorWidth ()I
FN:18,org/oppia/android/app/spotlight/SpotlightTarget::getFeature ()Lorg/oppia/android/app/model/Spotlight$FeatureCase;
FN:16,org/oppia/android/app/spotlight/SpotlightTarget::getHint ()Ljava/lang/String;
FN:17,org/oppia/android/app/spotlight/SpotlightTarget::getShape ()Lorg/oppia/android/app/spotlight/SpotlightShape;
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::<init> (Landroid/view/View;Ljava/lang/String;Lorg/oppia/android/app/spotlight/SpotlightShape;Lorg/oppia/android/app/model/Spotlight$FeatureCase;)V
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::<init> (Landroid/view/View;Ljava/lang/String;Lorg/oppia/android/app/spotlight/SpotlightShape;Lorg/oppia/android/app/model/Spotlight$FeatureCase;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorCentreX ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorCentreY ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorHeight ()I
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorLeft ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorTop ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorWidth ()I
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchor ()Landroid/view/View;
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorCentreX ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorCentreY ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorHeight ()I
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorLeft ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorTop ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorWidth ()I
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getFeature ()Lorg/oppia/android/app/model/Spotlight$FeatureCase;
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getHint ()Ljava/lang/String;
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getShape ()Lorg/oppia/android/app/spotlight/SpotlightShape;
FNF:18
FNH:0
DA:14,0
DA:15,0
DA:16,0
DA:17,0
DA:18,0
DA:22,0
DA:24,0
DA:26,0
DA:28,0
DA:30,0
DA:32,0
DA:34,0
DA:35,0
DA:36,0
DA:37,0
DA:38,0
DA:39,0
DA:40,0
DA:41,0
DA:44,0
DA:45,0
DA:46,0
DA:47,0
DA:51,0
DA:52,0
DA:53,0
DA:54,0
DA:58,0
DA:62,0
DA:66,0
DA:70,0
DA:72,0
LH:0
LF:32
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/ActivityLanguageLocaleHandler.kt
FN:30,org/oppia/android/app/translation/ActivityLanguageLocaleHandler$displayLocale$2::invoke ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FN:18,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::<init> (Lorg/oppia/android/domain/locale/LocaleController;Lorg/oppia/android/app/translation/AppLanguageLocaleHandler;)V
FN:29,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::getDisplayLocale ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FN:41,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::initializeLocaleForActivity (Landroid/content/res/Configuration;)V
FN:51,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::updateLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)Z
FNDA:1,org/oppia/android/app/translation/ActivityLanguageLocaleHandler$displayLocale$2::invoke ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FNDA:1,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::<init> (Lorg/oppia/android/domain/locale/LocaleController;Lorg/oppia/android/app/translation/AppLanguageLocaleHandler;)V
FNDA:1,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::getDisplayLocale ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FNDA:1,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::initializeLocaleForActivity (Landroid/content/res/Configuration;)V
FNDA:0,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::updateLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)Z
FNF:5
FNH:4
BRDA:53,0,0,-
BRDA:53,0,1,-
BRF:2
BRH:0
DA:18,1
DA:19,1
DA:20,1
DA:21,1
DA:29,1
DA:30,1
DA:41,1
DA:42,1
DA:51,0
DA:52,0
DA:53,0
LH:8
LF:11
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/ActivityRecreator.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/ActivityRecreatorImpl.kt
FN:7,org/oppia/android/app/translation/ActivityRecreatorImpl::<init> ()V
FN:9,org/oppia/android/app/translation/ActivityRecreatorImpl::recreate (Landroidx/appcompat/app/AppCompatActivity;)V
FNDA:0,org/oppia/android/app/translation/ActivityRecreatorImpl::<init> ()V
FNDA:0,org/oppia/android/app/translation/ActivityRecreatorImpl::recreate (Landroidx/appcompat/app/AppCompatActivity;)V
FNF:2
FNH:0
DA:7,0
DA:9,0
DA:10,0
LH:0
LF:3
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/ActivityRecreatorProdModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageActivityInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageActivityInjectorProvider.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageApplicationInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageApplicationInjectorProvider.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageLocaleHandler.kt
FN:20,org/oppia/android/app/translation/AppLanguageLocaleHandler::<init> (Lorg/oppia/android/domain/locale/LocaleController;)V
FN:76,org/oppia/android/app/translation/AppLanguageLocaleHandler::getDisplayLocale ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FN:41,org/oppia/android/app/translation/AppLanguageLocaleHandler::initializeLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)V
FN:56,org/oppia/android/app/translation/AppLanguageLocaleHandler::initializeLocaleForActivity (Landroid/content/res/Configuration;)V
FN:32,org/oppia/android/app/translation/AppLanguageLocaleHandler::isInitialized ()Z
FN:67,org/oppia/android/app/translation/AppLanguageLocaleHandler::updateLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)Z
FN:81,org/oppia/android/app/translation/AppLanguageLocaleHandler::verifyDisplayLocaleIsInitialized ()V
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::<init> (Lorg/oppia/android/domain/locale/LocaleController;)V
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::getDisplayLocale ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::initializeLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)V
FNDA:0,org/oppia/android/app/translation/AppLanguageLocaleHandler::initializeLocaleForActivity (Landroid/content/res/Configuration;)V
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::isInitialized ()Z
FNDA:0,org/oppia/android/app/translation/AppLanguageLocaleHandler::updateLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)Z
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::verifyDisplayLocaleIsInitialized ()V
FNF:7
FNH:5
BRDA:32,0,0,1
BRDA:32,0,1,1
BRDA:41,0,0,1
BRDA:41,0,1,0
BRDA:41,0,2,0
BRDA:41,0,3,1
BRDA:57,0,0,-
BRDA:57,0,1,-
BRDA:68,0,0,-
BRDA:68,0,1,-
BRDA:70,0,0,-
BRDA:70,0,1,-
BRDA:77,0,0,1
BRDA:77,0,1,0
BRDA:81,0,0,0
BRDA:81,0,1,1
BRF:16
BRH:6
DA:20,1
DA:21,1
DA:22,1
DA:32,1
DA:41,1
DA:42,0
DA:45,1
DA:46,1
DA:56,0
DA:57,0
DA:58,0
DA:67,0
DA:68,0
DA:69,0
DA:70,0
DA:76,1
DA:77,1
DA:81,1
DA:82,0
DA:85,1
LH:11
LF:20
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageWatcherMixin.kt
FN:80,org/oppia/android/app/translation/AppLanguageWatcherMixin$initialize$1::<init> (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;Landroidx/lifecycle/LiveData;)V
FN:82,org/oppia/android/app/translation/AppLanguageWatcherMixin$initialize$1::onChanged (Lorg/oppia/android/util/data/AsyncResult;)V
FN:20,org/oppia/android/app/translation/AppLanguageWatcherMixin::<init> (Landroidx/appcompat/app/AppCompatActivity;Lorg/oppia/android/domain/translation/TranslationController;Lorg/oppia/android/app/translation/AppLanguageLocaleHandler;Lorg/oppia/android/domain/locale/LocaleController;Lorg/oppia/android/domain/oppialogger/OppiaLogger;Lorg/oppia/android/app/translation/ActivityRecreator;Lorg/oppia/android/domain/profile/ProfileManagementController;Lorg/oppia/android/app/translation/ActivityLanguageLocaleHandler;)V
FN:43,org/oppia/android/app/translation/AppLanguageWatcherMixin::initialize (Z)V
FNDA:1,org/oppia/android/app/translation/AppLanguageWatcherMixin$initialize$1::<init> (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;Landroidx/lifecycle/LiveData;)V
FNDA:0,org/oppia/android/app/translation/AppLanguageWatcherMixin$initialize$1::onChanged (Lorg/oppia/android/util/data/AsyncResult;)V
FNDA:1,org/oppia/android/app/translation/AppLanguageWatcherMixin::<init> (Landroidx/appcompat/app/AppCompatActivity;Lorg/oppia/android/domain/translation/TranslationController;Lorg/oppia/android/app/translation/AppLanguageLocaleHandler;Lorg/oppia/android/domain/locale/LocaleController;Lorg/oppia/android/domain/oppialogger/OppiaLogger;Lorg/oppia/android/app/translation/ActivityRecreator;Lorg/oppia/android/domain/profile/ProfileManagementController;Lorg/oppia/android/app/translation/ActivityLanguageLocaleHandler;)V
FNDA:1,org/oppia/android/app/translation/AppLanguageWatcherMixin::initialize (Z)V
FNF:4
FNH:3
BRDA:43,0,0,1
BRDA:43,0,1,0
BRDA:72,0,0,0
BRDA:72,0,1,1
BRDA:73,0,0,1
BRDA:73,0,1,0
BRDA:83,0,0,-
BRDA:83,0,1,-
BRDA:86,0,0,-
BRDA:86,0,1,-
BRDA:103,0,0,-
BRDA:103,0,1,-
BRDA:109,0,0,-
BRDA:109,0,1,-
BRF:14
BRH:3
DA:20,1
DA:21,1
DA:22,1
DA:23,1
DA:24,1
DA:25,1
DA:26,1
DA:27,1
DA:28,1
DA:43,1
DA:60,0
DA:61,0
DA:63,0
DA:64,0
DA:66,0
DA:69,1
DA:71,1
DA:72,1
DA:73,1
DA:74,0
DA:77,1
DA:78,1
DA:79,1
DA:80,1
DA:82,0
DA:83,0
DA:86,0
DA:99,0
DA:100,0
DA:103,0
DA:104,0
DA:105,0
DA:106,0
DA:109,0
DA:111,0
DA:114,1
LH:19
LF:36
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/testing/ActivityRecreatorTestModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/testing/TestActivityRecreator.kt
FN:18,org/oppia/android/app/translation/testing/TestActivityRecreator::<init> ()V
FN:28,org/oppia/android/app/translation/testing/TestActivityRecreator::getRecreateCount ()I
FN:24,org/oppia/android/app/translation/testing/TestActivityRecreator::recreate (Landroidx/appcompat/app/AppCompatActivity;)V
FNDA:1,org/oppia/android/app/translation/testing/TestActivityRecreator::<init> ()V
FNDA:0,org/oppia/android/app/translation/testing/TestActivityRecreator::getRecreateCount ()I
FNDA:0,org/oppia/android/app/translation/testing/TestActivityRecreator::recreate (Landroidx/appcompat/app/AppCompatActivity;)V
FNF:3
FNH:1
DA:18,1
DA:19,1
DA:24,0
DA:25,0
DA:28,0
LH:2
LF:5
end_of_record
SF:app/src/main/java/org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory.kt
FN:36,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$createTimer$1::invokeSuspend (Ljava/lang/Object;)Ljava/lang/Object;
FN:80,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runPeriodically$1::invoke ()V
FN:53,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runWithDelay$1::<init> (Landroidx/lifecycle/LiveData;Lkotlin/jvm/functions/Function0;)V
FN:55,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runWithDelay$1::onChanged (Ljava/lang/Object;)V
FN:19,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::<init> (Lkotlinx/coroutines/CoroutineDispatcher;)V
FN:34,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::createTimer (J)Landroidx/lifecycle/LiveData;
FN:79,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runPeriodically (Landroidx/lifecycle/LifecycleOwner;JJLkotlin/jvm/functions/Function0;)V
FN:74,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runPeriodically$default (Lorg/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory;Landroidx/lifecycle/LifecycleOwner;JJLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
FN:50,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runWithDelay (Landroidx/lifecycle/LifecycleOwner;JLkotlin/jvm/functions/Function0;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$createTimer$1::invokeSuspend (Ljava/lang/Object;)Ljava/lang/Object;
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runPeriodically$1::invoke ()V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runWithDelay$1::<init> (Landroidx/lifecycle/LiveData;Lkotlin/jvm/functions/Function0;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runWithDelay$1::onChanged (Ljava/lang/Object;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::<init> (Lkotlinx/coroutines/CoroutineDispatcher;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::createTimer (J)Landroidx/lifecycle/LiveData;
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runPeriodically (Landroidx/lifecycle/LifecycleOwner;JJLkotlin/jvm/functions/Function0;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runPeriodically$default (Lorg/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory;Landroidx/lifecycle/LifecycleOwner;JJLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runWithDelay (Landroidx/lifecycle/LifecycleOwner;JLkotlin/jvm/functions/Function0;)V
FNF:9
FNH:0
DA:19,0
DA:20,0
DA:24,0
DA:34,0
DA:35,0
DA:36,0
DA:37,0
DA:38,0
DA:39,0
DA:50,0
DA:51,0
DA:52,0
DA:53,0
DA:55,0
DA:56,0
DA:57,0
DA:60,0
DA:74,0
DA:75,0
DA:79,0
DA:80,0
DA:81,0
DA:83,0
DA:84,0
LH:0
LF:24
end_of_record
SF:app/src/main/java/org/oppia/android/app/view/ViewComponent.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/view/ViewComponentBuilderInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/view/ViewComponentFactory.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/view/ViewScope.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/viewmodel/ObservableArrayList.kt
FN:7,org/oppia/android/app/viewmodel/ObservableArrayList::<init> ()V
FN:17,org/oppia/android/app/viewmodel/ObservableArrayList::add (ILjava/lang/Object;)V
FN:11,org/oppia/android/app/viewmodel/ObservableArrayList::add (Ljava/lang/Object;)Z
FN:31,org/oppia/android/app/viewmodel/ObservableArrayList::addAll (ILjava/util/Collection;)Z
FN:22,org/oppia/android/app/viewmodel/ObservableArrayList::addAll (Ljava/util/Collection;)Z
FN:69,org/oppia/android/app/viewmodel/ObservableArrayList::addOnListChangedCallback (Landroidx/databinding/ObservableList$OnListChangedCallback;)V
FN:48,org/oppia/android/app/viewmodel/ObservableArrayList::clear ()V
FN:8,org/oppia/android/app/viewmodel/ObservableArrayList::getListeners ()Landroidx/databinding/ListChangeRegistry;
FN:79,org/oppia/android/app/viewmodel/ObservableArrayList::notifyAdd (II)V
FN:83,org/oppia/android/app/viewmodel/ObservableArrayList::notifyRemove (II)V
FN:39,org/oppia/android/app/viewmodel/ObservableArrayList::removeAll (Ljava/util/Collection;)Z
FN:75,org/oppia/android/app/viewmodel/ObservableArrayList::removeOnListChangedCallback (Landroidx/databinding/ObservableList$OnListChangedCallback;)V
FN:62,org/oppia/android/app/viewmodel/ObservableArrayList::removeRange (II)V
FN:56,org/oppia/android/app/viewmodel/ObservableArrayList::set (ILjava/lang/Object;)Ljava/lang/Object;
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::<init> ()V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::add (ILjava/lang/Object;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::add (Ljava/lang/Object;)Z
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::addAll (ILjava/util/Collection;)Z
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::addAll (Ljava/util/Collection;)Z
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::addOnListChangedCallback (Landroidx/databinding/ObservableList$OnListChangedCallback;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::clear ()V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::getListeners ()Landroidx/databinding/ListChangeRegistry;
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::notifyAdd (II)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::notifyRemove (II)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::removeAll (Ljava/util/Collection;)Z
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::removeOnListChangedCallback (Landroidx/databinding/ObservableList$OnListChangedCallback;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::removeRange (II)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::set (ILjava/lang/Object;)Ljava/lang/Object;
FNF:14
FNH:0
DA:7,0
DA:8,0
DA:11,0
DA:12,0
DA:13,0
DA:17,0
DA:18,0
DA:19,0
DA:22,0
DA:23,0
DA:24,0
DA:25,0
DA:27,0
DA:31,0
DA:32,0
DA:33,0
DA:35,0
DA:39,0
DA:40,0
DA:41,0
DA:42,0
DA:44,0
DA:48,0
DA:49,0
DA:50,0
DA:51,0
DA:53,0
DA:56,0
DA:57,0
DA:58,0
DA:62,0
DA:63,0
DA:64,0
DA:69,0
DA:70,0
DA:75,0
DA:76,0
DA:79,0
DA:80,0
DA:83,0
DA:84,0
LH:0
LF:41
end_of_record
SF:app/src/main/java/org/oppia/android/app/viewmodel/ObservableViewModel.kt
FN:9,org/oppia/android/app/viewmodel/ObservableViewModel$callbacks$2::invoke ()Landroidx/databinding/PropertyChangeRegistry;
FN:7,org/oppia/android/app/viewmodel/ObservableViewModel::<init> ()V
FN:17,org/oppia/android/app/viewmodel/ObservableViewModel::addOnPropertyChangedCallback (Landroidx/databinding/Observable$OnPropertyChangedCallback;)V
FN:8,org/oppia/android/app/viewmodel/ObservableViewModel::getCallbacks ()Landroidx/databinding/PropertyChangeRegistry;
FN:22,org/oppia/android/app/viewmodel/ObservableViewModel::notifyChange ()V
FN:27,org/oppia/android/app/viewmodel/ObservableViewModel::notifyPropertyChanged (I)V
FN:13,org/oppia/android/app/viewmodel/ObservableViewModel::removeOnPropertyChangedCallback (Landroidx/databinding/Observable$OnPropertyChangedCallback;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel$callbacks$2::invoke ()Landroidx/databinding/PropertyChangeRegistry;
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::<init> ()V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::addOnPropertyChangedCallback (Landroidx/databinding/Observable$OnPropertyChangedCallback;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::getCallbacks ()Landroidx/databinding/PropertyChangeRegistry;
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::notifyChange ()V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::notifyPropertyChanged (I)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::removeOnPropertyChangedCallback (Landroidx/databinding/Observable$OnPropertyChangedCallback;)V
FNF:7
FNH:0
DA:7,0
DA:8,0
DA:9,0
DA:13,0
DA:14,0
DA:17,0
DA:18,0
DA:22,0
DA:23,0
DA:27,0
DA:28,0
LH:0
LF:11
end_of_record
SF:app/src/test/java/org/oppia/android/app/parser/FractionParsingUiErrorTest.kt
FN:243,org/oppia/android/app/parser/FractionParsingUiErrorTest$Companion::toUiError (Lorg/oppia/android/util/math/FractionParser$FractionParsingError;)Lorg/oppia/android/app/parser/FractionParsingUiError;
FN:288,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication$component$2::invoke ()Lorg/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplicationComponent;
FN:286,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::<init> ()V
FN:298,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::createActivityComponent (Landroidx/appcompat/app/AppCompatActivity;)Lorg/oppia/android/app/activity/ActivityComponent;
FN:286,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::getAppLanguageApplicationInjector ()Lorg/oppia/android/app/translation/AppLanguageApplicationInjector;
FN:301,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::getApplicationInjector ()Lorg/oppia/android/app/application/ApplicationInjector;
FN:287,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::getComponent ()Lorg/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplicationComponent;
FN:286,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::getConsoleLoggerInjector ()Lorg/oppia/android/util/logging/ConsoleLoggerInjector;
FN:286,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::getDataProvidersInjector ()Lorg/oppia/android/util/data/DataProvidersInjector;
FN:286,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::getDispatcherInjector ()Lorg/oppia/android/util/threading/DispatcherInjector;
FN:286,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::getLocaleApplicationInjector ()Lorg/oppia/android/domain/locale/LocaleApplicationInjector;
FN:286,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::getOppiaClockInjector ()Lorg/oppia/android/util/system/OppiaClockInjector;
FN:294,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::inject (Lorg/oppia/android/app/parser/FractionParsingUiErrorTest;)V
FN:207,org/oppia/android/app/parser/FractionParsingUiErrorTest$testRealTimeError_noNumerator_invalidFormat_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FN:196,org/oppia/android/app/parser/FractionParsingUiErrorTest$testRealTimeError_nonDigits_invalidChars_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FN:229,org/oppia/android/app/parser/FractionParsingUiErrorTest$testRealTimeError_severalDashes_invalidFormat_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FN:218,org/oppia/android/app/parser/FractionParsingUiErrorTest$testRealTimeError_severalSlashes_invalidFormat_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FN:186,org/oppia/android/app/parser/FractionParsingUiErrorTest$testRealTimeError_validRegularFraction_noErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FN:153,org/oppia/android/app/parser/FractionParsingUiErrorTest$testSubmitTimeError_ambiguousSpacing_invalidFormat_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FN:143,org/oppia/android/app/parser/FractionParsingUiErrorTest$testSubmitTimeError_divisionByZero_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FN:164,org/oppia/android/app/parser/FractionParsingUiErrorTest$testSubmitTimeError_emptyString_invalidFormat_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FN:175,org/oppia/android/app/parser/FractionParsingUiErrorTest$testSubmitTimeError_noDenominator_invalidFormat_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FN:132,org/oppia/android/app/parser/FractionParsingUiErrorTest$testSubmitTimeError_nonDigits_invalidFormat_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FN:121,org/oppia/android/app/parser/FractionParsingUiErrorTest$testSubmitTimeError_tenDigitNumber_numberTooLong_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FN:111,org/oppia/android/app/parser/FractionParsingUiErrorTest$testSubmitTimeError_validMixedNumber_noErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FN:87,org/oppia/android/app/parser/FractionParsingUiErrorTest::<init> ()V
FN:95,org/oppia/android/app/parser/FractionParsingUiErrorTest::getActivityRule ()Landroidx/test/ext/junit/rules/ActivityScenarioRule;
FN:92,org/oppia/android/app/parser/FractionParsingUiErrorTest::getInitializeDefaultLocaleRule ()Lorg/oppia/android/testing/junit/InitializeDefaultLocaleRule;
FN:95,org/oppia/android/app/parser/FractionParsingUiErrorTest::setActivityRule (Landroidx/test/ext/junit/rules/ActivityScenarioRule;)V
FN:104,org/oppia/android/app/parser/FractionParsingUiErrorTest::setUp ()V
FN:238,org/oppia/android/app/parser/FractionParsingUiErrorTest::setUpTestApplicationComponent ()V
FN:206,org/oppia/android/app/parser/FractionParsingUiErrorTest::testRealTimeError_noNumerator_invalidFormat_hasRelevantErrorMessage ()V
FN:195,org/oppia/android/app/parser/FractionParsingUiErrorTest::testRealTimeError_nonDigits_invalidChars_hasRelevantErrorMessage ()V
FN:228,org/oppia/android/app/parser/FractionParsingUiErrorTest::testRealTimeError_severalDashes_invalidFormat_hasRelevantErrorMessage ()V
FN:217,org/oppia/android/app/parser/FractionParsingUiErrorTest::testRealTimeError_severalSlashes_invalidFormat_hasRelevantErrorMessage ()V
FN:185,org/oppia/android/app/parser/FractionParsingUiErrorTest::testRealTimeError_validRegularFraction_noErrorMessage ()V
FN:152,org/oppia/android/app/parser/FractionParsingUiErrorTest::testSubmitTimeError_ambiguousSpacing_invalidFormat_hasRelevantErrorMessage ()V
FN:142,org/oppia/android/app/parser/FractionParsingUiErrorTest::testSubmitTimeError_divisionByZero_hasRelevantErrorMessage ()V
FN:163,org/oppia/android/app/parser/FractionParsingUiErrorTest::testSubmitTimeError_emptyString_invalidFormat_hasRelevantErrorMessage ()V
FN:174,org/oppia/android/app/parser/FractionParsingUiErrorTest::testSubmitTimeError_noDenominator_invalidFormat_hasRelevantErrorMessage ()V
FN:131,org/oppia/android/app/parser/FractionParsingUiErrorTest::testSubmitTimeError_nonDigits_invalidFormat_hasRelevantErrorMessage ()V
FN:120,org/oppia/android/app/parser/FractionParsingUiErrorTest::testSubmitTimeError_tenDigitNumber_numberTooLong_hasRelevantErrorMessage ()V
FN:110,org/oppia/android/app/parser/FractionParsingUiErrorTest::testSubmitTimeError_validMixedNumber_noErrorMessage ()V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$Companion::toUiError (Lorg/oppia/android/util/math/FractionParser$FractionParsingError;)Lorg/oppia/android/app/parser/FractionParsingUiError;
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication$component$2::invoke ()Lorg/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplicationComponent;
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::<init> ()V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::createActivityComponent (Landroidx/appcompat/app/AppCompatActivity;)Lorg/oppia/android/app/activity/ActivityComponent;
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::getAppLanguageApplicationInjector ()Lorg/oppia/android/app/translation/AppLanguageApplicationInjector;
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::getApplicationInjector ()Lorg/oppia/android/app/application/ApplicationInjector;
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::getComponent ()Lorg/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplicationComponent;
FNDA:0,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::getConsoleLoggerInjector ()Lorg/oppia/android/util/logging/ConsoleLoggerInjector;
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::getDataProvidersInjector ()Lorg/oppia/android/util/data/DataProvidersInjector;
FNDA:0,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::getDispatcherInjector ()Lorg/oppia/android/util/threading/DispatcherInjector;
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::getLocaleApplicationInjector ()Lorg/oppia/android/domain/locale/LocaleApplicationInjector;
FNDA:0,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::getOppiaClockInjector ()Lorg/oppia/android/util/system/OppiaClockInjector;
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$TestApplication::inject (Lorg/oppia/android/app/parser/FractionParsingUiErrorTest;)V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$testRealTimeError_noNumerator_invalidFormat_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$testRealTimeError_nonDigits_invalidChars_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$testRealTimeError_severalDashes_invalidFormat_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$testRealTimeError_severalSlashes_invalidFormat_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$testRealTimeError_validRegularFraction_noErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$testSubmitTimeError_ambiguousSpacing_invalidFormat_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$testSubmitTimeError_divisionByZero_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$testSubmitTimeError_emptyString_invalidFormat_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$testSubmitTimeError_noDenominator_invalidFormat_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$testSubmitTimeError_nonDigits_invalidFormat_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$testSubmitTimeError_tenDigitNumber_numberTooLong_hasRelevantErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest$testSubmitTimeError_validMixedNumber_noErrorMessage$1::perform (Lorg/oppia/android/app/testing/activity/TestActivity;)V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest::<init> ()V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest::getActivityRule ()Landroidx/test/ext/junit/rules/ActivityScenarioRule;
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest::getInitializeDefaultLocaleRule ()Lorg/oppia/android/testing/junit/InitializeDefaultLocaleRule;
FNDA:0,org/oppia/android/app/parser/FractionParsingUiErrorTest::setActivityRule (Landroidx/test/ext/junit/rules/ActivityScenarioRule;)V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest::setUp ()V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest::setUpTestApplicationComponent ()V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest::testRealTimeError_noNumerator_invalidFormat_hasRelevantErrorMessage ()V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest::testRealTimeError_nonDigits_invalidChars_hasRelevantErrorMessage ()V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest::testRealTimeError_severalDashes_invalidFormat_hasRelevantErrorMessage ()V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest::testRealTimeError_severalSlashes_invalidFormat_hasRelevantErrorMessage ()V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest::testRealTimeError_validRegularFraction_noErrorMessage ()V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest::testSubmitTimeError_ambiguousSpacing_invalidFormat_hasRelevantErrorMessage ()V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest::testSubmitTimeError_divisionByZero_hasRelevantErrorMessage ()V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest::testSubmitTimeError_emptyString_invalidFormat_hasRelevantErrorMessage ()V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest::testSubmitTimeError_noDenominator_invalidFormat_hasRelevantErrorMessage ()V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest::testSubmitTimeError_nonDigits_invalidFormat_hasRelevantErrorMessage ()V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest::testSubmitTimeError_tenDigitNumber_numberTooLong_hasRelevantErrorMessage ()V
FNDA:1,org/oppia/android/app/parser/FractionParsingUiErrorTest::testSubmitTimeError_validMixedNumber_noErrorMessage ()V
FNF:43
FNH:39
BRDA:111,0,0,1
BRDA:111,0,1,0
BRDA:121,0,0,1
BRDA:121,0,1,0
BRDA:132,0,0,1
BRDA:132,0,1,0
BRDA:143,0,0,1
BRDA:143,0,1,0
BRDA:153,0,0,1
BRDA:153,0,1,0
BRDA:164,0,0,1
BRDA:164,0,1,0
BRDA:175,0,0,1
BRDA:175,0,1,0
BRDA:186,0,0,1
BRDA:186,0,1,0
BRDA:196,0,0,1
BRDA:196,0,1,0
BRDA:207,0,0,1
BRDA:207,0,1,0
BRDA:218,0,0,1
BRDA:218,0,1,0
BRDA:229,0,0,1
BRDA:229,0,1,0
BRF:24
BRH:12
DA:87,1
DA:90,1
DA:92,1
DA:95,1
DA:96,1
DA:97,1
DA:98,0
DA:104,1
DA:105,1
DA:106,1
DA:110,1
DA:111,1
DA:112,1
DA:113,1
DA:114,1
DA:115,1
DA:116,1
DA:120,1
DA:121,1
DA:122,1
DA:123,1
DA:124,1
DA:125,1
DA:126,1
DA:127,1
DA:131,1
DA:132,1
DA:133,1
DA:134,1
DA:135,1
DA:136,1
DA:137,1
DA:138,1
DA:142,1
DA:143,1
DA:144,1
DA:145,1
DA:146,1
DA:147,1
DA:148,1
DA:152,1
DA:153,1
DA:154,1
DA:155,1
DA:156,1
DA:157,1
DA:158,1
DA:159,1
DA:163,1
DA:164,1
DA:165,1
DA:166,1
DA:167,1
DA:168,1
DA:169,1
DA:170,1
DA:174,1
DA:175,1
DA:176,1
DA:177,1
DA:178,1
DA:179,1
DA:180,1
DA:181,1
DA:185,1
DA:186,1
DA:187,1
DA:188,1
DA:189,1
DA:190,1
DA:191,1
DA:195,1
DA:196,1
DA:197,1
DA:198,1
DA:199,1
DA:200,1
DA:201,1
DA:202,1
DA:206,1
DA:207,1
DA:208,1
DA:209,1
DA:210,1
DA:211,1
DA:212,1
DA:213,1
DA:217,1
DA:218,1
DA:219,1
DA:220,1
DA:221,1
DA:222,1
DA:223,1
DA:224,1
DA:228,1
DA:229,1
DA:230,1
DA:231,1
DA:232,1
DA:233,1
DA:234,1
DA:235,1
DA:238,1
DA:239,1
DA:243,1
DA:286,1
DA:287,1
DA:288,1
DA:289,1
DA:290,1
DA:294,1
DA:295,1
DA:298,1
DA:301,1
LH:114
LF:115
end_of_record

I noticed the same behavior while testing with another file, FakeOppiaClock.kt, which I kept for discussion later. The same behavior was seen with the package-relative labelled StringToRatioParserTest target.

I am not sure if I did the refactoring of package-specific labeling right (I just tried replicating similar target builds). I have kept the code for reference in my fork (though it's messy). I will also try with other packages to see if I can find anything different that can be helpful.

@Rd4dev
Copy link
Collaborator

Rd4dev commented Jul 18, 2024

I found that, interestingly, two things:

  1. Coverage is failing for some groups of tests outside of app module.
  2. All app module tests that have their own explicit test targets work with coverage.

This is leading me to believe that there may be a problem with the top-level test targets that are defined, by default, for tests with no dedicated BUILD files. I need to dig a bit more to confirm this (& maybe come up with some explanation as to why), but if this is right then the pathway to fixing it is at least fairly straightforward.

Also adding to this (nothing useful but just to confirm the cases and few additional things) there are few test targets in the app module (with top level package labelling) that do pass the coverage but as observed above they too don't contain the relevant coverage data.

Few Example targets:

  • //app:src/sharedTest/java/org/oppia/android/app/faq/FAQSingleActivityTest
  • /app:src/sharedTest/java/org/oppia/android/app/home/WelcomeViewModelTest
  • //app:src/sharedTest/java/org/oppia/android/app/mydownloads/MyDownloadsActivityTest
  • //app:src/sharedTest/java/org/oppia/android/app/options/AppLanguageFragmentTest

And as mentioned looking at the coverage reports all files that are included in the coverage result do have their own explicit targets specified however I'm uncertain if the opposite holds true.
i.e. Not all files that have their explicit targets specified were included in the coverage report.

What I mean by that is, the coverage data includes the files -

SF:app/src/main/java/org/oppia/android/app/activity/route/Route.kt, 
SF:app/src/main/java/org/oppia/android/app/spotlight/SpotlightTarget.kt, 
SF:app/src/main/java/org/oppia/android/app/application/ApplicationModule.kt

and all these files have their targets set explicitly.

But also, recently I tried running the test target:

  • //app:src/sharedTest/java/org/oppia/android/app/parser/HtmlParserTest
    which has its own explicit target set for the source file (not test target) - utility/src/main/java/org/oppia/android/util/parser/html/HtmlParser.kt
    and looking at the report it doesn't include the coverage data for the HtmlParser.kt file.

A similar observation when I tried to convert the top-level labelling to package specific labelling

Coverage Report running bazel coverage //app:src/sharedTest/java/org/oppia/android/app/parser/HtmlParserTest --instrumentation_filter=//app/... (HtmlParserTest/coverage.dat) (Lengthy report inside)
SF:app/src/main/java/org/oppia/android/app/activity/ActivityComponent.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/ActivityComponentFactory.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/ActivityIntentFactories.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/ActivityScope.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/InjectableAppCompatActivity.kt
FN:19,org/oppia/android/app/activity/InjectableAppCompatActivity::<init> ()V
FN:29,org/oppia/android/app/activity/InjectableAppCompatActivity::attachBaseContext (Landroid/content/Context;)V
FN:48,org/oppia/android/app/activity/InjectableAppCompatActivity::createFragmentComponent (Landroidx/fragment/app/Fragment;)Lorg/oppia/android/app/fragment/FragmentComponent;
FN:92,org/oppia/android/app/activity/InjectableAppCompatActivity::ensureLayoutDirection ()V
FN:26,org/oppia/android/app/activity/InjectableAppCompatActivity::getActivityComponent ()Lorg/oppia/android/app/activity/ActivityComponent;
FN:52,org/oppia/android/app/activity/InjectableAppCompatActivity::getAppLanguageActivityInjector ()Lorg/oppia/android/app/translation/AppLanguageActivityInjector;
FN:38,org/oppia/android/app/activity/InjectableAppCompatActivity::onCreate (Landroid/os/Bundle;)V
FN:43,org/oppia/android/app/activity/InjectableAppCompatActivity::onCreate (Landroid/os/Bundle;Landroid/os/PersistableBundle;)V
FN:55,org/oppia/android/app/activity/InjectableAppCompatActivity::onInitializeActivityComponent (Landroid/content/Context;)V
FN:67,org/oppia/android/app/activity/InjectableAppCompatActivity::onInitializeLocalization (Landroid/content/Context;)Landroid/content/res/Configuration;
FN:26,org/oppia/android/app/activity/InjectableAppCompatActivity::setActivityComponent (Lorg/oppia/android/app/activity/ActivityComponent;)V
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::<init> ()V
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::attachBaseContext (Landroid/content/Context;)V
FNDA:0,org/oppia/android/app/activity/InjectableAppCompatActivity::createFragmentComponent (Landroidx/fragment/app/Fragment;)Lorg/oppia/android/app/fragment/FragmentComponent;
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::ensureLayoutDirection ()V
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::getActivityComponent ()Lorg/oppia/android/app/activity/ActivityComponent;
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::getAppLanguageActivityInjector ()Lorg/oppia/android/app/translation/AppLanguageActivityInjector;
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::onCreate (Landroid/os/Bundle;)V
FNDA:0,org/oppia/android/app/activity/InjectableAppCompatActivity::onCreate (Landroid/os/Bundle;Landroid/os/PersistableBundle;)V
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::onInitializeActivityComponent (Landroid/content/Context;)V
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::onInitializeLocalization (Landroid/content/Context;)Landroid/content/res/Configuration;
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::setActivityComponent (Lorg/oppia/android/app/activity/ActivityComponent;)V
FNF:11
FNH:9
BRDA:26,0,0,1
BRDA:26,0,1,0
BRDA:29,0,0,0
BRDA:29,0,1,1
BRDA:29,0,2,0
BRDA:29,0,3,1
BRDA:34,0,0,0
BRDA:34,0,1,1
BRDA:76,0,0,0
BRDA:76,0,1,1
BRDA:76,0,2,0
BRDA:76,0,3,1
BRF:12
BRH:6
DA:19,1
DA:20,1
DA:26,1
DA:29,1
DA:30,0
DA:32,1
DA:33,1
DA:34,1
DA:35,1
DA:38,1
DA:39,1
DA:40,1
DA:43,0
DA:44,0
DA:45,0
DA:48,0
DA:49,0
DA:52,1
DA:55,1
DA:56,1
DA:57,1
DA:67,1
DA:68,1
DA:69,1
DA:70,1
DA:71,1
DA:73,1
DA:74,1
DA:76,1
DA:77,1
DA:78,1
DA:92,1
DA:93,1
LH:27
LF:33
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity.kt
FN:13,org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity::<init> ()V
FN:16,org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity::initializeMixin (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;)V
FNDA:1,org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity::<init> ()V
FNDA:1,org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity::initializeMixin (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;)V
FNF:2
FNH:2
DA:13,1
DA:16,1
DA:17,1
LH:3
LF:3
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity.kt
FN:13,org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity::<init> ()V
FN:16,org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity::initializeMixin (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;)V
FNDA:0,org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity::<init> ()V
FNDA:0,org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity::initializeMixin (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;)V
FNF:2
FNH:0
DA:13,0
DA:16,0
DA:17,0
LH:0
LF:3
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/route/ActivityRouter.kt
FN:13,org/oppia/android/app/activity/route/ActivityRouter::<init> (Landroidx/appcompat/app/AppCompatActivity;Ljava/util/Map;Lorg/oppia/android/util/logging/ConsoleLogger;)V
FN:20,org/oppia/android/app/activity/route/ActivityRouter::routeToScreen (Lorg/oppia/android/app/model/DestinationScreen;)V
FNDA:0,org/oppia/android/app/activity/route/ActivityRouter::<init> (Landroidx/appcompat/app/AppCompatActivity;Ljava/util/Map;Lorg/oppia/android/util/logging/ConsoleLogger;)V
FNDA:0,org/oppia/android/app/activity/route/ActivityRouter::routeToScreen (Lorg/oppia/android/app/model/DestinationScreen;)V
FNF:2
FNH:0
DA:13,0
DA:14,0
DA:15,0
DA:16,0
DA:20,0
DA:21,0
DA:22,0
DA:23,0
DA:25,0
DA:26,0
DA:28,0
DA:30,0
LH:0
LF:12
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/route/Route.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/route/RouteKey.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationComponent.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationInjectorProvider.kt
FN:29,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getAppLanguageApplicationInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/app/translation/AppLanguageApplicationInjector;
FN:37,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getConsoleLoggerInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/logging/ConsoleLoggerInjector;
FN:26,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getDataProvidersInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/data/DataProvidersInjector;
FN:35,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getDispatcherInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/threading/DispatcherInjector;
FN:33,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getLocaleApplicationInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/domain/locale/LocaleApplicationInjector;
FN:31,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getOppiaClockInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/system/OppiaClockInjector;
FNDA:1,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getAppLanguageApplicationInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/app/translation/AppLanguageApplicationInjector;
FNDA:1,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getConsoleLoggerInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/logging/ConsoleLoggerInjector;
FNDA:1,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getDataProvidersInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/data/DataProvidersInjector;
FNDA:1,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getDispatcherInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/threading/DispatcherInjector;
FNDA:1,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getLocaleApplicationInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/domain/locale/LocaleApplicationInjector;
FNDA:0,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getOppiaClockInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/system/OppiaClockInjector;
FNF:6
FNH:5
DA:26,1
DA:29,1
DA:31,0
DA:33,1
DA:35,1
DA:37,1
LH:5
LF:6
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationStartupListenerModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/testing/TestingBuildFlavorModule.kt
FN:11,org/oppia/android/app/application/testing/TestingBuildFlavorModule::<init> ()V
FN:14,org/oppia/android/app/application/testing/TestingBuildFlavorModule::provideTestingBuildFlavor ()Lorg/oppia/android/app/model/BuildFlavor;
FNDA:1,org/oppia/android/app/application/testing/TestingBuildFlavorModule::<init> ()V
FNDA:0,org/oppia/android/app/application/testing/TestingBuildFlavorModule::provideTestingBuildFlavor ()Lorg/oppia/android/app/model/BuildFlavor;
FNF:2
FNH:1
DA:11,1
DA:12,1
DA:14,0
LH:2
LF:3
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/FragmentComponent.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/FragmentComponentBuilderInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/FragmentComponentFactory.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/FragmentScope.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment.kt
FN:14,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::<init> ()V
FN:31,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FN:22,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::getBottomSheetFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FN:25,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::onAttach (Landroid/content/Context;)V
FN:22,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::setBottomSheetFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::<init> ()V
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::getBottomSheetFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::onAttach (Landroid/content/Context;)V
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::setBottomSheetFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNF:5
FNH:0
DA:14,0
DA:15,0
DA:22,0
DA:25,0
DA:26,0
DA:27,0
DA:28,0
DA:31,0
DA:32,0
LH:0
LF:9
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/InjectableDialogFragment.kt
FN:14,org/oppia/android/app/fragment/InjectableDialogFragment::<init> ()V
FN:29,org/oppia/android/app/fragment/InjectableDialogFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FN:20,org/oppia/android/app/fragment/InjectableDialogFragment::getFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FN:23,org/oppia/android/app/fragment/InjectableDialogFragment::onAttach (Landroid/content/Context;)V
FN:20,org/oppia/android/app/fragment/InjectableDialogFragment::setFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNDA:0,org/oppia/android/app/fragment/InjectableDialogFragment::<init> ()V
FNDA:0,org/oppia/android/app/fragment/InjectableDialogFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableDialogFragment::getFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableDialogFragment::onAttach (Landroid/content/Context;)V
FNDA:0,org/oppia/android/app/fragment/InjectableDialogFragment::setFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNF:5
FNH:0
DA:14,0
DA:20,0
DA:23,0
DA:24,0
DA:25,0
DA:26,0
DA:29,0
DA:30,0
LH:0
LF:8
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/InjectableFragment.kt
FN:14,org/oppia/android/app/fragment/InjectableFragment::<init> ()V
FN:29,org/oppia/android/app/fragment/InjectableFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FN:20,org/oppia/android/app/fragment/InjectableFragment::getFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FN:23,org/oppia/android/app/fragment/InjectableFragment::onAttach (Landroid/content/Context;)V
FN:20,org/oppia/android/app/fragment/InjectableFragment::setFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNDA:0,org/oppia/android/app/fragment/InjectableFragment::<init> ()V
FNDA:0,org/oppia/android/app/fragment/InjectableFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableFragment::getFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableFragment::onAttach (Landroid/content/Context;)V
FNDA:0,org/oppia/android/app/fragment/InjectableFragment::setFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNF:5
FNH:0
DA:14,0
DA:20,0
DA:23,0
DA:24,0
DA:25,0
DA:26,0
DA:29,0
DA:30,0
LH:0
LF:8
end_of_record
SF:app/src/main/java/org/oppia/android/app/shim/IntentFactoryShim.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/shim/IntentFactoryShimModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/shim/ViewBindingShim.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/shim/ViewBindingShimModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/spotlight/SpotlightManager.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/spotlight/SpotlightNavigationListener.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/spotlight/SpotlightShape.kt
FN:6,org/oppia/android/app/spotlight/SpotlightShape$Circle::<init> ()V
FN:9,org/oppia/android/app/spotlight/SpotlightShape$RoundedRectangle::<init> ()V
FNDA:0,org/oppia/android/app/spotlight/SpotlightShape$Circle::<init> ()V
FNDA:0,org/oppia/android/app/spotlight/SpotlightShape$RoundedRectangle::<init> ()V
FNF:2
FNH:0
DA:6,0
DA:9,0
LH:0
LF:2
end_of_record
SF:app/src/main/java/org/oppia/android/app/spotlight/SpotlightTarget.kt
FN:14,org/oppia/android/app/spotlight/SpotlightTarget::<init> (Landroid/view/View;Ljava/lang/String;Lorg/oppia/android/app/spotlight/SpotlightShape;Lorg/oppia/android/app/model/Spotlight$FeatureCase;)V
FN:14,org/oppia/android/app/spotlight/SpotlightTarget::<init> (Landroid/view/View;Ljava/lang/String;Lorg/oppia/android/app/spotlight/SpotlightShape;Lorg/oppia/android/app/model/Spotlight$FeatureCase;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
FN:66,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorCentreX ()F
FN:70,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorCentreY ()F
FN:58,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorHeight ()I
FN:44,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorLeft ()F
FN:51,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorTop ()F
FN:62,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorWidth ()I
FN:15,org/oppia/android/app/spotlight/SpotlightTarget::getAnchor ()Landroid/view/View;
FN:30,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorCentreX ()F
FN:32,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorCentreY ()F
FN:26,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorHeight ()I
FN:22,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorLeft ()F
FN:24,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorTop ()F
FN:28,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorWidth ()I
FN:18,org/oppia/android/app/spotlight/SpotlightTarget::getFeature ()Lorg/oppia/android/app/model/Spotlight$FeatureCase;
FN:16,org/oppia/android/app/spotlight/SpotlightTarget::getHint ()Ljava/lang/String;
FN:17,org/oppia/android/app/spotlight/SpotlightTarget::getShape ()Lorg/oppia/android/app/spotlight/SpotlightShape;
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::<init> (Landroid/view/View;Ljava/lang/String;Lorg/oppia/android/app/spotlight/SpotlightShape;Lorg/oppia/android/app/model/Spotlight$FeatureCase;)V
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::<init> (Landroid/view/View;Ljava/lang/String;Lorg/oppia/android/app/spotlight/SpotlightShape;Lorg/oppia/android/app/model/Spotlight$FeatureCase;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorCentreX ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorCentreY ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorHeight ()I
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorLeft ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorTop ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorWidth ()I
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchor ()Landroid/view/View;
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorCentreX ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorCentreY ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorHeight ()I
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorLeft ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorTop ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorWidth ()I
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getFeature ()Lorg/oppia/android/app/model/Spotlight$FeatureCase;
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getHint ()Ljava/lang/String;
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getShape ()Lorg/oppia/android/app/spotlight/SpotlightShape;
FNF:18
FNH:0
DA:14,0
DA:15,0
DA:16,0
DA:17,0
DA:18,0
DA:22,0
DA:24,0
DA:26,0
DA:28,0
DA:30,0
DA:32,0
DA:34,0
DA:35,0
DA:36,0
DA:37,0
DA:38,0
DA:39,0
DA:40,0
DA:41,0
DA:44,0
DA:45,0
DA:46,0
DA:47,0
DA:51,0
DA:52,0
DA:53,0
DA:54,0
DA:58,0
DA:62,0
DA:66,0
DA:70,0
DA:72,0
LH:0
LF:32
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/ActivityLanguageLocaleHandler.kt
FN:30,org/oppia/android/app/translation/ActivityLanguageLocaleHandler$displayLocale$2::invoke ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FN:18,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::<init> (Lorg/oppia/android/domain/locale/LocaleController;Lorg/oppia/android/app/translation/AppLanguageLocaleHandler;)V
FN:29,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::getDisplayLocale ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FN:41,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::initializeLocaleForActivity (Landroid/content/res/Configuration;)V
FN:51,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::updateLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)Z
FNDA:1,org/oppia/android/app/translation/ActivityLanguageLocaleHandler$displayLocale$2::invoke ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FNDA:1,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::<init> (Lorg/oppia/android/domain/locale/LocaleController;Lorg/oppia/android/app/translation/AppLanguageLocaleHandler;)V
FNDA:1,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::getDisplayLocale ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FNDA:1,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::initializeLocaleForActivity (Landroid/content/res/Configuration;)V
FNDA:0,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::updateLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)Z
FNF:5
FNH:4
BRDA:53,0,0,-
BRDA:53,0,1,-
BRF:2
BRH:0
DA:18,1
DA:19,1
DA:20,1
DA:21,1
DA:29,1
DA:30,1
DA:41,1
DA:42,1
DA:51,0
DA:52,0
DA:53,0
LH:8
LF:11
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/ActivityRecreator.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/ActivityRecreatorImpl.kt
FN:7,org/oppia/android/app/translation/ActivityRecreatorImpl::<init> ()V
FN:9,org/oppia/android/app/translation/ActivityRecreatorImpl::recreate (Landroidx/appcompat/app/AppCompatActivity;)V
FNDA:0,org/oppia/android/app/translation/ActivityRecreatorImpl::<init> ()V
FNDA:0,org/oppia/android/app/translation/ActivityRecreatorImpl::recreate (Landroidx/appcompat/app/AppCompatActivity;)V
FNF:2
FNH:0
DA:7,0
DA:9,0
DA:10,0
LH:0
LF:3
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/ActivityRecreatorProdModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageActivityInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageActivityInjectorProvider.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageApplicationInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageApplicationInjectorProvider.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageLocaleHandler.kt
FN:20,org/oppia/android/app/translation/AppLanguageLocaleHandler::<init> (Lorg/oppia/android/domain/locale/LocaleController;)V
FN:76,org/oppia/android/app/translation/AppLanguageLocaleHandler::getDisplayLocale ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FN:41,org/oppia/android/app/translation/AppLanguageLocaleHandler::initializeLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)V
FN:56,org/oppia/android/app/translation/AppLanguageLocaleHandler::initializeLocaleForActivity (Landroid/content/res/Configuration;)V
FN:32,org/oppia/android/app/translation/AppLanguageLocaleHandler::isInitialized ()Z
FN:67,org/oppia/android/app/translation/AppLanguageLocaleHandler::updateLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)Z
FN:81,org/oppia/android/app/translation/AppLanguageLocaleHandler::verifyDisplayLocaleIsInitialized ()V
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::<init> (Lorg/oppia/android/domain/locale/LocaleController;)V
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::getDisplayLocale ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::initializeLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)V
FNDA:0,org/oppia/android/app/translation/AppLanguageLocaleHandler::initializeLocaleForActivity (Landroid/content/res/Configuration;)V
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::isInitialized ()Z
FNDA:0,org/oppia/android/app/translation/AppLanguageLocaleHandler::updateLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)Z
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::verifyDisplayLocaleIsInitialized ()V
FNF:7
FNH:5
BRDA:32,0,0,1
BRDA:32,0,1,1
BRDA:41,0,0,1
BRDA:41,0,1,0
BRDA:41,0,2,0
BRDA:41,0,3,1
BRDA:57,0,0,-
BRDA:57,0,1,-
BRDA:68,0,0,-
BRDA:68,0,1,-
BRDA:70,0,0,-
BRDA:70,0,1,-
BRDA:77,0,0,1
BRDA:77,0,1,0
BRDA:81,0,0,0
BRDA:81,0,1,1
BRF:16
BRH:6
DA:20,1
DA:21,1
DA:22,1
DA:32,1
DA:41,1
DA:42,0
DA:45,1
DA:46,1
DA:56,0
DA:57,0
DA:58,0
DA:67,0
DA:68,0
DA:69,0
DA:70,0
DA:76,1
DA:77,1
DA:81,1
DA:82,0
DA:85,1
LH:11
LF:20
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageWatcherMixin.kt
FN:80,org/oppia/android/app/translation/AppLanguageWatcherMixin$initialize$1::<init> (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;Landroidx/lifecycle/LiveData;)V
FN:82,org/oppia/android/app/translation/AppLanguageWatcherMixin$initialize$1::onChanged (Lorg/oppia/android/util/data/AsyncResult;)V
FN:20,org/oppia/android/app/translation/AppLanguageWatcherMixin::<init> (Landroidx/appcompat/app/AppCompatActivity;Lorg/oppia/android/domain/translation/TranslationController;Lorg/oppia/android/app/translation/AppLanguageLocaleHandler;Lorg/oppia/android/domain/locale/LocaleController;Lorg/oppia/android/domain/oppialogger/OppiaLogger;Lorg/oppia/android/app/translation/ActivityRecreator;Lorg/oppia/android/domain/profile/ProfileManagementController;Lorg/oppia/android/app/translation/ActivityLanguageLocaleHandler;)V
FN:43,org/oppia/android/app/translation/AppLanguageWatcherMixin::initialize (Z)V
FNDA:1,org/oppia/android/app/translation/AppLanguageWatcherMixin$initialize$1::<init> (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;Landroidx/lifecycle/LiveData;)V
FNDA:0,org/oppia/android/app/translation/AppLanguageWatcherMixin$initialize$1::onChanged (Lorg/oppia/android/util/data/AsyncResult;)V
FNDA:1,org/oppia/android/app/translation/AppLanguageWatcherMixin::<init> (Landroidx/appcompat/app/AppCompatActivity;Lorg/oppia/android/domain/translation/TranslationController;Lorg/oppia/android/app/translation/AppLanguageLocaleHandler;Lorg/oppia/android/domain/locale/LocaleController;Lorg/oppia/android/domain/oppialogger/OppiaLogger;Lorg/oppia/android/app/translation/ActivityRecreator;Lorg/oppia/android/domain/profile/ProfileManagementController;Lorg/oppia/android/app/translation/ActivityLanguageLocaleHandler;)V
FNDA:1,org/oppia/android/app/translation/AppLanguageWatcherMixin::initialize (Z)V
FNF:4
FNH:3
BRDA:43,0,0,1
BRDA:43,0,1,0
BRDA:72,0,0,0
BRDA:72,0,1,1
BRDA:73,0,0,1
BRDA:73,0,1,0
BRDA:83,0,0,-
BRDA:83,0,1,-
BRDA:86,0,0,-
BRDA:86,0,1,-
BRDA:103,0,0,-
BRDA:103,0,1,-
BRDA:109,0,0,-
BRDA:109,0,1,-
BRF:14
BRH:3
DA:20,1
DA:21,1
DA:22,1
DA:23,1
DA:24,1
DA:25,1
DA:26,1
DA:27,1
DA:28,1
DA:43,1
DA:60,0
DA:61,0
DA:63,0
DA:64,0
DA:66,0
DA:69,1
DA:71,1
DA:72,1
DA:73,1
DA:74,0
DA:77,1
DA:78,1
DA:79,1
DA:80,1
DA:82,0
DA:83,0
DA:86,0
DA:99,0
DA:100,0
DA:103,0
DA:104,0
DA:105,0
DA:106,0
DA:109,0
DA:111,0
DA:114,1
LH:19
LF:36
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/testing/ActivityRecreatorTestModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/testing/TestActivityRecreator.kt
FN:18,org/oppia/android/app/translation/testing/TestActivityRecreator::<init> ()V
FN:28,org/oppia/android/app/translation/testing/TestActivityRecreator::getRecreateCount ()I
FN:24,org/oppia/android/app/translation/testing/TestActivityRecreator::recreate (Landroidx/appcompat/app/AppCompatActivity;)V
FNDA:1,org/oppia/android/app/translation/testing/TestActivityRecreator::<init> ()V
FNDA:0,org/oppia/android/app/translation/testing/TestActivityRecreator::getRecreateCount ()I
FNDA:0,org/oppia/android/app/translation/testing/TestActivityRecreator::recreate (Landroidx/appcompat/app/AppCompatActivity;)V
FNF:3
FNH:1
DA:18,1
DA:19,1
DA:24,0
DA:25,0
DA:28,0
LH:2
LF:5
end_of_record
SF:app/src/main/java/org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory.kt
FN:36,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$createTimer$1::invokeSuspend (Ljava/lang/Object;)Ljava/lang/Object;
FN:80,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runPeriodically$1::invoke ()V
FN:53,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runWithDelay$1::<init> (Landroidx/lifecycle/LiveData;Lkotlin/jvm/functions/Function0;)V
FN:55,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runWithDelay$1::onChanged (Ljava/lang/Object;)V
FN:19,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::<init> (Lkotlinx/coroutines/CoroutineDispatcher;)V
FN:34,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::createTimer (J)Landroidx/lifecycle/LiveData;
FN:79,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runPeriodically (Landroidx/lifecycle/LifecycleOwner;JJLkotlin/jvm/functions/Function0;)V
FN:74,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runPeriodically$default (Lorg/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory;Landroidx/lifecycle/LifecycleOwner;JJLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
FN:50,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runWithDelay (Landroidx/lifecycle/LifecycleOwner;JLkotlin/jvm/functions/Function0;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$createTimer$1::invokeSuspend (Ljava/lang/Object;)Ljava/lang/Object;
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runPeriodically$1::invoke ()V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runWithDelay$1::<init> (Landroidx/lifecycle/LiveData;Lkotlin/jvm/functions/Function0;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runWithDelay$1::onChanged (Ljava/lang/Object;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::<init> (Lkotlinx/coroutines/CoroutineDispatcher;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::createTimer (J)Landroidx/lifecycle/LiveData;
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runPeriodically (Landroidx/lifecycle/LifecycleOwner;JJLkotlin/jvm/functions/Function0;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runPeriodically$default (Lorg/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory;Landroidx/lifecycle/LifecycleOwner;JJLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runWithDelay (Landroidx/lifecycle/LifecycleOwner;JLkotlin/jvm/functions/Function0;)V
FNF:9
FNH:0
DA:19,0
DA:20,0
DA:24,0
DA:34,0
DA:35,0
DA:36,0
DA:37,0
DA:38,0
DA:39,0
DA:50,0
DA:51,0
DA:52,0
DA:53,0
DA:55,0
DA:56,0
DA:57,0
DA:60,0
DA:74,0
DA:75,0
DA:79,0
DA:80,0
DA:81,0
DA:83,0
DA:84,0
LH:0
LF:24
end_of_record
SF:app/src/main/java/org/oppia/android/app/view/ViewComponent.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/view/ViewComponentBuilderInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/view/ViewComponentFactory.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/view/ViewScope.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/viewmodel/ObservableArrayList.kt
FN:7,org/oppia/android/app/viewmodel/ObservableArrayList::<init> ()V
FN:17,org/oppia/android/app/viewmodel/ObservableArrayList::add (ILjava/lang/Object;)V
FN:11,org/oppia/android/app/viewmodel/ObservableArrayList::add (Ljava/lang/Object;)Z
FN:31,org/oppia/android/app/viewmodel/ObservableArrayList::addAll (ILjava/util/Collection;)Z
FN:22,org/oppia/android/app/viewmodel/ObservableArrayList::addAll (Ljava/util/Collection;)Z
FN:69,org/oppia/android/app/viewmodel/ObservableArrayList::addOnListChangedCallback (Landroidx/databinding/ObservableList$OnListChangedCallback;)V
FN:48,org/oppia/android/app/viewmodel/ObservableArrayList::clear ()V
FN:8,org/oppia/android/app/viewmodel/ObservableArrayList::getListeners ()Landroidx/databinding/ListChangeRegistry;
FN:79,org/oppia/android/app/viewmodel/ObservableArrayList::notifyAdd (II)V
FN:83,org/oppia/android/app/viewmodel/ObservableArrayList::notifyRemove (II)V
FN:39,org/oppia/android/app/viewmodel/ObservableArrayList::removeAll (Ljava/util/Collection;)Z
FN:75,org/oppia/android/app/viewmodel/ObservableArrayList::removeOnListChangedCallback (Landroidx/databinding/ObservableList$OnListChangedCallback;)V
FN:62,org/oppia/android/app/viewmodel/ObservableArrayList::removeRange (II)V
FN:56,org/oppia/android/app/viewmodel/ObservableArrayList::set (ILjava/lang/Object;)Ljava/lang/Object;
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::<init> ()V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::add (ILjava/lang/Object;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::add (Ljava/lang/Object;)Z
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::addAll (ILjava/util/Collection;)Z
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::addAll (Ljava/util/Collection;)Z
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::addOnListChangedCallback (Landroidx/databinding/ObservableList$OnListChangedCallback;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::clear ()V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::getListeners ()Landroidx/databinding/ListChangeRegistry;
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::notifyAdd (II)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::notifyRemove (II)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::removeAll (Ljava/util/Collection;)Z
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::removeOnListChangedCallback (Landroidx/databinding/ObservableList$OnListChangedCallback;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::removeRange (II)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::set (ILjava/lang/Object;)Ljava/lang/Object;
FNF:14
FNH:0
DA:7,0
DA:8,0
DA:11,0
DA:12,0
DA:13,0
DA:17,0
DA:18,0
DA:19,0
DA:22,0
DA:23,0
DA:24,0
DA:25,0
DA:27,0
DA:31,0
DA:32,0
DA:33,0
DA:35,0
DA:39,0
DA:40,0
DA:41,0
DA:42,0
DA:44,0
DA:48,0
DA:49,0
DA:50,0
DA:51,0
DA:53,0
DA:56,0
DA:57,0
DA:58,0
DA:62,0
DA:63,0
DA:64,0
DA:69,0
DA:70,0
DA:75,0
DA:76,0
DA:79,0
DA:80,0
DA:83,0
DA:84,0
LH:0
LF:41
end_of_record
SF:app/src/main/java/org/oppia/android/app/viewmodel/ObservableViewModel.kt
FN:9,org/oppia/android/app/viewmodel/ObservableViewModel$callbacks$2::invoke ()Landroidx/databinding/PropertyChangeRegistry;
FN:7,org/oppia/android/app/viewmodel/ObservableViewModel::<init> ()V
FN:17,org/oppia/android/app/viewmodel/ObservableViewModel::addOnPropertyChangedCallback (Landroidx/databinding/Observable$OnPropertyChangedCallback;)V
FN:8,org/oppia/android/app/viewmodel/ObservableViewModel::getCallbacks ()Landroidx/databinding/PropertyChangeRegistry;
FN:22,org/oppia/android/app/viewmodel/ObservableViewModel::notifyChange ()V
FN:27,org/oppia/android/app/viewmodel/ObservableViewModel::notifyPropertyChanged (I)V
FN:13,org/oppia/android/app/viewmodel/ObservableViewModel::removeOnPropertyChangedCallback (Landroidx/databinding/Observable$OnPropertyChangedCallback;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel$callbacks$2::invoke ()Landroidx/databinding/PropertyChangeRegistry;
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::<init> ()V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::addOnPropertyChangedCallback (Landroidx/databinding/Observable$OnPropertyChangedCallback;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::getCallbacks ()Landroidx/databinding/PropertyChangeRegistry;
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::notifyChange ()V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::notifyPropertyChanged (I)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::removeOnPropertyChangedCallback (Landroidx/databinding/Observable$OnPropertyChangedCallback;)V
FNF:7
FNH:0
DA:7,0
DA:8,0
DA:9,0
DA:13,0
DA:14,0
DA:17,0
DA:18,0
DA:22,0
DA:23,0
DA:27,0
DA:28,0
LH:0
LF:11
end_of_record

@Rd4dev
Copy link
Collaborator

Rd4dev commented Jul 26, 2024

@BenHenning Uhmm.. apologies Ben I couldn't remember to bring this up in the meeting. So, you mentioned that the coverage execution fails in cases where the test files don't have their own explicit targets (not the source files). I tried acquiring coverage reports for the test target - SplashActivityTest which has its own explicit target set (for the test file - SplashActivityTest but not for its source).

bazel coverage //app/src/sharedTest/java/org/oppia/android/app/splash:SplashActivityTest --instrumentation_filter=//app/...

The coverage execution does pass when having the test modularized, but as mentioned the generated coverage reports doesn't seem to include coverage data for the related file.

Coverage Report (lengthy report inside)
cat /home/rddev/.cache/bazel/_bazel_rddev/81159660e9f0a21d3064c6805850402d/execroot/__main__/bazel-out/k8-fastbuild/testlogs/app/src/sharedTest/java/org/oppia/android/app/splash/SplashActivityTest/coverage.dat
SF:app/src/main/java/org/oppia/android/app/activity/ActivityComponent.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/ActivityComponentFactory.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/ActivityIntentFactories.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/ActivityScope.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/InjectableAppCompatActivity.kt
FN:19,org/oppia/android/app/activity/InjectableAppCompatActivity::<init> ()V
FN:29,org/oppia/android/app/activity/InjectableAppCompatActivity::attachBaseContext (Landroid/content/Context;)V
FN:48,org/oppia/android/app/activity/InjectableAppCompatActivity::createFragmentComponent (Landroidx/fragment/app/Fragment;)Lorg/oppia/android/app/fragment/FragmentComponent;
FN:92,org/oppia/android/app/activity/InjectableAppCompatActivity::ensureLayoutDirection ()V
FN:26,org/oppia/android/app/activity/InjectableAppCompatActivity::getActivityComponent ()Lorg/oppia/android/app/activity/ActivityComponent;
FN:52,org/oppia/android/app/activity/InjectableAppCompatActivity::getAppLanguageActivityInjector ()Lorg/oppia/android/app/translation/AppLanguageActivityInjector;
FN:38,org/oppia/android/app/activity/InjectableAppCompatActivity::onCreate (Landroid/os/Bundle;)V
FN:43,org/oppia/android/app/activity/InjectableAppCompatActivity::onCreate (Landroid/os/Bundle;Landroid/os/PersistableBundle;)V
FN:55,org/oppia/android/app/activity/InjectableAppCompatActivity::onInitializeActivityComponent (Landroid/content/Context;)V
FN:67,org/oppia/android/app/activity/InjectableAppCompatActivity::onInitializeLocalization (Landroid/content/Context;)Landroid/content/res/Configuration;
FN:26,org/oppia/android/app/activity/InjectableAppCompatActivity::setActivityComponent (Lorg/oppia/android/app/activity/ActivityComponent;)V
FNDA:0,org/oppia/android/app/activity/InjectableAppCompatActivity::<init> ()V
FNDA:0,org/oppia/android/app/activity/InjectableAppCompatActivity::attachBaseContext (Landroid/content/Context;)V
FNDA:0,org/oppia/android/app/activity/InjectableAppCompatActivity::createFragmentComponent (Landroidx/fragment/app/Fragment;)Lorg/oppia/android/app/fragment/FragmentComponent;
FNDA:0,org/oppia/android/app/activity/InjectableAppCompatActivity::ensureLayoutDirection ()V
FNDA:0,org/oppia/android/app/activity/InjectableAppCompatActivity::getActivityComponent ()Lorg/oppia/android/app/activity/ActivityComponent;
FNDA:0,org/oppia/android/app/activity/InjectableAppCompatActivity::getAppLanguageActivityInjector ()Lorg/oppia/android/app/translation/AppLanguageActivityInjector;
FNDA:0,org/oppia/android/app/activity/InjectableAppCompatActivity::onCreate (Landroid/os/Bundle;)V
FNDA:0,org/oppia/android/app/activity/InjectableAppCompatActivity::onCreate (Landroid/os/Bundle;Landroid/os/PersistableBundle;)V
FNDA:0,org/oppia/android/app/activity/InjectableAppCompatActivity::onInitializeActivityComponent (Landroid/content/Context;)V
FNDA:0,org/oppia/android/app/activity/InjectableAppCompatActivity::onInitializeLocalization (Landroid/content/Context;)Landroid/content/res/Configuration;
FNDA:0,org/oppia/android/app/activity/InjectableAppCompatActivity::setActivityComponent (Lorg/oppia/android/app/activity/ActivityComponent;)V
FNF:11
FNH:0
DA:19,0
DA:20,0
DA:26,0
DA:29,0
DA:30,0
DA:32,0
DA:33,0
DA:34,0
DA:35,0
DA:38,0
DA:39,0
DA:40,0
DA:43,0
DA:44,0
DA:45,0
DA:48,0
DA:49,0
DA:52,0
DA:55,0
DA:56,0
DA:57,0
DA:67,0
DA:68,0
DA:69,0
DA:70,0
DA:71,0
DA:73,0
DA:74,0
DA:76,0
DA:77,0
DA:78,0
DA:92,0
DA:93,0
LH:0
LF:33
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity.kt
FN:13,org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity::<init> ()V
FN:16,org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity::initializeMixin (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;)V
FNDA:0,org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity::<init> ()V
FNDA:0,org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity::initializeMixin (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;)V
FNF:2
FNH:0
DA:13,0
DA:16,0
DA:17,0
LH:0
LF:3
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity.kt
FN:13,org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity::<init> ()V
FN:16,org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity::initializeMixin (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;)V
FNDA:0,org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity::<init> ()V
FNDA:0,org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity::initializeMixin (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;)V
FNF:2
FNH:0
DA:13,0
DA:16,0
DA:17,0
LH:0
LF:3
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/route/ActivityRouter.kt
FN:13,org/oppia/android/app/activity/route/ActivityRouter::<init> (Landroidx/appcompat/app/AppCompatActivity;Ljava/util/Map;Lorg/oppia/android/util/logging/ConsoleLogger;)V
FN:20,org/oppia/android/app/activity/route/ActivityRouter::routeToScreen (Lorg/oppia/android/app/model/DestinationScreen;)V
FNDA:0,org/oppia/android/app/activity/route/ActivityRouter::<init> (Landroidx/appcompat/app/AppCompatActivity;Ljava/util/Map;Lorg/oppia/android/util/logging/ConsoleLogger;)V
FNDA:0,org/oppia/android/app/activity/route/ActivityRouter::routeToScreen (Lorg/oppia/android/app/model/DestinationScreen;)V
FNF:2
FNH:0
DA:13,0
DA:14,0
DA:15,0
DA:16,0
DA:20,0
DA:21,0
DA:22,0
DA:23,0
DA:25,0
DA:26,0
DA:28,0
DA:30,0
LH:0
LF:12
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/route/Route.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/route/RouteKey.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationComponent.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationInjectorProvider.kt
FN:29,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getAppLanguageApplicationInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/app/translation/AppLanguageApplicationInjector;
FN:37,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getConsoleLoggerInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/logging/ConsoleLoggerInjector;
FN:26,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getDataProvidersInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/data/DataProvidersInjector;
FN:35,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getDispatcherInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/threading/DispatcherInjector;
FN:33,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getLocaleApplicationInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/domain/locale/LocaleApplicationInjector;
FN:31,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getOppiaClockInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/system/OppiaClockInjector;
FNDA:0,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getAppLanguageApplicationInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/app/translation/AppLanguageApplicationInjector;
FNDA:0,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getConsoleLoggerInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/logging/ConsoleLoggerInjector;
FNDA:1,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getDataProvidersInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/data/DataProvidersInjector;
FNDA:0,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getDispatcherInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/threading/DispatcherInjector;
FNDA:0,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getLocaleApplicationInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/domain/locale/LocaleApplicationInjector;
FNDA:0,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getOppiaClockInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/system/OppiaClockInjector;
FNF:6
FNH:1
DA:26,1
DA:29,0
DA:31,0
DA:33,0
DA:35,0
DA:37,0
LH:1
LF:6
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationStartupListenerModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/FragmentComponent.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/FragmentComponentBuilderInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/FragmentComponentFactory.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/FragmentScope.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment.kt
FN:14,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::<init> ()V
FN:31,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FN:22,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::getBottomSheetFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FN:25,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::onAttach (Landroid/content/Context;)V
FN:22,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::setBottomSheetFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::<init> ()V
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::getBottomSheetFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::onAttach (Landroid/content/Context;)V
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::setBottomSheetFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNF:5
FNH:0
DA:14,0
DA:15,0
DA:22,0
DA:25,0
DA:26,0
DA:27,0
DA:28,0
DA:31,0
DA:32,0
LH:0
LF:9
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/InjectableDialogFragment.kt
FN:14,org/oppia/android/app/fragment/InjectableDialogFragment::<init> ()V
FN:29,org/oppia/android/app/fragment/InjectableDialogFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FN:20,org/oppia/android/app/fragment/InjectableDialogFragment::getFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FN:23,org/oppia/android/app/fragment/InjectableDialogFragment::onAttach (Landroid/content/Context;)V
FN:20,org/oppia/android/app/fragment/InjectableDialogFragment::setFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNDA:1,org/oppia/android/app/fragment/InjectableDialogFragment::<init> ()V
FNDA:0,org/oppia/android/app/fragment/InjectableDialogFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FNDA:1,org/oppia/android/app/fragment/InjectableDialogFragment::getFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FNDA:1,org/oppia/android/app/fragment/InjectableDialogFragment::onAttach (Landroid/content/Context;)V
FNDA:1,org/oppia/android/app/fragment/InjectableDialogFragment::setFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNF:5
FNH:4
BRDA:20,0,0,1
BRDA:20,0,1,0
BRF:2
BRH:1
DA:14,1
DA:20,1
DA:23,1
DA:24,1
DA:25,1
DA:26,1
DA:29,0
DA:30,0
LH:6
LF:8
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/InjectableFragment.kt
FN:14,org/oppia/android/app/fragment/InjectableFragment::<init> ()V
FN:29,org/oppia/android/app/fragment/InjectableFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FN:20,org/oppia/android/app/fragment/InjectableFragment::getFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FN:23,org/oppia/android/app/fragment/InjectableFragment::onAttach (Landroid/content/Context;)V
FN:20,org/oppia/android/app/fragment/InjectableFragment::setFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNDA:0,org/oppia/android/app/fragment/InjectableFragment::<init> ()V
FNDA:0,org/oppia/android/app/fragment/InjectableFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableFragment::getFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableFragment::onAttach (Landroid/content/Context;)V
FNDA:0,org/oppia/android/app/fragment/InjectableFragment::setFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNF:5
FNH:0
DA:14,0
DA:20,0
DA:23,0
DA:24,0
DA:25,0
DA:26,0
DA:29,0
DA:30,0
LH:0
LF:8
end_of_record
SF:app/src/main/java/org/oppia/android/app/shim/IntentFactoryShim.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/shim/IntentFactoryShimModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/shim/ViewBindingShim.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/shim/ViewBindingShimModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/spotlight/SpotlightManager.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/spotlight/SpotlightNavigationListener.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/spotlight/SpotlightShape.kt
FN:6,org/oppia/android/app/spotlight/SpotlightShape$Circle::<init> ()V
FN:9,org/oppia/android/app/spotlight/SpotlightShape$RoundedRectangle::<init> ()V
FNDA:0,org/oppia/android/app/spotlight/SpotlightShape$Circle::<init> ()V
FNDA:0,org/oppia/android/app/spotlight/SpotlightShape$RoundedRectangle::<init> ()V
FNF:2
FNH:0
DA:6,0
DA:9,0
LH:0
LF:2
end_of_record
SF:app/src/main/java/org/oppia/android/app/spotlight/SpotlightTarget.kt
FN:14,org/oppia/android/app/spotlight/SpotlightTarget::<init> (Landroid/view/View;Ljava/lang/String;Lorg/oppia/android/app/spotlight/SpotlightShape;Lorg/oppia/android/app/model/Spotlight$FeatureCase;)V
FN:14,org/oppia/android/app/spotlight/SpotlightTarget::<init> (Landroid/view/View;Ljava/lang/String;Lorg/oppia/android/app/spotlight/SpotlightShape;Lorg/oppia/android/app/model/Spotlight$FeatureCase;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
FN:66,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorCentreX ()F
FN:70,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorCentreY ()F
FN:58,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorHeight ()I
FN:44,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorLeft ()F
FN:51,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorTop ()F
FN:62,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorWidth ()I
FN:15,org/oppia/android/app/spotlight/SpotlightTarget::getAnchor ()Landroid/view/View;
FN:30,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorCentreX ()F
FN:32,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorCentreY ()F
FN:26,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorHeight ()I
FN:22,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorLeft ()F
FN:24,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorTop ()F
FN:28,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorWidth ()I
FN:18,org/oppia/android/app/spotlight/SpotlightTarget::getFeature ()Lorg/oppia/android/app/model/Spotlight$FeatureCase;
FN:16,org/oppia/android/app/spotlight/SpotlightTarget::getHint ()Ljava/lang/String;
FN:17,org/oppia/android/app/spotlight/SpotlightTarget::getShape ()Lorg/oppia/android/app/spotlight/SpotlightShape;
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::<init> (Landroid/view/View;Ljava/lang/String;Lorg/oppia/android/app/spotlight/SpotlightShape;Lorg/oppia/android/app/model/Spotlight$FeatureCase;)V
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::<init> (Landroid/view/View;Ljava/lang/String;Lorg/oppia/android/app/spotlight/SpotlightShape;Lorg/oppia/android/app/model/Spotlight$FeatureCase;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorCentreX ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorCentreY ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorHeight ()I
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorLeft ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorTop ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorWidth ()I
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchor ()Landroid/view/View;
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorCentreX ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorCentreY ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorHeight ()I
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorLeft ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorTop ()F
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorWidth ()I
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getFeature ()Lorg/oppia/android/app/model/Spotlight$FeatureCase;
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getHint ()Ljava/lang/String;
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::getShape ()Lorg/oppia/android/app/spotlight/SpotlightShape;
FNF:18
FNH:0
DA:14,0
DA:15,0
DA:16,0
DA:17,0
DA:18,0
DA:22,0
DA:24,0
DA:26,0
DA:28,0
DA:30,0
DA:32,0
DA:34,0
DA:35,0
DA:36,0
DA:37,0
DA:38,0
DA:39,0
DA:40,0
DA:41,0
DA:44,0
DA:45,0
DA:46,0
DA:47,0
DA:51,0
DA:52,0
DA:53,0
DA:54,0
DA:58,0
DA:62,0
DA:66,0
DA:70,0
DA:72,0
LH:0
LF:32
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/ActivityLanguageLocaleHandler.kt
FN:30,org/oppia/android/app/translation/ActivityLanguageLocaleHandler$displayLocale$2::invoke ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FN:18,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::<init> (Lorg/oppia/android/domain/locale/LocaleController;Lorg/oppia/android/app/translation/AppLanguageLocaleHandler;)V
FN:29,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::getDisplayLocale ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FN:41,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::initializeLocaleForActivity (Landroid/content/res/Configuration;)V
FN:51,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::updateLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)Z
FNDA:0,org/oppia/android/app/translation/ActivityLanguageLocaleHandler$displayLocale$2::invoke ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FNDA:0,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::<init> (Lorg/oppia/android/domain/locale/LocaleController;Lorg/oppia/android/app/translation/AppLanguageLocaleHandler;)V
FNDA:0,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::getDisplayLocale ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FNDA:0,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::initializeLocaleForActivity (Landroid/content/res/Configuration;)V
FNDA:0,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::updateLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)Z
FNF:5
FNH:0
DA:18,0
DA:19,0
DA:20,0
DA:21,0
DA:29,0
DA:30,0
DA:41,0
DA:42,0
DA:51,0
DA:52,0
DA:53,0
LH:0
LF:11
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/ActivityRecreator.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/ActivityRecreatorImpl.kt
FN:7,org/oppia/android/app/translation/ActivityRecreatorImpl::<init> ()V
FN:9,org/oppia/android/app/translation/ActivityRecreatorImpl::recreate (Landroidx/appcompat/app/AppCompatActivity;)V
FNDA:0,org/oppia/android/app/translation/ActivityRecreatorImpl::<init> ()V
FNDA:0,org/oppia/android/app/translation/ActivityRecreatorImpl::recreate (Landroidx/appcompat/app/AppCompatActivity;)V
FNF:2
FNH:0
DA:7,0
DA:9,0
DA:10,0
LH:0
LF:3
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/ActivityRecreatorProdModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageActivityInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageActivityInjectorProvider.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageApplicationInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageApplicationInjectorProvider.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageLocaleHandler.kt
FN:20,org/oppia/android/app/translation/AppLanguageLocaleHandler::<init> (Lorg/oppia/android/domain/locale/LocaleController;)V
FN:76,org/oppia/android/app/translation/AppLanguageLocaleHandler::getDisplayLocale ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FN:41,org/oppia/android/app/translation/AppLanguageLocaleHandler::initializeLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)V
FN:56,org/oppia/android/app/translation/AppLanguageLocaleHandler::initializeLocaleForActivity (Landroid/content/res/Configuration;)V
FN:32,org/oppia/android/app/translation/AppLanguageLocaleHandler::isInitialized ()Z
FN:67,org/oppia/android/app/translation/AppLanguageLocaleHandler::updateLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)Z
FN:81,org/oppia/android/app/translation/AppLanguageLocaleHandler::verifyDisplayLocaleIsInitialized ()V
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::<init> (Lorg/oppia/android/domain/locale/LocaleController;)V
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::getDisplayLocale ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::initializeLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)V
FNDA:0,org/oppia/android/app/translation/AppLanguageLocaleHandler::initializeLocaleForActivity (Landroid/content/res/Configuration;)V
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::isInitialized ()Z
FNDA:0,org/oppia/android/app/translation/AppLanguageLocaleHandler::updateLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)Z
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::verifyDisplayLocaleIsInitialized ()V
FNF:7
FNH:5
BRDA:32,0,0,1
BRDA:32,0,1,1
BRDA:41,0,0,1
BRDA:41,0,1,0
BRDA:41,0,2,0
BRDA:41,0,3,1
BRDA:57,0,0,-
BRDA:57,0,1,-
BRDA:68,0,0,-
BRDA:68,0,1,-
BRDA:70,0,0,-
BRDA:70,0,1,-
BRDA:77,0,0,1
BRDA:77,0,1,0
BRDA:81,0,0,0
BRDA:81,0,1,1
BRF:16
BRH:6
DA:20,1
DA:21,1
DA:22,1
DA:32,1
DA:41,1
DA:42,0
DA:45,1
DA:46,1
DA:56,0
DA:57,0
DA:58,0
DA:67,0
DA:68,0
DA:69,0
DA:70,0
DA:76,1
DA:77,1
DA:81,1
DA:82,0
DA:85,1
LH:11
LF:20
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageWatcherMixin.kt
FN:80,org/oppia/android/app/translation/AppLanguageWatcherMixin$initialize$1::<init> (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;Landroidx/lifecycle/LiveData;)V
FN:82,org/oppia/android/app/translation/AppLanguageWatcherMixin$initialize$1::onChanged (Lorg/oppia/android/util/data/AsyncResult;)V
FN:20,org/oppia/android/app/translation/AppLanguageWatcherMixin::<init> (Landroidx/appcompat/app/AppCompatActivity;Lorg/oppia/android/domain/translation/TranslationController;Lorg/oppia/android/app/translation/AppLanguageLocaleHandler;Lorg/oppia/android/domain/locale/LocaleController;Lorg/oppia/android/domain/oppialogger/OppiaLogger;Lorg/oppia/android/app/translation/ActivityRecreator;Lorg/oppia/android/domain/profile/ProfileManagementController;Lorg/oppia/android/app/translation/ActivityLanguageLocaleHandler;)V
FN:43,org/oppia/android/app/translation/AppLanguageWatcherMixin::initialize (Z)V
FNDA:0,org/oppia/android/app/translation/AppLanguageWatcherMixin$initialize$1::<init> (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;Landroidx/lifecycle/LiveData;)V
FNDA:0,org/oppia/android/app/translation/AppLanguageWatcherMixin$initialize$1::onChanged (Lorg/oppia/android/util/data/AsyncResult;)V
FNDA:0,org/oppia/android/app/translation/AppLanguageWatcherMixin::<init> (Landroidx/appcompat/app/AppCompatActivity;Lorg/oppia/android/domain/translation/TranslationController;Lorg/oppia/android/app/translation/AppLanguageLocaleHandler;Lorg/oppia/android/domain/locale/LocaleController;Lorg/oppia/android/domain/oppialogger/OppiaLogger;Lorg/oppia/android/app/translation/ActivityRecreator;Lorg/oppia/android/domain/profile/ProfileManagementController;Lorg/oppia/android/app/translation/ActivityLanguageLocaleHandler;)V
FNDA:0,org/oppia/android/app/translation/AppLanguageWatcherMixin::initialize (Z)V
FNF:4
FNH:0
DA:20,0
DA:21,0
DA:22,0
DA:23,0
DA:24,0
DA:25,0
DA:26,0
DA:27,0
DA:28,0
DA:43,0
DA:60,0
DA:61,0
DA:63,0
DA:64,0
DA:66,0
DA:69,0
DA:71,0
DA:72,0
DA:73,0
DA:74,0
DA:77,0
DA:78,0
DA:79,0
DA:80,0
DA:82,0
DA:83,0
DA:86,0
DA:99,0
DA:100,0
DA:103,0
DA:104,0
DA:105,0
DA:106,0
DA:109,0
DA:111,0
DA:114,0
LH:0
LF:36
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/testing/ActivityRecreatorTestModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/testing/TestActivityRecreator.kt
FN:18,org/oppia/android/app/translation/testing/TestActivityRecreator::<init> ()V
FN:28,org/oppia/android/app/translation/testing/TestActivityRecreator::getRecreateCount ()I
FN:24,org/oppia/android/app/translation/testing/TestActivityRecreator::recreate (Landroidx/appcompat/app/AppCompatActivity;)V
FNDA:0,org/oppia/android/app/translation/testing/TestActivityRecreator::<init> ()V
FNDA:0,org/oppia/android/app/translation/testing/TestActivityRecreator::getRecreateCount ()I
FNDA:0,org/oppia/android/app/translation/testing/TestActivityRecreator::recreate (Landroidx/appcompat/app/AppCompatActivity;)V
FNF:3
FNH:0
DA:18,0
DA:19,0
DA:24,0
DA:25,0
DA:28,0
LH:0
LF:5
end_of_record
SF:app/src/main/java/org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory.kt
FN:36,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$createTimer$1::invokeSuspend (Ljava/lang/Object;)Ljava/lang/Object;
FN:80,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runPeriodically$1::invoke ()V
FN:53,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runWithDelay$1::<init> (Landroidx/lifecycle/LiveData;Lkotlin/jvm/functions/Function0;)V
FN:55,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runWithDelay$1::onChanged (Ljava/lang/Object;)V
FN:19,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::<init> (Lkotlinx/coroutines/CoroutineDispatcher;)V
FN:34,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::createTimer (J)Landroidx/lifecycle/LiveData;
FN:79,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runPeriodically (Landroidx/lifecycle/LifecycleOwner;JJLkotlin/jvm/functions/Function0;)V
FN:74,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runPeriodically$default (Lorg/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory;Landroidx/lifecycle/LifecycleOwner;JJLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
FN:50,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runWithDelay (Landroidx/lifecycle/LifecycleOwner;JLkotlin/jvm/functions/Function0;)V
FNDA:1,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$createTimer$1::invokeSuspend (Ljava/lang/Object;)Ljava/lang/Object;
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runPeriodically$1::invoke ()V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runWithDelay$1::<init> (Landroidx/lifecycle/LiveData;Lkotlin/jvm/functions/Function0;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runWithDelay$1::onChanged (Ljava/lang/Object;)V
FNDA:1,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::<init> (Lkotlinx/coroutines/CoroutineDispatcher;)V
FNDA:1,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::createTimer (J)Landroidx/lifecycle/LiveData;
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runPeriodically (Landroidx/lifecycle/LifecycleOwner;JJLkotlin/jvm/functions/Function0;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runPeriodically$default (Lorg/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory;Landroidx/lifecycle/LifecycleOwner;JJLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runWithDelay (Landroidx/lifecycle/LifecycleOwner;JLkotlin/jvm/functions/Function0;)V
FNF:9
FNH:3
DA:19,1
DA:20,1
DA:24,1
DA:34,1
DA:35,1
DA:36,1
DA:37,1
DA:38,1
DA:39,1
DA:50,0
DA:51,0
DA:52,0
DA:53,0
DA:55,0
DA:56,0
DA:57,0
DA:60,0
DA:74,0
DA:75,0
DA:79,0
DA:80,0
DA:81,0
DA:83,0
DA:84,0
LH:9
LF:24
end_of_record
SF:app/src/main/java/org/oppia/android/app/view/ViewComponent.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/view/ViewComponentBuilderInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/view/ViewComponentFactory.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/view/ViewScope.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/viewmodel/ObservableArrayList.kt
FN:7,org/oppia/android/app/viewmodel/ObservableArrayList::<init> ()V
FN:17,org/oppia/android/app/viewmodel/ObservableArrayList::add (ILjava/lang/Object;)V
FN:11,org/oppia/android/app/viewmodel/ObservableArrayList::add (Ljava/lang/Object;)Z
FN:31,org/oppia/android/app/viewmodel/ObservableArrayList::addAll (ILjava/util/Collection;)Z
FN:22,org/oppia/android/app/viewmodel/ObservableArrayList::addAll (Ljava/util/Collection;)Z
FN:69,org/oppia/android/app/viewmodel/ObservableArrayList::addOnListChangedCallback (Landroidx/databinding/ObservableList$OnListChangedCallback;)V
FN:48,org/oppia/android/app/viewmodel/ObservableArrayList::clear ()V
FN:8,org/oppia/android/app/viewmodel/ObservableArrayList::getListeners ()Landroidx/databinding/ListChangeRegistry;
FN:79,org/oppia/android/app/viewmodel/ObservableArrayList::notifyAdd (II)V
FN:83,org/oppia/android/app/viewmodel/ObservableArrayList::notifyRemove (II)V
FN:39,org/oppia/android/app/viewmodel/ObservableArrayList::removeAll (Ljava/util/Collection;)Z
FN:75,org/oppia/android/app/viewmodel/ObservableArrayList::removeOnListChangedCallback (Landroidx/databinding/ObservableList$OnListChangedCallback;)V
FN:62,org/oppia/android/app/viewmodel/ObservableArrayList::removeRange (II)V
FN:56,org/oppia/android/app/viewmodel/ObservableArrayList::set (ILjava/lang/Object;)Ljava/lang/Object;
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::<init> ()V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::add (ILjava/lang/Object;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::add (Ljava/lang/Object;)Z
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::addAll (ILjava/util/Collection;)Z
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::addAll (Ljava/util/Collection;)Z
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::addOnListChangedCallback (Landroidx/databinding/ObservableList$OnListChangedCallback;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::clear ()V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::getListeners ()Landroidx/databinding/ListChangeRegistry;
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::notifyAdd (II)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::notifyRemove (II)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::removeAll (Ljava/util/Collection;)Z
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::removeOnListChangedCallback (Landroidx/databinding/ObservableList$OnListChangedCallback;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::removeRange (II)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::set (ILjava/lang/Object;)Ljava/lang/Object;
FNF:14
FNH:0
DA:7,0
DA:8,0
DA:11,0
DA:12,0
DA:13,0
DA:17,0
DA:18,0
DA:19,0
DA:22,0
DA:23,0
DA:24,0
DA:25,0
DA:27,0
DA:31,0
DA:32,0
DA:33,0
DA:35,0
DA:39,0
DA:40,0
DA:41,0
DA:42,0
DA:44,0
DA:48,0
DA:49,0
DA:50,0
DA:51,0
DA:53,0
DA:56,0
DA:57,0
DA:58,0
DA:62,0
DA:63,0
DA:64,0
DA:69,0
DA:70,0
DA:75,0
DA:76,0
DA:79,0
DA:80,0
DA:83,0
DA:84,0
LH:0
LF:41
end_of_record
SF:app/src/main/java/org/oppia/android/app/viewmodel/ObservableViewModel.kt
FN:9,org/oppia/android/app/viewmodel/ObservableViewModel$callbacks$2::invoke ()Landroidx/databinding/PropertyChangeRegistry;
FN:7,org/oppia/android/app/viewmodel/ObservableViewModel::<init> ()V
FN:17,org/oppia/android/app/viewmodel/ObservableViewModel::addOnPropertyChangedCallback (Landroidx/databinding/Observable$OnPropertyChangedCallback;)V
FN:8,org/oppia/android/app/viewmodel/ObservableViewModel::getCallbacks ()Landroidx/databinding/PropertyChangeRegistry;
FN:22,org/oppia/android/app/viewmodel/ObservableViewModel::notifyChange ()V
FN:27,org/oppia/android/app/viewmodel/ObservableViewModel::notifyPropertyChanged (I)V
FN:13,org/oppia/android/app/viewmodel/ObservableViewModel::removeOnPropertyChangedCallback (Landroidx/databinding/Observable$OnPropertyChangedCallback;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel$callbacks$2::invoke ()Landroidx/databinding/PropertyChangeRegistry;
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::<init> ()V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::addOnPropertyChangedCallback (Landroidx/databinding/Observable$OnPropertyChangedCallback;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::getCallbacks ()Landroidx/databinding/PropertyChangeRegistry;
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::notifyChange ()V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::notifyPropertyChanged (I)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::removeOnPropertyChangedCallback (Landroidx/databinding/Observable$OnPropertyChangedCallback;)V
FNF:7
FNH:0
DA:7,0
DA:8,0
DA:9,0
DA:13,0
DA:14,0
DA:17,0
DA:18,0
DA:22,0
DA:23,0
DA:27,0
DA:28,0
LH:0
LF:11
end_of_record

And there were doubts if that could be due to having the genrule - I think that's the case. Just wanted to provide an example of confirming the scenerio.

The files in the app/src/main/java/org/oppia/android/app/spotlight package has the following files

  • SpotlightFragment
  • SpotlightManager
  • SpotlightNavigationListener
  • SpotlightShape
  • SpotlightTarget

app/src/main/java/org/oppia/android/app/spotlight/BUILD.bazel

"""
Constructs for setting up spotlights.
"""

load("@io_bazel_rules_kotlin//kotlin:android.bzl", "kt_android_library")

genrule(
    name = "update_SpotlightFragment",
    srcs = ["SpotlightFragment.kt"],
    outs = ["SpotlightFragment_updated.kt"],
    cmd = """
    cat $(SRCS) |
    sed 's/import org.oppia.android.R/import org.oppia.android.app.R/g' |
    sed 's/import org.oppia.android.databinding./import org.oppia.android.app.databinding.databinding./g' > $(OUTS)
    """,
    visibility = ["//app:app_visibility"],
)

kt_android_library(
    name = "spotlight",
    srcs = [
        "SpotlightManager.kt",
        "SpotlightNavigationListener.kt",
        "SpotlightShape.kt",
        "SpotlightTarget.kt",
    ],
    visibility = ["//app:app_visibility"],
    deps = ["//model/src/main/proto:spotlight_java_proto_lite"],
)

It only has tests for SpotlightFragment -> SpotlightFragmentTest (but it doesn't have explicit test target declared) and running the command

bazel coverage //app:src/sharedTest/java/org/oppia/android/app/spotlight/SpotlightFragmentTest --instrumentation_filter=//app/..

does produce pass result but most importantly it includes / provides coverage data for the files
(under kt_android_library)

  • SpotlightTarget
  • SpotlightShape
  • SpotlightNavigationListener
  • SpotlightManager

and ignores the report for the file
(under genrule)

  • SpotlightFragment (as mentioned with name = "update_SpotlightFragment")
Coverage report with spotlight files included (lengthy report)
cat /home/rddev/.cache/bazel/_bazel_rddev/81159660e9f0a21d3064c6805850402d/execroot/__main__/bazel-out/k8-fastbuild/testlogs/app/src/sharedTest/java/org/oppia/android/app/spotlight/SpotlightFragmentTest/coverage.dat
SF:app/src/main/java/org/oppia/android/app/activity/ActivityComponent.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/ActivityComponentFactory.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/ActivityIntentFactories.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/ActivityScope.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/InjectableAppCompatActivity.kt
FN:19,org/oppia/android/app/activity/InjectableAppCompatActivity::<init> ()V
FN:29,org/oppia/android/app/activity/InjectableAppCompatActivity::attachBaseContext (Landroid/content/Context;)V
FN:48,org/oppia/android/app/activity/InjectableAppCompatActivity::createFragmentComponent (Landroidx/fragment/app/Fragment;)Lorg/oppia/android/app/fragment/FragmentComponent;
FN:92,org/oppia/android/app/activity/InjectableAppCompatActivity::ensureLayoutDirection ()V
FN:26,org/oppia/android/app/activity/InjectableAppCompatActivity::getActivityComponent ()Lorg/oppia/android/app/activity/ActivityComponent;
FN:52,org/oppia/android/app/activity/InjectableAppCompatActivity::getAppLanguageActivityInjector ()Lorg/oppia/android/app/translation/AppLanguageActivityInjector;
FN:38,org/oppia/android/app/activity/InjectableAppCompatActivity::onCreate (Landroid/os/Bundle;)V
FN:43,org/oppia/android/app/activity/InjectableAppCompatActivity::onCreate (Landroid/os/Bundle;Landroid/os/PersistableBundle;)V
FN:55,org/oppia/android/app/activity/InjectableAppCompatActivity::onInitializeActivityComponent (Landroid/content/Context;)V
FN:67,org/oppia/android/app/activity/InjectableAppCompatActivity::onInitializeLocalization (Landroid/content/Context;)Landroid/content/res/Configuration;
FN:26,org/oppia/android/app/activity/InjectableAppCompatActivity::setActivityComponent (Lorg/oppia/android/app/activity/ActivityComponent;)V
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::<init> ()V
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::attachBaseContext (Landroid/content/Context;)V
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::createFragmentComponent (Landroidx/fragment/app/Fragment;)Lorg/oppia/android/app/fragment/FragmentComponent;
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::ensureLayoutDirection ()V
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::getActivityComponent ()Lorg/oppia/android/app/activity/ActivityComponent;
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::getAppLanguageActivityInjector ()Lorg/oppia/android/app/translation/AppLanguageActivityInjector;
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::onCreate (Landroid/os/Bundle;)V
FNDA:0,org/oppia/android/app/activity/InjectableAppCompatActivity::onCreate (Landroid/os/Bundle;Landroid/os/PersistableBundle;)V
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::onInitializeActivityComponent (Landroid/content/Context;)V
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::onInitializeLocalization (Landroid/content/Context;)Landroid/content/res/Configuration;
FNDA:1,org/oppia/android/app/activity/InjectableAppCompatActivity::setActivityComponent (Lorg/oppia/android/app/activity/ActivityComponent;)V
FNF:11
FNH:10
BRDA:26,0,0,1
BRDA:26,0,1,0
BRDA:29,0,0,0
BRDA:29,0,1,1
BRDA:29,0,2,0
BRDA:29,0,3,1
BRDA:34,0,0,0
BRDA:34,0,1,1
BRDA:76,0,0,0
BRDA:76,0,1,1
BRDA:76,0,2,0
BRDA:76,0,3,1
BRF:12
BRH:6
DA:19,1
DA:20,1
DA:26,1
DA:29,1
DA:30,0
DA:32,1
DA:33,1
DA:34,1
DA:35,1
DA:38,1
DA:39,1
DA:40,1
DA:43,0
DA:44,0
DA:45,0
DA:48,1
DA:49,1
DA:52,1
DA:55,1
DA:56,1
DA:57,1
DA:67,1
DA:68,1
DA:69,1
DA:70,1
DA:71,1
DA:73,1
DA:74,1
DA:76,1
DA:77,1
DA:78,1
DA:92,1
DA:93,1
LH:29
LF:33
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity.kt
FN:13,org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity::<init> ()V
FN:16,org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity::initializeMixin (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;)V
FNDA:1,org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity::<init> ()V
FNDA:1,org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity::initializeMixin (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;)V
FNF:2
FNH:2
DA:13,1
DA:16,1
DA:17,1
LH:3
LF:3
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity.kt
FN:13,org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity::<init> ()V
FN:16,org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity::initializeMixin (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;)V
FNDA:0,org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity::<init> ()V
FNDA:0,org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity::initializeMixin (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;)V
FNF:2
FNH:0
DA:13,0
DA:16,0
DA:17,0
LH:0
LF:3
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/route/ActivityRouter.kt
FN:13,org/oppia/android/app/activity/route/ActivityRouter::<init> (Landroidx/appcompat/app/AppCompatActivity;Ljava/util/Map;Lorg/oppia/android/util/logging/ConsoleLogger;)V
FN:20,org/oppia/android/app/activity/route/ActivityRouter::routeToScreen (Lorg/oppia/android/app/model/DestinationScreen;)V
FNDA:1,org/oppia/android/app/activity/route/ActivityRouter::<init> (Landroidx/appcompat/app/AppCompatActivity;Ljava/util/Map;Lorg/oppia/android/util/logging/ConsoleLogger;)V
FNDA:0,org/oppia/android/app/activity/route/ActivityRouter::routeToScreen (Lorg/oppia/android/app/model/DestinationScreen;)V
FNF:2
FNH:1
BRDA:20,0,0,-
BRDA:20,0,1,-
BRDA:25,0,0,-
BRDA:25,0,1,-
BRF:4
BRH:0
DA:13,1
DA:14,1
DA:15,1
DA:16,1
DA:20,0
DA:21,0
DA:22,0
DA:23,0
DA:25,0
DA:26,0
DA:28,0
DA:30,0
LH:4
LF:12
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/route/Route.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/activity/route/RouteKey.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationComponent.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationInjectorProvider.kt
FN:29,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getAppLanguageApplicationInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/app/translation/AppLanguageApplicationInjector;
FN:37,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getConsoleLoggerInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/logging/ConsoleLoggerInjector;
FN:26,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getDataProvidersInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/data/DataProvidersInjector;
FN:35,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getDispatcherInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/threading/DispatcherInjector;
FN:33,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getLocaleApplicationInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/domain/locale/LocaleApplicationInjector;
FN:31,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getOppiaClockInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/system/OppiaClockInjector;
FNDA:0,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getAppLanguageApplicationInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/app/translation/AppLanguageApplicationInjector;
FNDA:0,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getConsoleLoggerInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/logging/ConsoleLoggerInjector;
FNDA:1,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getDataProvidersInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/data/DataProvidersInjector;
FNDA:0,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getDispatcherInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/threading/DispatcherInjector;
FNDA:0,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getLocaleApplicationInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/domain/locale/LocaleApplicationInjector;
FNDA:0,org/oppia/android/app/application/ApplicationInjectorProvider$DefaultImpls::getOppiaClockInjector (Lorg/oppia/android/app/application/ApplicationInjectorProvider;)Lorg/oppia/android/util/system/OppiaClockInjector;
FNF:6
FNH:1
DA:26,1
DA:29,0
DA:31,0
DA:33,0
DA:35,0
DA:37,0
LH:1
LF:6
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/ApplicationStartupListenerModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/application/testing/TestingBuildFlavorModule.kt
FN:11,org/oppia/android/app/application/testing/TestingBuildFlavorModule::<init> ()V
FN:14,org/oppia/android/app/application/testing/TestingBuildFlavorModule::provideTestingBuildFlavor ()Lorg/oppia/android/app/model/BuildFlavor;
FNDA:1,org/oppia/android/app/application/testing/TestingBuildFlavorModule::<init> ()V
FNDA:0,org/oppia/android/app/application/testing/TestingBuildFlavorModule::provideTestingBuildFlavor ()Lorg/oppia/android/app/model/BuildFlavor;
FNF:2
FNH:1
DA:11,1
DA:12,1
DA:14,0
LH:2
LF:3
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/FragmentComponent.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/FragmentComponentBuilderInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/FragmentComponentFactory.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/FragmentScope.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment.kt
FN:14,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::<init> ()V
FN:31,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FN:22,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::getBottomSheetFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FN:25,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::onAttach (Landroid/content/Context;)V
FN:22,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::setBottomSheetFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::<init> ()V
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::getBottomSheetFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::onAttach (Landroid/content/Context;)V
FNDA:0,org/oppia/android/app/fragment/InjectableBottomSheetDialogFragment::setBottomSheetFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNF:5
FNH:0
DA:14,0
DA:15,0
DA:22,0
DA:25,0
DA:26,0
DA:27,0
DA:28,0
DA:31,0
DA:32,0
LH:0
LF:9
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/InjectableDialogFragment.kt
FN:14,org/oppia/android/app/fragment/InjectableDialogFragment::<init> ()V
FN:29,org/oppia/android/app/fragment/InjectableDialogFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FN:20,org/oppia/android/app/fragment/InjectableDialogFragment::getFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FN:23,org/oppia/android/app/fragment/InjectableDialogFragment::onAttach (Landroid/content/Context;)V
FN:20,org/oppia/android/app/fragment/InjectableDialogFragment::setFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNDA:0,org/oppia/android/app/fragment/InjectableDialogFragment::<init> ()V
FNDA:0,org/oppia/android/app/fragment/InjectableDialogFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableDialogFragment::getFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FNDA:0,org/oppia/android/app/fragment/InjectableDialogFragment::onAttach (Landroid/content/Context;)V
FNDA:0,org/oppia/android/app/fragment/InjectableDialogFragment::setFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNF:5
FNH:0
DA:14,0
DA:20,0
DA:23,0
DA:24,0
DA:25,0
DA:26,0
DA:29,0
DA:30,0
LH:0
LF:8
end_of_record
SF:app/src/main/java/org/oppia/android/app/fragment/InjectableFragment.kt
FN:14,org/oppia/android/app/fragment/InjectableFragment::<init> ()V
FN:29,org/oppia/android/app/fragment/InjectableFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FN:20,org/oppia/android/app/fragment/InjectableFragment::getFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FN:23,org/oppia/android/app/fragment/InjectableFragment::onAttach (Landroid/content/Context;)V
FN:20,org/oppia/android/app/fragment/InjectableFragment::setFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNDA:1,org/oppia/android/app/fragment/InjectableFragment::<init> ()V
FNDA:0,org/oppia/android/app/fragment/InjectableFragment::createViewComponent (Landroid/view/View;)Lorg/oppia/android/app/view/ViewComponent;
FNDA:1,org/oppia/android/app/fragment/InjectableFragment::getFragmentComponent ()Lorg/oppia/android/app/fragment/FragmentComponent;
FNDA:1,org/oppia/android/app/fragment/InjectableFragment::onAttach (Landroid/content/Context;)V
FNDA:1,org/oppia/android/app/fragment/InjectableFragment::setFragmentComponent (Lorg/oppia/android/app/fragment/FragmentComponent;)V
FNF:5
FNH:4
BRDA:20,0,0,1
BRDA:20,0,1,0
BRF:2
BRH:1
DA:14,1
DA:20,1
DA:23,1
DA:24,1
DA:25,1
DA:26,1
DA:29,0
DA:30,0
LH:6
LF:8
end_of_record
SF:app/src/main/java/org/oppia/android/app/shim/IntentFactoryShim.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/shim/IntentFactoryShimModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/shim/ViewBindingShim.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/shim/ViewBindingShimModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/spotlight/SpotlightManager.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/spotlight/SpotlightNavigationListener.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/spotlight/SpotlightShape.kt
FN:6,org/oppia/android/app/spotlight/SpotlightShape$Circle::<init> ()V
FN:9,org/oppia/android/app/spotlight/SpotlightShape$RoundedRectangle::<init> ()V
FNDA:0,org/oppia/android/app/spotlight/SpotlightShape$Circle::<init> ()V
FNDA:1,org/oppia/android/app/spotlight/SpotlightShape$RoundedRectangle::<init> ()V
FNF:2
FNH:1
DA:6,0
DA:9,1
LH:1
LF:2
end_of_record
SF:app/src/main/java/org/oppia/android/app/spotlight/SpotlightTarget.kt
FN:14,org/oppia/android/app/spotlight/SpotlightTarget::<init> (Landroid/view/View;Ljava/lang/String;Lorg/oppia/android/app/spotlight/SpotlightShape;Lorg/oppia/android/app/model/Spotlight$FeatureCase;)V
FN:14,org/oppia/android/app/spotlight/SpotlightTarget::<init> (Landroid/view/View;Ljava/lang/String;Lorg/oppia/android/app/spotlight/SpotlightShape;Lorg/oppia/android/app/model/Spotlight$FeatureCase;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
FN:66,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorCentreX ()F
FN:70,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorCentreY ()F
FN:58,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorHeight ()I
FN:44,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorLeft ()F
FN:51,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorTop ()F
FN:62,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorWidth ()I
FN:15,org/oppia/android/app/spotlight/SpotlightTarget::getAnchor ()Landroid/view/View;
FN:30,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorCentreX ()F
FN:32,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorCentreY ()F
FN:26,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorHeight ()I
FN:22,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorLeft ()F
FN:24,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorTop ()F
FN:28,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorWidth ()I
FN:18,org/oppia/android/app/spotlight/SpotlightTarget::getFeature ()Lorg/oppia/android/app/model/Spotlight$FeatureCase;
FN:16,org/oppia/android/app/spotlight/SpotlightTarget::getHint ()Ljava/lang/String;
FN:17,org/oppia/android/app/spotlight/SpotlightTarget::getShape ()Lorg/oppia/android/app/spotlight/SpotlightShape;
FNDA:1,org/oppia/android/app/spotlight/SpotlightTarget::<init> (Landroid/view/View;Ljava/lang/String;Lorg/oppia/android/app/spotlight/SpotlightShape;Lorg/oppia/android/app/model/Spotlight$FeatureCase;)V
FNDA:0,org/oppia/android/app/spotlight/SpotlightTarget::<init> (Landroid/view/View;Ljava/lang/String;Lorg/oppia/android/app/spotlight/SpotlightShape;Lorg/oppia/android/app/model/Spotlight$FeatureCase;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
FNDA:1,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorCentreX ()F
FNDA:1,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorCentreY ()F
FNDA:1,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorHeight ()I
FNDA:1,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorLeft ()F
FNDA:1,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorTop ()F
FNDA:1,org/oppia/android/app/spotlight/SpotlightTarget::calculateAnchorWidth ()I
FNDA:1,org/oppia/android/app/spotlight/SpotlightTarget::getAnchor ()Landroid/view/View;
FNDA:1,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorCentreX ()F
FNDA:1,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorCentreY ()F
FNDA:1,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorHeight ()I
FNDA:1,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorLeft ()F
FNDA:1,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorTop ()F
FNDA:1,org/oppia/android/app/spotlight/SpotlightTarget::getAnchorWidth ()I
FNDA:1,org/oppia/android/app/spotlight/SpotlightTarget::getFeature ()Lorg/oppia/android/app/model/Spotlight$FeatureCase;
FNDA:1,org/oppia/android/app/spotlight/SpotlightTarget::getHint ()Ljava/lang/String;
FNDA:1,org/oppia/android/app/spotlight/SpotlightTarget::getShape ()Lorg/oppia/android/app/spotlight/SpotlightShape;
FNF:18
FNH:17
DA:14,1
DA:15,1
DA:16,1
DA:17,1
DA:18,1
DA:22,1
DA:24,1
DA:26,1
DA:28,1
DA:30,1
DA:32,1
DA:34,1
DA:35,1
DA:36,1
DA:37,1
DA:38,1
DA:39,1
DA:40,1
DA:41,1
DA:44,1
DA:45,1
DA:46,1
DA:47,1
DA:51,1
DA:52,1
DA:53,1
DA:54,1
DA:58,1
DA:62,1
DA:66,1
DA:70,1
DA:72,0
LH:31
LF:32
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/ActivityLanguageLocaleHandler.kt
FN:30,org/oppia/android/app/translation/ActivityLanguageLocaleHandler$displayLocale$2::invoke ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FN:18,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::<init> (Lorg/oppia/android/domain/locale/LocaleController;Lorg/oppia/android/app/translation/AppLanguageLocaleHandler;)V
FN:29,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::getDisplayLocale ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FN:41,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::initializeLocaleForActivity (Landroid/content/res/Configuration;)V
FN:51,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::updateLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)Z
FNDA:1,org/oppia/android/app/translation/ActivityLanguageLocaleHandler$displayLocale$2::invoke ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FNDA:1,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::<init> (Lorg/oppia/android/domain/locale/LocaleController;Lorg/oppia/android/app/translation/AppLanguageLocaleHandler;)V
FNDA:1,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::getDisplayLocale ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FNDA:1,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::initializeLocaleForActivity (Landroid/content/res/Configuration;)V
FNDA:1,org/oppia/android/app/translation/ActivityLanguageLocaleHandler::updateLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)Z
FNF:5
FNH:5
BRDA:53,0,0,1
BRDA:53,0,1,1
BRF:2
BRH:2
DA:18,1
DA:19,1
DA:20,1
DA:21,1
DA:29,1
DA:30,1
DA:41,1
DA:42,1
DA:51,1
DA:52,1
DA:53,1
LH:11
LF:11
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/ActivityRecreator.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/ActivityRecreatorImpl.kt
FN:7,org/oppia/android/app/translation/ActivityRecreatorImpl::<init> ()V
FN:9,org/oppia/android/app/translation/ActivityRecreatorImpl::recreate (Landroidx/appcompat/app/AppCompatActivity;)V
FNDA:0,org/oppia/android/app/translation/ActivityRecreatorImpl::<init> ()V
FNDA:0,org/oppia/android/app/translation/ActivityRecreatorImpl::recreate (Landroidx/appcompat/app/AppCompatActivity;)V
FNF:2
FNH:0
DA:7,0
DA:9,0
DA:10,0
LH:0
LF:3
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/ActivityRecreatorProdModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageActivityInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageActivityInjectorProvider.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageApplicationInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageApplicationInjectorProvider.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageLocaleHandler.kt
FN:20,org/oppia/android/app/translation/AppLanguageLocaleHandler::<init> (Lorg/oppia/android/domain/locale/LocaleController;)V
FN:76,org/oppia/android/app/translation/AppLanguageLocaleHandler::getDisplayLocale ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FN:41,org/oppia/android/app/translation/AppLanguageLocaleHandler::initializeLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)V
FN:56,org/oppia/android/app/translation/AppLanguageLocaleHandler::initializeLocaleForActivity (Landroid/content/res/Configuration;)V
FN:32,org/oppia/android/app/translation/AppLanguageLocaleHandler::isInitialized ()Z
FN:67,org/oppia/android/app/translation/AppLanguageLocaleHandler::updateLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)Z
FN:81,org/oppia/android/app/translation/AppLanguageLocaleHandler::verifyDisplayLocaleIsInitialized ()V
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::<init> (Lorg/oppia/android/domain/locale/LocaleController;)V
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::getDisplayLocale ()Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::initializeLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)V
FNDA:0,org/oppia/android/app/translation/AppLanguageLocaleHandler::initializeLocaleForActivity (Landroid/content/res/Configuration;)V
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::isInitialized ()Z
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::updateLocale (Lorg/oppia/android/util/locale/OppiaLocale$DisplayLocale;)Z
FNDA:1,org/oppia/android/app/translation/AppLanguageLocaleHandler::verifyDisplayLocaleIsInitialized ()V
FNF:7
FNH:6
BRDA:32,0,0,1
BRDA:32,0,1,1
BRDA:41,0,0,1
BRDA:41,0,1,0
BRDA:41,0,2,0
BRDA:41,0,3,1
BRDA:57,0,0,-
BRDA:57,0,1,-
BRDA:68,0,0,1
BRDA:68,0,1,0
BRDA:70,0,0,1
BRDA:70,0,1,1
BRDA:77,0,0,1
BRDA:77,0,1,0
BRDA:81,0,0,0
BRDA:81,0,1,1
BRF:16
BRH:9
DA:20,1
DA:21,1
DA:22,1
DA:32,1
DA:41,1
DA:42,0
DA:45,1
DA:46,1
DA:56,0
DA:57,0
DA:58,0
DA:67,1
DA:68,1
DA:69,1
DA:70,1
DA:76,1
DA:77,1
DA:81,1
DA:82,0
DA:85,1
LH:15
LF:20
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/AppLanguageWatcherMixin.kt
FN:80,org/oppia/android/app/translation/AppLanguageWatcherMixin$initialize$1::<init> (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;Landroidx/lifecycle/LiveData;)V
FN:82,org/oppia/android/app/translation/AppLanguageWatcherMixin$initialize$1::onChanged (Lorg/oppia/android/util/data/AsyncResult;)V
FN:20,org/oppia/android/app/translation/AppLanguageWatcherMixin::<init> (Landroidx/appcompat/app/AppCompatActivity;Lorg/oppia/android/domain/translation/TranslationController;Lorg/oppia/android/app/translation/AppLanguageLocaleHandler;Lorg/oppia/android/domain/locale/LocaleController;Lorg/oppia/android/domain/oppialogger/OppiaLogger;Lorg/oppia/android/app/translation/ActivityRecreator;Lorg/oppia/android/domain/profile/ProfileManagementController;Lorg/oppia/android/app/translation/ActivityLanguageLocaleHandler;)V
FN:43,org/oppia/android/app/translation/AppLanguageWatcherMixin::initialize (Z)V
FNDA:1,org/oppia/android/app/translation/AppLanguageWatcherMixin$initialize$1::<init> (Lorg/oppia/android/app/translation/AppLanguageWatcherMixin;Landroidx/lifecycle/LiveData;)V
FNDA:1,org/oppia/android/app/translation/AppLanguageWatcherMixin$initialize$1::onChanged (Lorg/oppia/android/util/data/AsyncResult;)V
FNDA:1,org/oppia/android/app/translation/AppLanguageWatcherMixin::<init> (Landroidx/appcompat/app/AppCompatActivity;Lorg/oppia/android/domain/translation/TranslationController;Lorg/oppia/android/app/translation/AppLanguageLocaleHandler;Lorg/oppia/android/domain/locale/LocaleController;Lorg/oppia/android/domain/oppialogger/OppiaLogger;Lorg/oppia/android/app/translation/ActivityRecreator;Lorg/oppia/android/domain/profile/ProfileManagementController;Lorg/oppia/android/app/translation/ActivityLanguageLocaleHandler;)V
FNDA:1,org/oppia/android/app/translation/AppLanguageWatcherMixin::initialize (Z)V
FNF:4
FNH:4
BRDA:43,0,0,1
BRDA:43,0,1,1
BRDA:72,0,0,0
BRDA:72,0,1,1
BRDA:73,0,0,1
BRDA:73,0,1,0
BRDA:83,0,0,1
BRDA:83,0,1,0
BRDA:86,0,0,1
BRDA:86,0,1,1
BRDA:103,0,0,-
BRDA:103,0,1,-
BRDA:109,0,0,-
BRDA:109,0,1,-
BRF:14
BRH:7
DA:20,1
DA:21,1
DA:22,1
DA:23,1
DA:24,1
DA:25,1
DA:26,1
DA:27,1
DA:28,1
DA:43,1
DA:60,1
DA:61,1
DA:63,1
DA:64,1
DA:66,1
DA:69,1
DA:71,1
DA:72,1
DA:73,1
DA:74,0
DA:77,1
DA:78,1
DA:79,1
DA:80,1
DA:82,1
DA:83,1
DA:86,1
DA:99,1
DA:100,1
DA:103,0
DA:104,0
DA:105,0
DA:106,0
DA:109,0
DA:111,1
DA:114,1
LH:30
LF:36
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/testing/ActivityRecreatorTestModule.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/translation/testing/TestActivityRecreator.kt
FN:18,org/oppia/android/app/translation/testing/TestActivityRecreator::<init> ()V
FN:28,org/oppia/android/app/translation/testing/TestActivityRecreator::getRecreateCount ()I
FN:24,org/oppia/android/app/translation/testing/TestActivityRecreator::recreate (Landroidx/appcompat/app/AppCompatActivity;)V
FNDA:1,org/oppia/android/app/translation/testing/TestActivityRecreator::<init> ()V
FNDA:0,org/oppia/android/app/translation/testing/TestActivityRecreator::getRecreateCount ()I
FNDA:1,org/oppia/android/app/translation/testing/TestActivityRecreator::recreate (Landroidx/appcompat/app/AppCompatActivity;)V
FNF:3
FNH:2
DA:18,1
DA:19,1
DA:24,1
DA:25,1
DA:28,0
LH:4
LF:5
end_of_record
SF:app/src/main/java/org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory.kt
FN:36,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$createTimer$1::invokeSuspend (Ljava/lang/Object;)Ljava/lang/Object;
FN:80,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runPeriodically$1::invoke ()V
FN:53,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runWithDelay$1::<init> (Landroidx/lifecycle/LiveData;Lkotlin/jvm/functions/Function0;)V
FN:55,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runWithDelay$1::onChanged (Ljava/lang/Object;)V
FN:19,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::<init> (Lkotlinx/coroutines/CoroutineDispatcher;)V
FN:34,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::createTimer (J)Landroidx/lifecycle/LiveData;
FN:79,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runPeriodically (Landroidx/lifecycle/LifecycleOwner;JJLkotlin/jvm/functions/Function0;)V
FN:74,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runPeriodically$default (Lorg/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory;Landroidx/lifecycle/LifecycleOwner;JJLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
FN:50,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runWithDelay (Landroidx/lifecycle/LifecycleOwner;JLkotlin/jvm/functions/Function0;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$createTimer$1::invokeSuspend (Ljava/lang/Object;)Ljava/lang/Object;
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runPeriodically$1::invoke ()V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runWithDelay$1::<init> (Landroidx/lifecycle/LiveData;Lkotlin/jvm/functions/Function0;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory$runWithDelay$1::onChanged (Ljava/lang/Object;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::<init> (Lkotlinx/coroutines/CoroutineDispatcher;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::createTimer (J)Landroidx/lifecycle/LiveData;
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runPeriodically (Landroidx/lifecycle/LifecycleOwner;JJLkotlin/jvm/functions/Function0;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runPeriodically$default (Lorg/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory;Landroidx/lifecycle/LifecycleOwner;JJLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
FNDA:0,org/oppia/android/app/utility/lifecycle/LifecycleSafeTimerFactory::runWithDelay (Landroidx/lifecycle/LifecycleOwner;JLkotlin/jvm/functions/Function0;)V
FNF:9
FNH:0
DA:19,0
DA:20,0
DA:24,0
DA:34,0
DA:35,0
DA:36,0
DA:37,0
DA:38,0
DA:39,0
DA:50,0
DA:51,0
DA:52,0
DA:53,0
DA:55,0
DA:56,0
DA:57,0
DA:60,0
DA:74,0
DA:75,0
DA:79,0
DA:80,0
DA:81,0
DA:83,0
DA:84,0
LH:0
LF:24
end_of_record
SF:app/src/main/java/org/oppia/android/app/view/ViewComponent.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/view/ViewComponentBuilderInjector.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/view/ViewComponentFactory.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/view/ViewScope.kt
FNF:0
FNH:0
LH:0
LF:0
end_of_record
SF:app/src/main/java/org/oppia/android/app/viewmodel/ObservableArrayList.kt
FN:7,org/oppia/android/app/viewmodel/ObservableArrayList::<init> ()V
FN:17,org/oppia/android/app/viewmodel/ObservableArrayList::add (ILjava/lang/Object;)V
FN:11,org/oppia/android/app/viewmodel/ObservableArrayList::add (Ljava/lang/Object;)Z
FN:31,org/oppia/android/app/viewmodel/ObservableArrayList::addAll (ILjava/util/Collection;)Z
FN:22,org/oppia/android/app/viewmodel/ObservableArrayList::addAll (Ljava/util/Collection;)Z
FN:69,org/oppia/android/app/viewmodel/ObservableArrayList::addOnListChangedCallback (Landroidx/databinding/ObservableList$OnListChangedCallback;)V
FN:48,org/oppia/android/app/viewmodel/ObservableArrayList::clear ()V
FN:8,org/oppia/android/app/viewmodel/ObservableArrayList::getListeners ()Landroidx/databinding/ListChangeRegistry;
FN:79,org/oppia/android/app/viewmodel/ObservableArrayList::notifyAdd (II)V
FN:83,org/oppia/android/app/viewmodel/ObservableArrayList::notifyRemove (II)V
FN:39,org/oppia/android/app/viewmodel/ObservableArrayList::removeAll (Ljava/util/Collection;)Z
FN:75,org/oppia/android/app/viewmodel/ObservableArrayList::removeOnListChangedCallback (Landroidx/databinding/ObservableList$OnListChangedCallback;)V
FN:62,org/oppia/android/app/viewmodel/ObservableArrayList::removeRange (II)V
FN:56,org/oppia/android/app/viewmodel/ObservableArrayList::set (ILjava/lang/Object;)Ljava/lang/Object;
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::<init> ()V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::add (ILjava/lang/Object;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::add (Ljava/lang/Object;)Z
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::addAll (ILjava/util/Collection;)Z
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::addAll (Ljava/util/Collection;)Z
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::addOnListChangedCallback (Landroidx/databinding/ObservableList$OnListChangedCallback;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::clear ()V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::getListeners ()Landroidx/databinding/ListChangeRegistry;
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::notifyAdd (II)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::notifyRemove (II)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::removeAll (Ljava/util/Collection;)Z
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::removeOnListChangedCallback (Landroidx/databinding/ObservableList$OnListChangedCallback;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::removeRange (II)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableArrayList::set (ILjava/lang/Object;)Ljava/lang/Object;
FNF:14
FNH:0
DA:7,0
DA:8,0
DA:11,0
DA:12,0
DA:13,0
DA:17,0
DA:18,0
DA:19,0
DA:22,0
DA:23,0
DA:24,0
DA:25,0
DA:27,0
DA:31,0
DA:32,0
DA:33,0
DA:35,0
DA:39,0
DA:40,0
DA:41,0
DA:42,0
DA:44,0
DA:48,0
DA:49,0
DA:50,0
DA:51,0
DA:53,0
DA:56,0
DA:57,0
DA:58,0
DA:62,0
DA:63,0
DA:64,0
DA:69,0
DA:70,0
DA:75,0
DA:76,0
DA:79,0
DA:80,0
DA:83,0
DA:84,0
LH:0
LF:41
end_of_record
SF:app/src/main/java/org/oppia/android/app/viewmodel/ObservableViewModel.kt
FN:9,org/oppia/android/app/viewmodel/ObservableViewModel$callbacks$2::invoke ()Landroidx/databinding/PropertyChangeRegistry;
FN:7,org/oppia/android/app/viewmodel/ObservableViewModel::<init> ()V
FN:17,org/oppia/android/app/viewmodel/ObservableViewModel::addOnPropertyChangedCallback (Landroidx/databinding/Observable$OnPropertyChangedCallback;)V
FN:8,org/oppia/android/app/viewmodel/ObservableViewModel::getCallbacks ()Landroidx/databinding/PropertyChangeRegistry;
FN:22,org/oppia/android/app/viewmodel/ObservableViewModel::notifyChange ()V
FN:27,org/oppia/android/app/viewmodel/ObservableViewModel::notifyPropertyChanged (I)V
FN:13,org/oppia/android/app/viewmodel/ObservableViewModel::removeOnPropertyChangedCallback (Landroidx/databinding/Observable$OnPropertyChangedCallback;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel$callbacks$2::invoke ()Landroidx/databinding/PropertyChangeRegistry;
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::<init> ()V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::addOnPropertyChangedCallback (Landroidx/databinding/Observable$OnPropertyChangedCallback;)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::getCallbacks ()Landroidx/databinding/PropertyChangeRegistry;
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::notifyChange ()V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::notifyPropertyChanged (I)V
FNDA:0,org/oppia/android/app/viewmodel/ObservableViewModel::removeOnPropertyChangedCallback (Landroidx/databinding/Observable$OnPropertyChangedCallback;)V
FNF:7
FNH:0
DA:7,0
DA:8,0
DA:9,0
DA:13,0
DA:14,0
DA:17,0
DA:18,0
DA:22,0
DA:23,0
DA:27,0
DA:28,0
LH:0
LF:11
end_of_record

Also, with this case would it mean (at least considering the app modules), the coverage reports being included / passing would be related to having package specific source targets? (since the spotlight test modules didn't have an explicit one)

BenHenning pushed a commit that referenced this issue Jul 29, 2024
…concurrency (#5466)

<!-- READ ME FIRST: Please fill in the explanation section below and
check off every point from the Essential Checklist! -->
## Explanation
<!--
- Explain what your PR does. If this PR fixes an existing bug, please
include
- "Fixes #bugnum:" in the explanation so that GitHub can auto-close the
issue
  - when this PR is merged.
  -->

Fix #2711 
Fixes part of #5343 

### Project
[PR 2.5 of Project 4.1]

### Changes Made
- The existing workflow canceller utilized the
[cancel-workflow-action](https://github.com/styfle/cancel-workflow-action)
by syfle.
- Since GitHub introduced native
[concurrency](https://docs.github.com/en/actions/using-jobs/using-concurrency)
support on April 19, 2021, we can now utilize this built-in feature for
better integration.
- This implementation leverages the [concurrency
property](https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-concurrency-and-the-default-behavior)
to manage workflows, using the configuration:
```
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
```
- This setup groups workflows by their name and reference, allowing
GitHub to automatically cancel any in-progress jobs in the workflow when
a new workflow run is triggered.
- This retires the existing Automatic workflow canceller
(workflow_canceller.yml).
- This approach is now in place for the following workflows: 
  - Build Tests 
  - Static Checks 
  - Unit Tests (Robolectric - Gradle)
  - Unit Tests (Robolectric - Bazel)

### Triggered Cancellation
(PR Check Triggers) ->
https://github.com/oppia/oppia-android/pull/5466/checks

### Screenshots of workflow cancelled
**Workflows Running:**

![Screenshot
(1536)](https://github.com/user-attachments/assets/fa11a887-0bee-4d6c-8c58-fa2e723bde91)

**Workflows in previous run cancelling after latest commit**

![Screenshot
(1538)](https://github.com/user-attachments/assets/14d96ff7-38c6-4054-a084-7712c34b9c29)

**Note:** It is observed that the Non-App Module runs take a bit of time
to cancel but they eventually get cancelled.


![image](https://github.com/user-attachments/assets/516628ee-15a0-4a95-926c-ea925357bae2)


![image](https://github.com/user-attachments/assets/03a74685-c458-44a8-ada9-09faf45eeb93)

## Essential Checklist
<!-- Please tick the relevant boxes by putting an "x" in them. -->
- [x] The PR title and explanation each start with "Fix #bugnum: " (If
this PR fixes part of an issue, prefix the title with "Fix part of
#bugnum: ...".)
- [x] Any changes to
[scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets)
files have their rationale included in the PR explanation.
- [x] The PR follows the [style
guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide).
- [x] The PR does not contain any unnecessary code changes from Android
Studio
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)).
- [x] The PR is made from a branch that's **not** called "develop" and
is up-to-date with "develop".
- [x] The PR is **assigned** to the appropriate reviewers
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)).
BenHenning pushed a commit that referenced this issue Aug 7, 2024
… target files (#5459)

<!-- READ ME FIRST: Please fill in the explanation section below and
check off every point from the Essential Checklist! -->
## Explanation
<!--
- Explain what your PR does. If this PR fixes an existing bug, please
include
- "Fixes #bugnum:" in the explanation so that GitHub can auto-close the
issue
  - when this PR is merged.
  -->

Fixes part of #5343 

### Project
[PR 2.1 of Project 4.1]

### Changes Made
- Enabling code coverage analysis for many-to-one relationship test
target files by aggregating the coverage reports of each related test
target into a single report using the
`calculateAggregateCoverageReport()` function.
- Using the calculated aggregated coverage report to generate Markdown
and HTML files.
- Properly re-implemented the asynchronous flow as previous
implementation though has async calls was still handling it sequentially
as targets are provided one by one and made to wait until the coverage
report is generated and the previous one is returned back.

**Working test asynchronous flow screenshot**
With static test targets provided:
2ac7b04


![image](https://github.com/oppia/oppia-android/assets/122200035/295cfd9d-7c3a-4784-ba51-a1e8241dccbd)

**Low impact changes:**

Not related to the current PR implementation but added few fixes along
with it,
- Restyled the HTML report slightly since the previous version appeared
somewhat vague and empty 😶‍🌫️.
- Renamed sample test name from `TwoSum` to `AddNums`, felt more
appropriate and clear.

### Note
I couldn't find any actual working app module file with both shared and
local tests to fully test this. Instead, I mocked the behavior with a
sample coverage report and tested it with test cases, assuming that both
tests for the same source file would have identical **line_number**,
**lines_hit**, and **lines_found** data.

___

### Screenshot of current HTML report
![Screenshot
(1460)](https://github.com/oppia/oppia-android/assets/122200035/922a6228-1685-4463-8d64-6d162d5d1e59)

**Responsive layouts**
![zero contributions
(48)](https://github.com/oppia/oppia-android/assets/122200035/626e08eb-eeec-446b-b54c-46dd6aa5eaf8)

## Essential Checklist
<!-- Please tick the relevant boxes by putting an "x" in them. -->
- [x] The PR title and explanation each start with "Fix #bugnum: " (If
this PR fixes part of an issue, prefix the title with "Fix part of
#bugnum: ...".)
- [x] Any changes to
[scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets)
files have their rationale included in the PR explanation.
- [x] The PR follows the [style
guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide).
- [x] The PR does not contain any unnecessary code changes from Android
Studio
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)).
- [x] The PR is made from a branch that's **not** called "develop" and
is up-to-date with "develop".
- [x] The PR is **assigned** to the appropriate reviewers
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)).

## For UI-specific PRs only
<!-- Delete these section if this PR does not include UI-related
changes. -->
If your PR includes UI-related changes, then:
- Add screenshots for portrait/landscape for both a tablet & phone of
the before & after UI changes
- For the screenshots above, include both English and pseudo-localized
(RTL) screenshots (see [RTL
guide](https://github.com/oppia/oppia-android/wiki/RTL-Guidelines))
- Add a video showing the full UX flow with a screen reader enabled (see
[accessibility
guide](https://github.com/oppia/oppia-android/wiki/Accessibility-A11y-Guide))
- For PRs introducing new UI elements or color changes, both light and
dark mode screenshots must be included
- Add a screenshot demonstrating that you ran affected Espresso tests
locally & that they're passing
@Rd4dev
Copy link
Collaborator

Rd4dev commented Aug 8, 2024

@BenHenning another finding that might be helpful

Just tried running coverage on the non-modularized test: BundleExtensionsTest

bazel coverage //utility:src/test/java/org/oppia/android/util/extensions/BundleExtensionsTest

Note: The source file is modularized while the test is not

Running the bazel coverage command did pass the coverage analysis:

image

And also it has its SourceFile included in the coverage report:

...

SF:utility/src/main/java/org/oppia/android/util/extensions/BundleExtensions.kt
FN:37,org/oppia/android/util/extensions/BundleExtensionsKt::getProto (Landroid/os/Bundle;Ljava/lang/String;Lcom/google/protobuf/MessageLite;)Lcom/google/protobuf/MessageLite;
FN:66,org/oppia/android/util/extensions/BundleExtensionsKt::getProtoExtra (Landroid/content/Intent;Ljava/lang/String;Lcom/google/protobuf/MessageLite;)Lcom/google/protobuf/MessageLite;
FN:84,org/oppia/android/util/extensions/BundleExtensionsKt::getSerializableAboveApi32 (Landroid/os/Bundle;Ljava/lang/String;Ljava/lang/Class;)Ljava/io/Serializable;
FN:73,org/oppia/android/util/extensions/BundleExtensionsKt::getStringFromBundle (Landroid/os/Bundle;Ljava/lang/String;)Ljava/lang/String;
FN:18,org/oppia/android/util/extensions/BundleExtensionsKt::putProto (Landroid/os/Bundle;Ljava/lang/String;Lcom/google/protobuf/MessageLite;)V
FN:57,org/oppia/android/util/extensions/BundleExtensionsKt::putProtoExtra (Landroid/content/Intent;Ljava/lang/String;Lcom/google/protobuf/MessageLite;)V
FNDA:1,org/oppia/android/util/extensions/BundleExtensionsKt::getProto (Landroid/os/Bundle;Ljava/lang/String;Lcom/google/protobuf/MessageLite;)Lcom/google/protobuf/MessageLite;
FNDA:1,org/oppia/android/util/extensions/BundleExtensionsKt::getProtoExtra (Landroid/content/Intent;Ljava/lang/String;Lcom/google/protobuf/MessageLite;)Lcom/google/protobuf/MessageLite;
FNDA:0,org/oppia/android/util/extensions/BundleExtensionsKt::getSerializableAboveApi32 (Landroid/os/Bundle;Ljava/lang/String;Ljava/lang/Class;)Ljava/io/Serializable;
FNDA:0,org/oppia/android/util/extensions/BundleExtensionsKt::getStringFromBundle (Landroid/os/Bundle;Ljava/lang/String;)Ljava/lang/String;
FNDA:1,org/oppia/android/util/extensions/BundleExtensionsKt::putProto (Landroid/os/Bundle;Ljava/lang/String;Lcom/google/protobuf/MessageLite;)V
FNDA:1,org/oppia/android/util/extensions/BundleExtensionsKt::putProtoExtra (Landroid/content/Intent;Ljava/lang/String;Lcom/google/protobuf/MessageLite;)V
FNF:6
FNH:4
BRDA:37,0,0,1
BRDA:37,0,1,1
BRDA:37,0,2,1
BRDA:37,0,3,1
BRDA:57,0,0,1
BRDA:57,0,1,1
BRDA:66,0,0,1
BRDA:66,0,1,1
BRDA:66,0,2,1
BRDA:66,0,3,0
BRF:10
BRH:9
DA:18,1
DA:19,1
DA:37,1
DA:40,1
DA:42,1
DA:43,1
DA:44,1
DA:46,1
DA:57,1
DA:58,1
DA:66,1
DA:73,0
DA:84,0
LH:11
LF:13
end_of_record

Todo:
(will try later) -> Tried running

bazel coverage //domain:src/test/java/org/oppia/android/domain/util/StringExtensionsTest

whose source is specified in the same build file as of BundleExtensions

BUILD.bazel
kt_android_library(
    name = "bundle_extensions",
    srcs = [
        "BundleExtensions.kt",
    ],
    visibility = ["//:oppia_api_visibility"],
    deps = [
        "//third_party:com_google_protobuf_protobuf-javalite",
    ],
)

kt_android_library(
    name = "context_extensions",
    srcs = [
        "ContextExtensions.kt",
    ],
    visibility = ["//:oppia_api_visibility"],
    deps = [
        "//third_party:com_google_protobuf_protobuf-javalite",
    ],
)

kt_android_library(
    name = "string_extensions",
    srcs = [
        "StringExtensions.kt",
    ],
    visibility = ["//:oppia_api_visibility"],
)

The coverage run failed.

but test file seems to be in an improper place (might be that could be a troublemaker), will later try to move it to its respective package and again try analysing it.

BenHenning added a commit that referenced this issue Aug 10, 2024
)

## Explanation
Fixes part of #5343

This PR prepares for enabling code coverage support in CI by:
- Introducing a new source file test exemption property: incompatibility
with code coverage (see below for more insight into why this is needed).
- Updating the existing test file exemption textproto to include all of
the current source files whose corresponding tests do not run correctly
with the recently introduced code coverage tooling.
- Adding several test declarations that were missed in previous PRs
(future Bazel work may include a script that checks for test file
declarations to try and reduce the likelihood of this happening in the
future).

At a high-level, there are several reasons why a test may fail to run in
coverage:
- It isn't modularized (this fails for reasons not yet fully
understood--see investigation findings in #5343), though some
unmodularized tests do seem to pass (looking at you,
``SpotlightFragmentTest``).
- Its source file is either missing from offline instrumentation, or it
simply fails to be resolved. This either results in a runtime failure
during the test, or the source file being missing from its coverage.dat
file.
- Other JaCoCo runtime issues that may imply an incorrect
instrumentation filter due to attempting to reinstrument an already
instrumented dependency class. A multi-hour search for related problems
and an analysis of code coverage support in both Bazel and rules_kotlin
did not yield any additional insight into why this situation can happen.
- Test files that are incorrectly named or in the wrong location (this
PR doesn't make an effort to move these).
- And yet other unknown failures that result in instrumentation failure
or a failure to generate a coverage.dat file.

There are probably many investigations needed to fix all of these
problems, so it makes sense to at least denylist all tests that that are
for sure known to fail. This at least sets up the team to get some value
from CI-run code coverage, though hard enforcement probably can't be
enabled until these stability problems are addressed.

Note that a custom script was written for the purpose of actually
performing this analysis, and that can be seen here:

```kotlin
package org.oppia.android.scripts.coverage

import com.google.protobuf.TextFormat
import org.oppia.android.scripts.common.CommandExecutor
import org.oppia.android.scripts.common.CommandExecutorImpl
import org.oppia.android.scripts.common.RepositoryFile
import org.oppia.android.scripts.common.ScriptBackgroundCoroutineDispatcher
import org.oppia.android.scripts.proto.TestFileExemptions
import java.io.File
import java.io.FileInputStream
import java.util.concurrent.TimeUnit

fun main(vararg args: String) {
  val repoRoot = File(args[0]).absoluteFile.normalize()
  // Skip non-Kotlin files, tests, this file, and already exempted files.
  val testFileExemptionList = loadTestFileExemptionsProto()
    .testFileExemptionList
    .filter { it.testFileNotRequired || it.sourceFileIsIncompatibleWithCodeCoverage }
    .mapTo(mutableSetOf()) { it.exemptedFilePath }
  val sourceFiles = RepositoryFile.collectSearchFiles(repoPath = repoRoot.path, expectedExtension = ".kt").filterNot { it.nameWithoutExtension.endsWith("Test") }.filterNot { it.nameWithoutExtension == "RunCoverageForAll" }.distinct()
  val nonExemptedSourceFiles = sourceFiles.filter { it.toRelativeString(repoRoot) !in testFileExemptionList }.sorted()
  println("Found ${sourceFiles.size} source files on which to run tests, but only ${nonExemptedSourceFiles.size} need to be checked (the others should be exempted).")
  val startTime = System.currentTimeMillis()
  val coverageResults = ScriptBackgroundCoroutineDispatcher().use { scriptBgDispatcher ->
    val commandExecutor = CommandExecutorImpl(scriptBgDispatcher, processTimeout = 10, processTimeoutUnit = TimeUnit.MINUTES)
    nonExemptedSourceFiles.withIndex().associate { (index, sourceFile) ->
      val sourcePath = sourceFile.toRelativeString(repoRoot)
      val timeSpentMs = (System.currentTimeMillis() - startTime).toFloat()
      val averageTimeMs = timeSpentMs / index.toFloat()
      val estRemainingTimeMs = averageTimeMs * (nonExemptedSourceFiles.size - index)
      if (index > 0) {
        print("- $sourcePath (${index + 1}/${nonExemptedSourceFiles.size})...~${estRemainingTimeMs / 60000.0f}m left")
      } else print("- $sourcePath (${index + 1}/${nonExemptedSourceFiles.size})...")
      sourcePath to commandExecutor.runCoverageForSourceFile(repoRoot, sourceFile).also { result ->
        println("\r- $sourcePath (${index + 1}/${nonExemptedSourceFiles.size}) -> ${result.summary}")
      }
    }
  }
  println()

  println("Found coverage results for ${coverageResults.size} files. High-level results:")
  val exemptions = coverageResults.values.filter { it == RunCoverageResult.Exempted }
  val failures = coverageResults.filter { (_, result) -> result.isFailure }
  val successes = coverageResults.values.filterIsInstance<RunCoverageResult.RanWithCoverage>()
  val averageCoverageRatio = successes.map { it.ratio }.average()
  println("- ${exemptions.size} source files had additional exemptions for code coverage.")
  println("- ${failures.size} source files failed to compute coverage. By category:")
  failures.values.groupBy { it.summary }.forEach { (summary, failuresGroup) ->
    println("  - ${summary.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }}: ${failuresGroup.size}/${failures.size} failures.")
  }
  println("- Average coverage precentage is (for ${successes.size}/${coverageResults.size} passing tests): ${(averageCoverageRatio * 100.0).toFloat()}%.")
  println()

  println("Recomputed test file exemptions textproto:")
  println()
  println()
  val newExemptions = failures.map { (sourcePath, _) ->
    TestFileExemptions.TestFileExemption.newBuilder().apply {
      this.exemptedFilePath = sourcePath
      this.sourceFileIsIncompatibleWithCodeCoverage = true
    }.build()
  }
  val oldExemptionsProto = loadTestFileExemptionsProto()
  val allExemptions = (oldExemptionsProto.testFileExemptionList + newExemptions).sortedBy { it.exemptedFilePath }
  val updatedExemptionsProto = oldExemptionsProto.toBuilder().apply {
    clearTestFileExemption()
    addAllTestFileExemption(allExemptions)
  }.build()
  TextFormat.printer().print(updatedExemptionsProto, System.out)
  println()
}

private fun CommandExecutor.runCoverageForSourceFile(repoRoot: File, sourceFile: File): RunCoverageResult {
  val result = executeCommand(repoRoot, "bazel", "run", "//scripts:run_coverage", repoRoot.path, sourceFile.toRelativeString(repoRoot), "format=MARKDOWN")
  val outputLines = result.output
  return when {
    result.exitCode == 1 && outputLines.any { "Coverage data not found for the file" in it } -> RunCoverageResult.CoverageNotGenerated
    result.exitCode == 1 && outputLines.any { "No appropriate test file found" in it } -> RunCoverageResult.MissingTestFile
    result.exitCode == 1 && outputLines.any { "Cannot process instrumented class" in it } -> RunCoverageResult.FailsToInstrument
    result.exitCode == 1 && outputLines.any { "tried to access private method" in it } -> RunCoverageResult.CannotAccessJacocoInit
    result.exitCode == 0 && outputLines.any { it.startsWith("This file is exempted from having a test file") } -> RunCoverageResult.Exempted
    result.exitCode == 0 && outputLines.any { it.startsWith("Computed Coverage Ratio") } -> {
      val computedRatioLine = outputLines.single { it.startsWith("Computed Coverage Ratio") }
      val ratioStr = computedRatioLine.substringAfter(":").trim()
      RunCoverageResult.RanWithCoverage(ratioStr.toDouble())
    }
    else -> {
      println()
      println("Failed to run command (exit code ${result.exitCode}):")
      println("  ${result.command.joinToString(separator = " ")}")
      println()
      println("Output:")
      println("#".repeat(80))
      println()
      result.output.forEach(::println)
      println()
      println("#".repeat(80))
      println()
      error("Failed.")
    }
  }
}

private fun loadTestFileExemptionsProto(): TestFileExemptions {
  val protoBinaryFile = File("scripts/assets/test_file_exemptions.pb")
  val builder = TestFileExemptions.getDefaultInstance().newBuilderForType()

  // This cast is type-safe since proto guarantees type consistency from mergeFrom(),
  // and this method is bounded by the generic type T.
  @Suppress("UNCHECKED_CAST")
  val protoObj: TestFileExemptions =
    FileInputStream(protoBinaryFile).use {
      builder.mergeFrom(it)
    }.build() as TestFileExemptions
  return protoObj
}

private sealed class RunCoverageResult {
  abstract val isFailure: Boolean
  abstract val summary: String

  object Exempted : RunCoverageResult() {
    override val isFailure = false
    override val summary = "exempted"
  }

  // Seems to happen to some unmodularized tests.
  object CoverageNotGenerated : RunCoverageResult() {
    override val isFailure = true
    override val summary = "coverage.dat was not generated"
  }

  // Test files needs to be added, renamed, or moved.
  object MissingTestFile : RunCoverageResult() {
    override val isFailure = true
    override val summary = "missing test file"
  }

  // Seems to happen to some unmodularized tests.
  object FailsToInstrument : RunCoverageResult() {
    override val isFailure = true
    override val summary = "fails to instrument"
  }

  // Unclear what the root cause is for these cases; possibly an incorrect instrumentation_filter is
  // being used.
  object CannotAccessJacocoInit : RunCoverageResult() {
    override val isFailure = true
    override val summary = "cannot access private method jacocoInit in unnamed module"
  }

  data class RanWithCoverage(val ratio: Double) : RunCoverageResult() {
    override val isFailure = false
    override val summary: String get() = "coverage ran (${(ratio * 100.0).toFloat()}%)"
  }
}
```

With its corresponding library Bazel declaration:

```bazel
kt_jvm_library(
    name = "run_coverage_for_all_lib",
    testonly = True,
    srcs = [
        "RunCoverageForAll.kt",
    ],
    visibility = ["//scripts:oppia_script_binary_visibility"],
    deps = [
        "//scripts/src/java/org/oppia/android/scripts/common:bazel_client",
        "//scripts/src/java/org/oppia/android/scripts/common:repository_file",
        "//scripts/src/java/org/oppia/android/scripts/proto:script_exemptions_java_proto",
    ],
)
```

and its binary declaration:

```bazel
kt_jvm_binary(
    name = "run_coverage_for_all",
    testonly = True,
    data = TEST_FILE_EXEMPTION_ASSETS,
    main_class = "org.oppia.android.scripts.coverage.RunCoverageForAllKt",
    runtime_deps = ["//scripts/src/java/org/oppia/android/scripts/coverage:run_coverage_for_all_lib"],
)
```

This script was a significant help in simplifying the work to
determining the list of exempted files. It also seems stable: running it
with the latest exemption list correctly only runs valid tests.

The script also produced some high-level outputs which are interesting
to note:
- 1274 total source files exist for potential code coverage (excludes
non-Kotlin files, tests, and the ``RunCoverageForAll`` script itself).
- After omitting exemptions (i.e. those tests which the team has
exempted from requiring test files), 387 remaining source files were
expected to have 1 or more corresponding tests.
- Of those, 230 failed to have code coverage computed (and thus needed
to be exempted in this PR). Here's the failure category break-down:
- 115/230 failures occurred from coverage.dat missing after running
``bazel coverage``.
- 32/230 failures occurred from the test file not actually existing
where it was expected to be.
- 81/230 failures occurred from a failure to instrument one or more of
the classes needed for runtime.
- 2/230 failures occurred from a JaCoCo access issue (likely indicating
some significant build configuration issue somewhere in the toolchain).
- The average code coverage among the remaining 157 properly passing
source files was: 85.15078%. This isn't fully representative since ~60%
of source files couldn't be properly tested for coverage, but it's still
much higher than expected.

**Note to reviewers**: ``scripts/assets/test_file_exemptions.textproto``
was automatically generated using the script above, and it was sorted by
file path to make it a bit cleaner.

Finally, please note that ``DirectoryManagementUtilTest`` had one source
file change due to a compile-time build warning that wasn't caught
before (since the test wasn't being built in Bazel with Kotlin
warnings-as-errors enabled).

## Essential Checklist
- [x] The PR title and explanation each start with "Fix #bugnum: " (If
this PR fixes part of an issue, prefix the title with "Fix part of
#bugnum: ...".)
- [x] Any changes to
[scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets)
files have their rationale included in the PR explanation.
- [x] The PR follows the [style
guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide).
- [x] The PR does not contain any unnecessary code changes from Android
Studio
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)).
- [x] The PR is made from a branch that's **not** called "develop" and
is up-to-date with "develop".
- [x] The PR is **assigned** to the appropriate reviewers
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)).

## For UI-specific PRs only
N/A -- This is only affecting build and test infrastructure.
BenHenning pushed a commit that referenced this issue Aug 10, 2024
)

<!-- READ ME FIRST: Please fill in the explanation section below and
check off every point from the Essential Checklist! -->
## Explanation
<!--
- Explain what your PR does. If this PR fixes an existing bug, please
include
- "Fixes #bugnum:" in the explanation so that GitHub can auto-close the
issue
  - when this PR is merged.
  -->

Fixes part of #5343 

### Project
[PR 2.2 of Project 4.1]

### Changes Made
- **File Path List:** The implementation now enables doing coverage
analysis for a list of provided files (which used to be just a single
file). Coverage analysis runs sequentially for each file.

**Updated command:**
```
bazel run //scripts:run_coverage -- $(pwd) <path/to/file1.kt> <path/to/file2.kt> <path/to/file3.kt> --format=MARKDOWN --processTimeout=15
```

**Handled Edge cases:**
- **Non-kotlin Files:**
- Since when retrieving changed files list other non-kotlin files
(resource files - .xml, .txt, .md, .pb, .json, etc.) could be included,
this script will handle the analysis by only filtering in the required
kotlin files.
- The kotlin files which are test files are mapped to their appropriate
source files and then provided for coverage analysis.
- So the provided list of files: [utility/.../MathTokenizer.kt,
app/.../layout.xml, scripts/.../TestFileCheckTest.kt] will only do
coverage analysis for the files "utility/.../MathTokenizer.kt",
"scripts/.../TestFileCheck.kt".

- **Input variations:**
- Developers would be able to provide list of files in all below
variations
  - [file1.kt, file2.kt, file3.kt]
  - ["file1.kt", "file2.kt", "file3.kt"]
  - file1.kt file2.kt file3.kt
  - file1.kt, file2.kt, file3.kt

- **Input format:**
- Included the option to use the short form 'md' for the markdown format
(just to enhance user experience).
```
bazel run //scripts:run_coverage -- $(pwd) <path/to/file1.kt> <path/to/file2.kt> --format=md
```

- **Coverage Results Display:** Based on the discussions, it was decided
to display only the failure cases (i.e., below the minimum threshold).
However, I included success cases in a hidden dropdown. This allows
developers to see the coverage checks and percentages of other files,
enabling them to improve their test scenarios if needed. (yet to
discussed if that's ok)
- **Error Handling:** Error statements in the coverage flow have been
replaced with the introduction to Failure and Exception files having
their own types to identify them.
**New Proto Structure:**
```
message CoverageReport {
  oneof report_status {
    // Coverage report details when coverage data retrieval succeeds.
    CoverageDetails details = 1;
    // Coverage report failure when coverage data retrieval fails.
    CoverageFailure failure = 2;
    // Coverage exemption when the source file is exempted from having a test file.
    CoverageExemption exemption = 3;
  }
}
```
- **Handling Anomaly Cases:** There are scenarios where files could be
exempted, coverage cannot be retrieved, or coverage does not exist.
Previously, an error in one file could halt the entire process. Instead
of throwing an error, the flow continues while displaying the
encountered cases.
- **PASS / FAIL:** While still the coverage analysis continues with
failure / anomaly cases with any case other than a PASS would be
considered FAIL and checked at the end to throw an error at the end of
the entire execution completion, helping with both local dev and ci
checks.
- **Format:** Defaulting the report generation format to **HTML**
considering priority format for local development. While with both .md
and .html reports a text report will be logged to the console, so a
quick glance is provided and that will make .md obsolete for local
development.

(Updated) The Logged Report is now updated to only log reports that Fail
(either a hasFailure case or details that fail below threshold or if
exempted under overridden threshold)

Sample log while having min threshold as 99% and exempted percentage for
MathModel.kt as 101% (for testing purposes)

![image](https://github.com/user-attachments/assets/f6c816cc-13e5-462d-bdde-5b58076c4bc9)

**Logged Report Text:**


![image](https://github.com/oppia/oppia-android/assets/122200035/26e38860-4a02-4422-8ff7-4ab83ca6bed4)

- **Final Markdown Report:** The final Markdown report is generated in
the CoverageReporter.kt file, with the entire list of coverage data
proto collected from each file's coverage analysis. The report template
is inspired from [Oppia Web's Codecov
report](oppia/oppia#9618 (comment))
and includes a dropdown for better readability (provided below). Though
the original template was to have it as a list of dropdowns (the new
template is yet to be confirmed).

- The updated template also has the exempted percentage included to make
it clear and not cause any if any exempted cases are being included in
the analysis.

### MD Report Template

## Coverage Report

### Results
Number of files assessed: 5
Overall Coverage: **94.26%**
Coverage Analysis: **FAIL** ❌
##

### Failure Cases

| File | Failure Reason |
|------|----------------|
| File.kt | No appropriate test file found for File.kt. |

### Failing coverage

| File | Coverage | Lines Hit | Status | Min Required |
|------|:--------:|----------:|:------:|:------------:|
|
<details><summary>RunCoverage.kt</summary>scripts/src/java/org/oppia/android/scripts/coverage/RunCoverage.kt</details>
| 51.38% | 148 / 288 | ❌ | 70% |
|
<details><summary>MathModel.kt</summary>utility/src/main/java/org/oppia/android/util/parser/math/MathModel.kt</details>
| 77.78% | 7 / 9 | ❌ | 80% _*_ |
|
<details><summary>MultipleChoiceInputModule.kt</summary>domain/src/main/java/org/oppia/android/domain/classify/rules/multiplechoiceinput/MultipleChoiceInputModule.kt</details>
| 10.00% | 1 / 10 | ❌ | 30% _*_ |

>**_*_** represents tests with custom overridden pass/fail coverage
thresholds

### Passing coverage

<details>
<summary>Files with passing code coverage</summary><br>

| File | Coverage | Lines Hit | Status | Min Required |
|------|:--------:|----------:|:------:|:------------:|
|
<details><summary>MathTokenizer.kt</summary>utility/src/main/java/org/oppia/android/util/math/MathTokenizer.kt</details>
| 94.26% | 197 / 209 | ✅ | 70% |
</details>

### Exempted coverage
<details><summary>Files exempted from coverage</summary> <br>

<details><summary>ActivityComponent.kt</summary>app/src/main/java/org/oppia/android/app/activity/ActivityComponent.kt</details>

<details><summary>TestExemptedFile.kt</summary>app/src/main/java/org/oppia/android/app/activity/TestExemptedFile.kt</details>

<details><summary>SourceIncompatible.kt</summary>app/src/main/java/org/oppia/android/app/activity/SourceIncompatible.kt</details>
</details>

---

### To be discussed:
- The `shards_count` for RunCoverageTest.
- The `MIN_THRESHOLD` that need to be set.
- The final report having Success cases table included.
- On how to handle the anomaly cases (should they be considered FAIL
case for coverage analysis)
- To discuss cases when the coverage data are unavailable for source
targets (files) (ie SF: doesn't point to source files)

### Todo
- **[Done]** Use dynamic filename list taken from the arg (required for
both ci and developer workflow)
- **[Done]** Figure out a way on how to handle the delivery of the final
md report and check status generated
- The final md report will be used as an uploadable comment (considering
saving it to $(pwd)/finalreport.md (to access the same file in ci)
  - The check status will be used to set the ci run fail/pass case
- **[Done]** Update tests
- **[Done]** add min threshold for exempted files in the table to let
developers know them.
- **[Done]** Add links for anomaly case file paths too.
- **[Done]** Remove Asynchronous flow and have it Sequential
- **[Done]** The test files too need to be taken into account while
considering coverage analysis (mapping test files to their source files
and provide it to the script run, also these files need to be figured
out even in the compute changed files utility as that will help with
building the targets)

With this doing a script run of 
```
bazel run //scripts:run_coverage -- $(pwd) 
utility/src/main/java/org/oppia/android/util/parser/math/MathModel.kt 
scripts/src/javatests/org/oppia/android/scripts/coverage/CoverageRunnerTest.kt 
data/src/test/java/org/oppia/android/data/backends/gae/JsonPrefixNetworkInterceptorTest.kt 
app/src/sharedTest/java/org/oppia/android/app/story/StoryFragmentTest.kt 
app/src/test/java/org/oppia/android/app/application/alpha/AlphaBuildFlavorModuleTest.kt test.xml 
app/src/test/java/org/oppia/android/app/home/HomeActivityLocalTest.kt
```
will do coverage analysis on files:
```
Running coverage analysis for the files: [
utility/src/main/java/org/oppia/android/util/parser/math/MathModel.kt, 
scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt, 
data/src/main/java/org/oppia/android/data/backends/gae/JsonPrefixNetworkInterceptor.kt, 
app/src/main/java/org/oppia/android/app/story/StoryFragment.kt, 
app/src/main/java/org/oppia/android/app/application/alpha/AlphaBuildFlavorModule.kt, 
app/src/main/java/org/oppia/android/app/home/HomeActivity.kt
]
```

- **[Done]** The Error statements need to have a clear indication of why
it failed.
- **[Done]** Every fail case is a Coverage Status "FAIL' only a pass is
'PASS'
- **[Done]** Re-work on the final md generation [use a centralized proto
collection way, move the existing md generation script and have it with
the CoverageReporter just for md, have the exisiting html generation for
individual files]
- **[Done]** Add tests with addition to including test file's source
files.

## Essential Checklist
<!-- Please tick the relevant boxes by putting an "x" in them. -->
- [x] The PR title and explanation each start with "Fix #bugnum: " (If
this PR fixes part of an issue, prefix the title with "Fix part of
#bugnum: ...".)
- [x] Any changes to
[scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets)
files have their rationale included in the PR explanation.
- [x] The PR follows the [style
guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide).
- [x] The PR does not contain any unnecessary code changes from Android
Studio
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)).
- [x] The PR is made from a branch that's **not** called "develop" and
is up-to-date with "develop".
- [ ] The PR is **assigned** to the appropriate reviewers
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)).



<details><summary>Old Template</summary>

**FOR TESTING PURPOSE**
The below provided data was tested while having a min percentage of 99%
and having the test_file_exemption as
```
test_file_exemption {
  exempted_file_path: "utility/src/main/java/org/oppia/android/util/logging/ConsoleLogger.kt"
  override_min_coverage_percent_required: 20
}
test_file_exemption {
  exempted_file_path: "domain/src/main/java/org/oppia/android/domain/auth/FirebaseAuthWrapperImpl.kt"
  override_min_coverage_percent_required: 70
}
```

## Coverage Report

- Number of files assessed: 5
- Coverage Analysis: **FAIL** ❌

| File | Coverage | Lines Hit | Status | Min Required |
|-----|:----------:|---------:|:-------:|:--------------:|
|
[MathTokenizer.kt](https://github.com/oppia/oppia-android/tree/develop/utility/src/main/java/org/oppia/android/util/math/MathTokenizer.kt)
| 94% | 197 / 209 | ❌ | 99% |
|Exempted 🔻|
|
[FirebaseAuthWrapperImpl.kt](https://github.com/oppia/oppia-android/tree/develop/domain/src/main/java/org/oppia/android/domain/auth/FirebaseAuthWrapperImpl.kt)
| 31% | 5 / 16 | ❌ | 70% |

<details>
<summary>Succeeded Coverages</summary><br>

| File | Coverage | Lines Hit | Status | Min Required |
|-----|:----------:|---------:|:-------:|:--------------:|
|
[MathModel.kt](https://github.com/oppia/oppia-android/tree/develop/utility/src/main/java/org/oppia/android/util/parser/math/MathModel.kt)
| 100% | 19 / 19 | ✅ | 99% |
|Exempted 🔻|
|
[ConsoleLogger.kt](https://github.com/oppia/oppia-android/tree/develop/utility/src/main/java/org/oppia/android/util/logging/ConsoleLogger.kt)
| 54% | 30 / 55 | ✅ | 20% |
</details>

### Test File Exempted Cases
-
[ActivityComponent.kt](https://github.com/oppia/oppia-android/tree/develop/app/src/main/java/org/oppia/android/app/activity/ActivityComponent.kt)

[Todo] Add report with failure case and coverage check status.

<details>
<summary>Old template</summary>

---

## Coverage Report

- Total covered files: 5
- Coverage Status: **FAIL**
### Failed Coverages
Min Coverage Required: 40% _// the set value is 10 (MIN_THRESHOLD),
Using 40 for just testing._
| Covered File | Percentage | Line Coverage | Status |
|--------------|------------|---------------|--------|

|[FirebaseAuthWrapperImpl.kt](https://github.com/oppia/oppia-android/tree/develop/domain/src/main/java/org/oppia/android/domain/auth/FirebaseAuthWrapperImpl.kt)|31.25%|5
/ 16|:x:|

<details>
<summary>Succeeded Coverages</summary><br>

| Covered File | Percentage | Line Coverage | Status |
|--------------|------------|---------------|--------|

|[NumericExpressionEvaluator.kt](https://github.com/oppia/oppia-android/tree/develop/utility/src/main/java/org/oppia/android/util/math/NumericExpressionEvaluator.kt)|86.36%|19
/ 22|:white_check_mark:|

|[MathTokenizer.kt](https://github.com/oppia/oppia-android/tree/develop/utility/src/main/java/org/oppia/android/util/math/MathTokenizer.kt)|94.26%|197
/ 209|:white_check_mark:|

|[RealExtensions.kt](https://github.com/oppia/oppia-android/tree/develop/utility/src/main/java/org/oppia/android/util/math/RealExtensions.kt)|89.73%|201
/ 224|:white_check_mark:|
</details>

### Anomaly Cases
- The file:
[ActivityComponent.kt](https://github.com/oppia/oppia-android/tree/develop/app/src/main/java/org/oppia/android/app/activity/ActivityComponent.kt)
is exempted from having a test file; skipping coverage check.

---

</details>
</details>
BenHenning pushed a commit that referenced this issue Aug 10, 2024
<!-- READ ME FIRST: Please fill in the explanation section below and
check off every point from the Essential Checklist! -->
## Explanation
<!--
- Explain what your PR does. If this PR fixes an existing bug, please
include
- "Fixes #bugnum:" in the explanation so that GitHub can auto-close the
issue
  - when this PR is merged.
  -->

Fixes part of #5343 

### Project
[PR 2.3 of Project 4.1]

### Changes Made
- Replicated the compute affected test utility to compute changed files
to acquire the list of kotlin files changed based on changes in the
local Oppia Android Git repository, which will be organized into shards.
It categorizes files by their paths into buckets (app, data, domain,
etc.) and applies sharding strategies (large, medium, small).
- Modified BazelClient to run coverage commands based on shard
configurations.
- Introducing a new CI workflow replicating the unit_test.yml
implementation.
- The Coverage workflow should **run only after** the unit test (bazel)
workflow is **successfully completed**.
- With **[RunAllTests]** added to the title this should perform code
coverage on every file
- This PR is intended only to run coverages and the storing of protos
and uploading of comments are yet to be figured out with the upcoming
PR.

### Todo:
- **[Done]** Add test cases with RunAllTests setting.
- When a test file is provided the corresponding source file need to be
mapped and provided for Build Oppia File (to pre build it before code
coverage).
- Need to look after the runs and verify them.
  - To run only if unit tests pass:
- Below image represents the ci check where the unit test fails causing
the coverage runs to skip but still throw a fail status.

![image](https://github.com/user-attachments/assets/d85ac3d0-0d25-454d-ba04-0a3522f2b58d)


## Essential Checklist
<!-- Please tick the relevant boxes by putting an "x" in them. -->
- [x] The PR title and explanation each start with "Fix #bugnum: " (If
this PR fixes part of an issue, prefix the title with "Fix part of
#bugnum: ...".)
- [x] Any changes to
[scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets)
files have their rationale included in the PR explanation.
- [x] The PR follows the [style
guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide).
- [x] The PR does not contain any unnecessary code changes from Android
Studio
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)).
- [x] The PR is made from a branch that's **not** called "develop" and
is up-to-date with "develop".
- [x] The PR is **assigned** to the appropriate reviewers
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)).
BenHenning pushed a commit that referenced this issue Aug 13, 2024
…t as comments (#5469)

## Explanation
Fixes part of #5343 

### Project
[PR 2.4 of Project 4.1]

### Changes Made

With the protos collected and stored with their respective file paths
through #5465, this PR will focus on collecting the stored proto files
and passing it to the script to generate a coverage report along with a
status check to decide the success failure case of the CI Coverage Check
run.

**Collection of protos**
- The stored protos are now being uploaded as an artifact.
- The name of the artifact is set to a dynamic value corresponding to
its shard_name.
- The shard_name is extracted from the first portion of the
`CHANGED_FILES_BUCKET_BASE64_ENCODED_SHARD` value.
- eg: The matrix job -
[app-shard0;H4sIAAAAAAAAAONiTiwoEHIFEvrFRcn6uYmZefpZi....] will save the
artifact with name **coverage-report-app-shard0**
- The dynamic or unique name is important to prevent the following
error:
```
Error: Failed to CreateArtifact: Received non-retryable error: Failed request: (409) Conflict: 
an artifact with this name already exists on the workflow run
```
- The artifacts that match the pattern of coverage-report-* are
downloaded.

```
Found 4 artifact(s)
Filtering artifacts by pattern 'coverage-report-*'
Preparing to download the following artifacts:
- coverage-report-domain-shard0 (ID: 1799350592, Size: 489)
- coverage-report-scripts-shard2 (ID: 1799348996, Size: 2075)
- coverage-report-app-shard3 (ID: 1799348891, Size: 770)
- coverage-report-generic-shard1 (ID: 1799348719, Size: 551)
```
- All the stored coverage_report.pb files are found and their paths are
stored as list.
- The list of coverage_report.pb files are then passed to the
CoverageReporter.kt script to handle the coverage report protos.
- The script combines them as one single CoverageReportContainer to
generate a Markdown report with it.
- Finally, a .md report is stored and based on the status of the
coverage check, the job either succeeds or fails.
- The stored md report is again uploaded and downloaded as an artifact
to pass it for publication of the report.
- The CoverageReport.md file is then uploaded as a comment to the
corresponding PR using -
https://github.com/peter-evans/create-or-update-comment action

>The comment will be published regardless of whether the coverage passes
or fails. The only time comments will not be published is if the unit
tests themselves fail, making the coverage checks non-functional (also
less cluttered).

#

### CI Run Data

This check was run with 4 different shards on all possible cases capable
of being produced.
Check :
https://github.com/oppia/oppia-android/actions/runs/10340867060?pr=5469
Comment Published with the above run:
#5469 (comment)

The above cases are run with custom temporary changes to the test
exemption file (testing purposes).
```
test_file_exemption {
  exempted_file_path: "scripts/src/java/org/oppia/android/scripts/testfile/TestFileCheck.kt"
  override_min_coverage_percent_required: 101
}
test_file_exemption {
  exempted_file_path: "utility/src/main/java/org/oppia/android/util/logging/ConsoleLogger.kt"
  override_min_coverage_percent_required: 30
}
```

## Essential Checklist
- [x] The PR title and explanation each start with "Fix #bugnum: " (If
this PR fixes part of an issue, prefix the title with "Fix part of
#bugnum: ...".)
- [x] Any changes to
[scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets)
files have their rationale included in the PR explanation.
- [x] The PR follows the [style
guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide).
- [x] The PR does not contain any unnecessary code changes from Android
Studio
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)).
- [x] The PR is made from a branch that's **not** called "develop" and
is up-to-date with "develop".
- [x] The PR is **assigned** to the appropriate reviewers
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)).
BenHenning added a commit that referenced this issue Aug 23, 2024
…e usage and limitations (#5483)

## Explanation
Fixes part of #5343 
Fixes #5486 

### Project
[PR 2.6 of Project 4.1]

### Changes Made
- This PR introduces 2 new wiki pages:
  - Oppia Android Code Coverage
  - Writing tests with Good Behavioural Coverage
- Fix to the comment upload feature permission issues with PRs created
from the forked branches.
  - Split the code coverage workflow into 2
    1.  Core code coverage workflow to handle 
        - Collection of changed files 
        - Bucket partitioning
        - Run coverage in matrices
    2.  Comment upload workflow to handle
        - evaluation of reports 
        - generation of md reports 
        - uploading comments
        - Coverage Status Checks
      (as the later required `pull_request_target`)
- Fix to #5486 
- The issue should have arisen as the pr got merged with the branch
being deleted while the publish comment job still running, finding it
hard to fetch the pr-issue number to publish a comment.
- Now the Coverage Check Status was made to be dependent on the comment
uploader ie. the final Coverage check job occurs only after the
Evaluation and Comment jobs are done, so it will always have the pr
reference)
```
  check_coverage_results:
    name: Check Code Coverage Results
    needs: [ evaluate-code-coverage-reports, comment_coverage_report ]
```

#

### Reasons for splitting the code_coverage workflow 

The single code_coverage workflow was split into 
1. **code_coverage** (to run coverages)
2. **coverage_report** (to generate and publish reports)

### Separating the comment upload job

- The primary reason is the need to have ability to upload comments from
PRs opened from a fork branch.
-
[`pull_request_target`](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request_target):
For workflows that are triggered by the pull_request_target event, the
GITHUB_TOKEN is granted read/write repository permission, even when it
is triggered from a fork.
- Workflows triggered by `pull_request_target` events are run in the
context of the base branch. Since the base branch is considered trusted,
workflows triggered by these events will always run, regardless of
approval settings. [[GitHub
Docs](https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/approving-workflow-runs-from-public-forks#about-workflow-runs-from-public-forks)]

### Separating the evaluation / generation of report job

- While initially it was split to help with 'skip files' - no files
changed conditional check, with the introduction to 'SKIP' status check,
it doesn't continue to serve the mentioned purpose.
- But if we still have it as one workflow then the flow will work as
such:

Workflow 1: **code_coverage** 
  - compute changed files
  - run coverage (needs compute changed files)
  - evaluate / generate md
  - code coverage check result

Workflow 2: **coverage_report**
  - comment publication
  
If no `.kt` files changes are detected
  - compute changed files
  - skips run coverage 
  - skips evaluate / generate md
  - pass code coverage check result 

As the workflow was concluded as success, the 2nd workflow runs as,
  - failed comment publication (as no report is generation due to skip)

But expectation is to still produce a pass check for the comment
publication. (either to at least skip or upload a skip status as
coverage comment report)

- With moving it to a separate workflow allows us to not make the
evaluation / generation jobs rely on the Run coverage job making it
independently behave once the code_coverage workflows are completed
successfully.
- And it checks if pb files are generated and based on that it decides
whether to generate PASS, FAIL or SKIP status checks.

### Separating the coverage status check result job

There are 2 main reasons to moving it to new workflow. While it would
still make sense to have it with the 1st workflow itself after Run
coverage, the drawbacks are,

- If the check coverage status result was left with the 1st workflow,
then when the Run coverage job completes in the 1st workflow the
coverage status check result is set to true on success even before the
sibling part of upload comment is done, making it an incomplete status
result.
- #5486 occurred as it lost its reference to the pr number, so making
the coverage check status result dependent on (needs) the comment upload
job should resolve this by only allowing the PR to be closed once the
comment is uploaded.

#

**Todo:**
- **[Done]** Add a new wiki page for "Writing effective tests / Writing
test with good behavioural coverage"


## Essential Checklist
- [x] The PR title and explanation each start with "Fix #bugnum: " (If
this PR fixes part of an issue, prefix the title with "Fix part of
#bugnum: ...".)
- [x] Any changes to
[scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets)
files have their rationale included in the PR explanation.
- [x] The PR follows the [style
guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide).
- [x] The PR does not contain any unnecessary code changes from Android
Studio
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)).
- [x] The PR is made from a branch that's **not** called "develop" and
is up-to-date with "develop".
- [x] The PR is **assigned** to the appropriate reviewers
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)).

## For UI-specific PRs only
If your PR includes UI-related changes, then:
- Add screenshots for portrait/landscape for both a tablet & phone of
the before & after UI changes
- For the screenshots above, include both English and pseudo-localized
(RTL) screenshots (see [RTL
guide](https://github.com/oppia/oppia-android/wiki/RTL-Guidelines))
- Add a video showing the full UX flow with a screen reader enabled (see
[accessibility
guide](https://github.com/oppia/oppia-android/wiki/Accessibility-A11y-Guide))
- For PRs introducing new UI elements or color changes, both light and
dark mode screenshots must be included
- Add a screenshot demonstrating that you ran affected Espresso tests
locally & that they're passing

---------

Co-authored-by: Ben Henning <[email protected]>
Rd4dev added a commit to Rd4dev/oppia-android that referenced this issue Aug 24, 2024
adhiamboperes pushed a commit to adhiamboperes/oppia-android that referenced this issue Aug 24, 2024
…de coverage usage and limitations (oppia#5483)

## Explanation
Fixes part of oppia#5343 
Fixes oppia#5486 

### Project
[PR 2.6 of Project 4.1]

### Changes Made
- This PR introduces 2 new wiki pages:
  - Oppia Android Code Coverage
  - Writing tests with Good Behavioural Coverage
- Fix to the comment upload feature permission issues with PRs created
from the forked branches.
  - Split the code coverage workflow into 2
    1.  Core code coverage workflow to handle 
        - Collection of changed files 
        - Bucket partitioning
        - Run coverage in matrices
    2.  Comment upload workflow to handle
        - evaluation of reports 
        - generation of md reports 
        - uploading comments
        - Coverage Status Checks
      (as the later required `pull_request_target`)
- Fix to oppia#5486 
- The issue should have arisen as the pr got merged with the branch
being deleted while the publish comment job still running, finding it
hard to fetch the pr-issue number to publish a comment.
- Now the Coverage Check Status was made to be dependent on the comment
uploader ie. the final Coverage check job occurs only after the
Evaluation and Comment jobs are done, so it will always have the pr
reference)
```
  check_coverage_results:
    name: Check Code Coverage Results
    needs: [ evaluate-code-coverage-reports, comment_coverage_report ]
```

#

### Reasons for splitting the code_coverage workflow 

The single code_coverage workflow was split into 
1. **code_coverage** (to run coverages)
2. **coverage_report** (to generate and publish reports)

### Separating the comment upload job

- The primary reason is the need to have ability to upload comments from
PRs opened from a fork branch.
-
[`pull_request_target`](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request_target):
For workflows that are triggered by the pull_request_target event, the
GITHUB_TOKEN is granted read/write repository permission, even when it
is triggered from a fork.
- Workflows triggered by `pull_request_target` events are run in the
context of the base branch. Since the base branch is considered trusted,
workflows triggered by these events will always run, regardless of
approval settings. [[GitHub
Docs](https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/approving-workflow-runs-from-public-forks#about-workflow-runs-from-public-forks)]

### Separating the evaluation / generation of report job

- While initially it was split to help with 'skip files' - no files
changed conditional check, with the introduction to 'SKIP' status check,
it doesn't continue to serve the mentioned purpose.
- But if we still have it as one workflow then the flow will work as
such:

Workflow 1: **code_coverage** 
  - compute changed files
  - run coverage (needs compute changed files)
  - evaluate / generate md
  - code coverage check result

Workflow 2: **coverage_report**
  - comment publication
  
If no `.kt` files changes are detected
  - compute changed files
  - skips run coverage 
  - skips evaluate / generate md
  - pass code coverage check result 

As the workflow was concluded as success, the 2nd workflow runs as,
  - failed comment publication (as no report is generation due to skip)

But expectation is to still produce a pass check for the comment
publication. (either to at least skip or upload a skip status as
coverage comment report)

- With moving it to a separate workflow allows us to not make the
evaluation / generation jobs rely on the Run coverage job making it
independently behave once the code_coverage workflows are completed
successfully.
- And it checks if pb files are generated and based on that it decides
whether to generate PASS, FAIL or SKIP status checks.

### Separating the coverage status check result job

There are 2 main reasons to moving it to new workflow. While it would
still make sense to have it with the 1st workflow itself after Run
coverage, the drawbacks are,

- If the check coverage status result was left with the 1st workflow,
then when the Run coverage job completes in the 1st workflow the
coverage status check result is set to true on success even before the
sibling part of upload comment is done, making it an incomplete status
result.
- oppia#5486 occurred as it lost its reference to the pr number, so making
the coverage check status result dependent on (needs) the comment upload
job should resolve this by only allowing the PR to be closed once the
comment is uploaded.

#

**Todo:**
- **[Done]** Add a new wiki page for "Writing effective tests / Writing
test with good behavioural coverage"


## Essential Checklist
- [x] The PR title and explanation each start with "Fix #bugnum: " (If
this PR fixes part of an issue, prefix the title with "Fix part of
#bugnum: ...".)
- [x] Any changes to
[scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets)
files have their rationale included in the PR explanation.
- [x] The PR follows the [style
guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide).
- [x] The PR does not contain any unnecessary code changes from Android
Studio
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)).
- [x] The PR is made from a branch that's **not** called "develop" and
is up-to-date with "develop".
- [x] The PR is **assigned** to the appropriate reviewers
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)).

## For UI-specific PRs only
If your PR includes UI-related changes, then:
- Add screenshots for portrait/landscape for both a tablet & phone of
the before & after UI changes
- For the screenshots above, include both English and pseudo-localized
(RTL) screenshots (see [RTL
guide](https://github.com/oppia/oppia-android/wiki/RTL-Guidelines))
- Add a video showing the full UX flow with a screen reader enabled (see
[accessibility
guide](https://github.com/oppia/oppia-android/wiki/Accessibility-A11y-Guide))
- For PRs introducing new UI elements or color changes, both light and
dark mode screenshots must be included
- Add a screenshot demonstrating that you ran affected Espresso tests
locally & that they're passing

---------

Co-authored-by: Ben Henning <[email protected]>
BenHenning pushed a commit that referenced this issue Aug 28, 2024
…overage Wiki Page (#5511)

<!-- READ ME FIRST: Please fill in the explanation section below and
check off every point from the Essential Checklist! -->
## Explanation
<!--
- Explain what your PR does. If this PR fixes an existing bug, please
include
- "Fixes #bugnum:" in the explanation so that GitHub can auto-close the
issue
  - when this PR is merged.
  -->

Fixes Part of #5343 

### This PR includes

- Updated the incorrect link reference in the #5483 for the Oppia
Android Code Coverage Page
- Current Broken link:
https://github.com/oppia/oppia-android-workflow/wiki/Oppia-Android-Code-Coverage
- Correct link to wiki:
https://github.com/oppia/oppia-android/wiki/Oppia-Android-Code-Coverage
- Fixed an incorrect SKIP status that triggered even after 'Unit Tests -
Bazel' failure causing it to miscalculate the pb file list as zero
thereby posting a skip comment.
  - Solved by adding an additional condition for the evaluation job.
```
if: ${{ !cancelled() && needs.check_unit_tests_completed.result == 'success'}}
```
- The code coverage comment got triggered even after assignment changes
due to the presence of 'assigned' in the on `pull_request_target`
triggered, fixed it by removing the 'assigned' trigger.
- Utilized 'HtmlEscapers' to escape HTML characters from source code
lines in CoverageReporter.kt as strings those already included html tags
overlapped / conflicted with the report html templates.
- Added limitations section to the 'Oppia-Android-Code-Coverage' wiki
page
- Filed all possible coverage gaps that exist right now based on the
available pass cases.

## Essential Checklist
<!-- Please tick the relevant boxes by putting an "x" in them. -->
- [x] The PR title and explanation each start with "Fix #bugnum: " (If
this PR fixes part of an issue, prefix the title with "Fix part of
#bugnum: ...".)
- [x] Any changes to
[scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets)
files have their rationale included in the PR explanation.
- [x] The PR follows the [style
guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide).
- [x] The PR does not contain any unnecessary code changes from Android
Studio
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)).
- [x] The PR is made from a branch that's **not** called "develop" and
is up-to-date with "develop".
- [x] The PR is **assigned** to the appropriate reviewers
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)).

## For UI-specific PRs only
<!-- Delete these section if this PR does not include UI-related
changes. -->
If your PR includes UI-related changes, then:
- Add screenshots for portrait/landscape for both a tablet & phone of
the before & after UI changes
- For the screenshots above, include both English and pseudo-localized
(RTL) screenshots (see [RTL
guide](https://github.com/oppia/oppia-android/wiki/RTL-Guidelines))
- Add a video showing the full UX flow with a screen reader enabled (see
[accessibility
guide](https://github.com/oppia/oppia-android/wiki/Accessibility-A11y-Guide))
- For PRs introducing new UI elements or color changes, both light and
dark mode screenshots must be included
- Add a screenshot demonstrating that you ran affected Espresso tests
locally & that they're passing
@BenHenning
Copy link
Member Author

I think we can close this as the project is essentially finished now. :) Thanks again @Rd4dev for all the work on this!

@BenHenning
Copy link
Member Author

So I spent a lot of time this week trying to get up to a point of verifying this result, but I couldn't quite get one of the modularization PRs building again (the prerequisites #4920 and #4978 took a long time to get working). I'll need to revisit this when I next have availability (in July).

So I meant to follow up to this earlier. We decided to forego trying to finish modularization work before adding in code coverage because the lift was too much, and we can still get a lot of value out of code coverage in the meantime. Instead, #5481 was filed to track getting these tests explicitly fixed (and they were exempted in #5480).

Modularization work still needs to happen before we can comfortably move off of Gradle (since the large Bazel library targets take comparably much longer to build--Bazel shines at incremental builds, but only if the incremental targets are reasonably small). The next PR that will be merged to move this forward is #4979 and it has some prerequisite work that needs to be finished first. I started updating these old branches to the latest tip-of-tree, but unsurprisingly there are a lot of new dependency fixes that needed to be added (and the script introduced in #4978 to support this has also had a lot of recent fixes). It will probably be a few months yet before the modularization work can make it into a proper review state, but after that most test exemptions for code coverage should be able to be lifted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement End user-perceivable enhancements.
Development

No branches or pull requests

4 participants