Introduction

Testing is an integral part of the software development lifecycle, ensuring that software applications and their individual components function correctly and meet specified requirements. Various types of testing are used to validate different aspects of the application, from individual units of code, such as functions or classes, to the integrated system and external components.

Test-to-Pass vs Test-to-Fail

Two fundamental approaches to testing are test-to-pass and test-to-fail. Understanding these approaches helps in designing more robust and comprehensive test cases.

Test-to-Pass confirms that the software works as expected under normal conditions. The general approach is to write tests with valid inputs to verify that the software performs the desired operations correctly. The focus is on typical usage scenarios to ensures that the software meets its functional requirements which helps verify the correctness of the main functionality. However, these tests may not uncover edge cases or rare conditions and thus are primarily focused on confirming positive scenarios.

On the other hand, Test-to-Fail testing identifies scenarios where the software might fail and ensure it handles them gracefully. The idea is to write tests with invalid or unexpected inputs to check how the software handles errors and edge cases and whether the system’s or application’s performance gracefully degrades – or simply crashes. Thus the focus is on robustness and error handling to ensure that the software fails in a controlled manner and provides meaningful error messages or handles exceptions appropriately. The main benefits of test-to-fail include helping to identify and fix potential weaknesses in the software, ensure robustness by handling edge cases and unexpected inputs, and improve the reliability of the software by testing how it fails. Naturally, it may not cover all typical usage scenarios and requires substantial effort to identify and create edge case tests.

Both test-to-pass and test-to-fail are essential components of a robust testing strategy. While test-to-pass ensures that the software meets its functional requirements, test-to-fail identifies potential weaknesses and improves the software’s robustness. By integrating both approaches, the software developer can develop more reliable and resilient software, ultimately enhancing user satisfaction and reducing the risk of failures in production.

Testing Workflow

A comprehensive testing workflow should include both test-to-pass and test-to-fail approaches and generally requires the following process steps:

  1. Define Clear Requirements: Clearly define the expected behavior of the software, including both normal operations and error handling.

  2. Develop a Test Plan: Create a test plan that outlines which scenarios to test, including both typical use cases and edge cases.

  3. Automate Testing: Use automated testing tools to regularly run both test-to-pass and test-to-fail scenarios, ensuring continuous validation of the software.

  4. Prioritize Critical Functions: Focus on critical functions and high-risk areas first, ensuring that they are thoroughly tested under both normal and exceptional conditions.

  5. Review and Refactor: Continuously review and refactor your test cases based on new insights and changing requirements, ensuring comprehensive coverage.

Types of Testing

Most software development organizations perform seven different levels of testing, each ensuring a distinct degree of functionality.

  1. Unit Testing
  2. Integration Testing
  3. System Testing
  4. Acceptance Testing
  5. Performance Testing
  6. Security Testing
  7. Usability Testing

Unit Testing

Objective: Verify that individual units or components of the software work as intended.

How to Perform: - Write test cases for each function or method in isolation. - Use assertions to check if the function returns expected results for given inputs. - Tools: JUnit for Java, pytest for Python, testthat for R.

Integration Testing

Objective: Ensure that different modules or services in a system work together as expected.

How to Perform: - Test the interaction between integrated components. - Identify and test critical integration points. - Tools: JUnit with Spring for Java, pytest for Python, testthat for R.

System Testing

Objective: Validate the complete and fully integrated software product to ensure it meets the requirements. Create user stories and acceptance criteria to validate if the arithmetic operations fulfill the business needs.

How to Perform: - Conduct end-to-end testing of the application. - Test scenarios that reflect real-world usage. - Tools: Selenium for web applications, QTP/UFT for desktop applications.

Acceptance Testing

Objective: Verify that the software meets the business requirements and is ready for delivery.

How to Perform: - Conducted by the end-users or testers. - Use predefined acceptance criteria. - Tools: Cucumber, FitNesse.

Performance Testing

Objective: Ensure the software performs well under expected load conditions and that throughput and response time meet non-functional quality-of-service requirements.

How to Perform: - Measure response time, throughput, and resource utilization. - Conduct stress, load, and scalability tests. - Tools: JMeter, LoadRunner.

Security Testing

Objective: Identify vulnerabilities and ensure the software is secure, for example checking for common vulnerabilities such as SQL Injection Attacks, Denial of Service Attacks, and Buffer Overflow Attacks. Also, verifies that information is kept secure, encrypted, and confidential.

How to Perform: - Perform penetration testing and vulnerability scanning. - Test for common security issues like SQL injection, XSS, etc. - Tools: OWASP ZAP, Burp Suite.

Usability Testing

Objective: Verify that the software is user-friendly and meets user experience standards. Commonly uses observation and task completion studies.

How to Perform: - Conduct tests with real users. - Gather feedback on ease of use, interface design, etc. - Tools: UserTesting.com, Morae.

Best Practices

  1. Automate Where Possible: Use automated testing tools to save time and reduce human error.
  2. Test Early and Often: Integrate testing into your development process from the beginning.
  3. Use a Test Plan: Develop a comprehensive test plan that outlines testing strategies, scope, resources, and schedule.
  4. Prioritize Tests: Focus on critical functionalities and high-risk areas.
  5. Review and Refactor: Continuously review and improve your test cases to adapt to changing requirements.

Test Automation with testthat

Testing is a crucial part of software development that ensures your code works correctly. In R, the testthat package provides a robust framework for writing and running tests. This tutorial will guide you through the concepts of unit and system testing using the framework of the testthat package.

Setting Up the Environment

First, you need to install the testthat package if you haven’t already, using either the R code fragment below, or by installing it through your IDE (RStudio, Posit, or VS Code, etc.):

Installation is only necessary once, but you need to load the package into your R session everytime you wish to use it:

library(testthat)

Unit Testing

Unit testing focuses on testing individual functions or components of your code. The goal is to verify that each function performs as expected.

Writing Unit Tests

Consider a simple function that adds two numbers:

add <- function(x, y) {
  return(x + y)
}

To write a unit test for this function, create a separate test file. By convention, test files are placed in a β€œtests/testthat” directory within your project folder. Let’s name our test file test-add.R.

In test-add.R, you would write the following tests:

# TEST SCRIPT: test-add.R

library(testthat)

test_that("addition works", {
  expect_equal(add(1, 1), 2)
  expect_equal(add(-1, -1), -2)
  expect_equal(add(1, -1), 0)
})
## Test passed 🎊

In the above code, the function test_that defines a test block, and expect_equal checks if the function output matches the expected result.

Running Unit Tests

You can run the tests using the following command (assuming that you have your tests defined in the folder tests/testthat:

test_dir("tests/testthat")

Alternatively, if you are using RStudio/Posit, you can use the β€œBuild” pane to run all tests. In addition, you can run the above command from the R Console within RStudio/Posit which would allow you to keep the testing mechanism outside your program/script code.

System Testing

System testing, also sometimes referred to as integration testing (even though it is not quite the same), involves testing the complete system or application. It ensures that different parts of the application work together as expected.

Writing System Tests

Let’s expand our example to a small system that performs basic arithmetic operations. We’ll create functions for addition, subtraction, multiplication, and division:

add <- function(x, y) {
  return(x + y)
}

subtract <- function(x, y) {
  return(x - y)
}

multiply <- function(x, y) {
  return(x * y)
}

divide <- function(x, y) {
  if (y == 0) {
    stop("Division by zero error")
  }
  return(x / y)
}

Next, we will create a new test file in the folder tests/testthat named test-arithmetic.R for system tests:

# TEST FILE: test-arithmetic.R

library(testthat)

test_that("arithmetic operations work correctly", {
  expect_equal(add(2, 3), 5)
  expect_equal(subtract(5, 3), 2)
  expect_equal(multiply(2, 3), 6)
  expect_equal(divide(6, 3), 2)
  
  # Testing edge cases
  expect_error(divide(1, 0), "Division by zero error")
})

In this test, we are checking the correctness of all arithmetic functions together, including handling edge cases like division by zero.

Running System Tests

Run the tests using the same command as for unit tests (again, assuming that the above test code exists in the folder):

test_dir("tests/testthat")
## βœ” | F W  S  OK | Context
## ⠏ |          0 | add                                                            βœ” |          3 | add
## ⠏ |          0 | arithmetic                                                     βœ” |          5 | arithmetic
## 
## ══ Results ═════════════════════════════════════════════════════════════════════
## [ FAIL 0 | WARN 0 | SKIP 0 | PASS 8 ]

Note that this command runs all tests in the folder tests/testthat. This allows tests to be segmented and more easily managed.

Best Practices for Testing in R

  1. Write Tests Early: Develop your tests alongside your code to catch issues early. Some software development frameworks require tests to be written before the code is created to ensure that the code matches the requirements: write against tests.
  2. Test Edge Cases: Always consider and test for edge cases and unusual inputs, especially checking boundary conditions. Most errors occur on boundaries, e.g., if a number is supposed to be 10 or more, then test for 9 (fail) and 10 (pass).
  3. Keep Tests Small and Focused: Each test should focus on a single aspect of the function’s behavior.
  4. Use Descriptive Names: Use descriptive names for your test cases to make it clear what is being tested.
  5. Automate Testing: Integrate your tests into your development workflow to run them automatically.

Testing Side Effects

Side Effects in Programming

In programming, a side effect occurs when a function or expression modifies some state or interacts with the external world in ways beyond returning a value. Side effects can include altering a variable, modifying a data structure, writing to a file, writing to a database, sending a message to another process, or changing the state of the user interface.

There are several characteristics of side effects, including

  1. Modifying Variables: Changing the value of variables that exist outside the function’s local scope.
  2. I/O Operations: Reading from or writing to external sources like files, databases, or network sockets.
  3. State Changes: Modifying the state of objects or data structures in ways that persist beyond the function call.
  4. Interaction with External Systems: Calling external APIs or interacting with hardware components.

Consider a function that increments a global variable:

counter <- 0

increment_counter <- function() {
  counter <<- counter + 1
}

Here, increment_counter modifies the global variable counter, causing a side effect.

Another example is when a function writes to a file:

write_to_file <- function(text) {
  write(text, file = "output.txt")
}

Writing to a file is a side effect because it changes the state of the file system.

Functional Programming

In functional programming, side effects are minimized or eliminated to ensure functions are pure. A pure function is one that, given the same input, always returns the same output and does not cause any side effects.

Example of a Pure Function:

add <- function(x, y) {
  return(x + y)
}

This function is pure because it does not modify any state or interact with the outside world.

Practical Side Effects

Interactions with the outside world (e.g., user input, file operations) are inherently side effects and are essential for real-world applications. They would not be possible to build without side effects. Side effects can be useful for managing state and controlling program flow.

However, functions with side effects are more challenging to test because their behavior can depend on external state. In addition, side effects can introduce defects (bugs) that are difficult to trace, especially in large codebases. Consequently, functions with side effects are less predictable, as they may behave differently based on external conditions.

In practice, while we often need side effect, it is advisable to manage side effects effectively and to minimize them as much as feasible. Use pure functions wherever possible and limit side effects to specific parts of the code. Encapsulate side effects within well-defined boundaries, such as specific modules, classes, or layers of the application. Prefer immutable data structures that do not change state after creation. And, finally, isolate side effects in tests, using techniques like mocking to simulate interactions with external systems.

Testing Database Code

Modifications of databases through SQL statements or triggers is a type of side effect. To test SQL code and triggers using the testthat package, we need to write functions that interact with the database and perform the required checks.

Let’s walk through an example using SQLite. The steps are shown below

1. Creating a Test Environment

Create a temporary SQLite database, set up the necessary tables and triggers, and populate the database with synthetic sample data. In the example below, we use the special database name β€œ:memory:” which creates a SQLite database in memory rather than in the file system. The function dbExecute() returns a status of 0 when the SQL code was executed correctly. We are omitting the checks in the code below for brevity.

library(RSQLite)

# Create a temporary in-memopry SQLite database
con <- dbConnect(RSQLite::SQLite(), ":memory:")

# Create tables
s <- dbExecute(con, paste0("CREATE TABLE users (",
                           "  id INTEGER PRIMARY KEY, ",
                           "  name TEXT, ",
                           "  last_updated TEXT)"))
s <- dbExecute(con, paste0("CREATE TABLE orders (",
                           "  order_id INTEGER PRIMARY KEY, ",
                           "  user_id INTEGER, ",
                           "  status TEXT, ",
                           "  FOREIGN KEY (user_id) REFERENCES users(id))"))
s <- dbExecute(con, "CREATE TABLE audit_log (log_id INTEGER PRIMARY KEY, user_id INTEGER, action TEXT)")

# Create a trigger
s <- dbExecute(con, "
  CREATE TRIGGER update_timestamp
  AFTER UPDATE ON users
  FOR EACH ROW
  BEGIN
    UPDATE users SET last_updated = CURRENT_TIMESTAMP WHERE id = NEW.id;
    INSERT INTO audit_log (user_id, action) VALUES (NEW.id, 'updated');
  END
")

2. Writing Tests Using testthat**

Next, we write test cases for unit testing, integration testing, and data integrity testing.

Unit Testing

library(testthat)

test_that("trigger updates timestamp", {
  # Insert a test record
  dbExecute(con, "INSERT INTO users (id, name, last_updated) VALUES (1, 'Alice', '2023-01-01 00:00:00')")

  # Update the test record
  dbExecute(con, "UPDATE users SET name = 'Alice Updated' WHERE id = 1")

  # Check if the trigger updated the timestamp
  result <- dbGetQuery(con, "SELECT last_updated FROM users WHERE id = 1")
  expect_false(result$last_updated == '2023-01-01 00:00:00')
})
## Test passed 😸

Integration Testing

test_that("integration of users and audit_log", {
  # Insert a test record
  dbExecute(con, "INSERT INTO users (id, name) VALUES (2, 'Bob')")

  # Update the test record
  dbExecute(con, "UPDATE users SET name = 'Bob Updated' WHERE id = 2")

  # Check if the trigger inserted into the audit_log
  result <- dbGetQuery(con, "SELECT * FROM audit_log WHERE user_id = 2")
  expect_equal(nrow(result), 1)
  expect_equal(result$action, 'updated')
})
## Test passed πŸ₯‡

Data Integrity Testing

test_that("foreign key constraint prevents deletion", {
  # Insert test records
  dbExecute(con, "INSERT INTO users (id, name) VALUES (3, 'Charlie')")
  dbExecute(con, "INSERT INTO orders (order_id, user_id, status) VALUES (1, 3, 'pending')")

  # Attempt to delete the user (should fail due to foreign key constraint)
  expect_error(dbExecute(con, "DELETE FROM users WHERE id = 3"))

  # Verify that the user is still present
  result <- dbGetQuery(con, "SELECT * FROM users WHERE id = 3")
  expect_equal(nrow(result), 1)
})

3. Running the Tests

As shown before, to run the tests, use the test_dir or test_file functions from the testthat package. If your tests are in a directory called tests/testthat, you can run them all with:

testthat::test_dir("tests/testthat")

Or, if you have your tests in a single file, you can run:

testthat::test_file("tests/testthat/test_sql.R")

Conclusion

Effective testing is vital for delivering high-quality software. By understanding and implementing different types of testing, you can ensure that your software not only meets requirements but also performs well in real-world scenarios. Adopting a comprehensive testing strategy helps in identifying issues early, reducing costs, and enhancing the overall reliability and user satisfaction of your software product.

Using the testthat package in R, you can easily create and run both unit and system tests to ensure your code functions as intended. By adopting a comprehensive testing strategy, you can improve the reliability and maintainability of your R projects.

Side effects are a fundamental concept in programming, representing any interaction with or modification of external state. While they are necessary for real-world applications, managing them effectively is crucial for writing reliable, maintainable, and testable code. Understanding and controlling side effects can significantly improve the quality and predictability of software.

By using testthat, you can effectively test SQL code and triggers within R. This approach allows you to write comprehensive unit, integration, and data integrity tests, ensuring your SQL operations perform as expected and maintain data integrity. Integrating these tests into your development workflow helps identify issues early and improves the reliability of your database operations.


Files & Resources

All Files for Lesson 6.194

References

None yet.

Errata

Let us know.

LS0tCnRpdGxlOiAiQXV0b21hdGVkIFVuaXQgYW5kIEludGVncml0eSBUZXN0aW5nIGluIFIiCnBhcmFtczoKICBjYXRlZ29yeTogNgogIG51bWJlcjogMTk0CiAgdGltZTogNDUKICBsZXZlbDogYmVnaW5uZXIKICB0YWdzOiAicix0ZXN0dGhhdCx1bml0IHRlc3RpbmcsdGVzdGluZyIKICBkZXNjcmlwdGlvbjogIkRlbW9uc3RyYXRlcyBob3cgdG8gYnVpbGQgc2ltcGxlIHVuaXQgdGVzdHMgaW4gUiB1c2luZyB0aGUKICAgICAgICAgICAgICAgICd0ZXN0dGhhdCcgcGFja2FnZS4gRXhwbGFpbnMgY29tbW9uIHVuaXQgYW5kIHN5c3RlbSB0ZXN0aW5nCiAgICAgICAgICAgICAgICBwcmluY2lwbGVzLiBTaG93cyBob3cgdG8gdGVzdCBkYXRhYmFzZSBjb2RlLiIKZGF0ZTogIjxzbWFsbD5gciBTeXMuRGF0ZSgpYDwvc21hbGw+IgphdXRob3I6ICI8c21hbGw+TWFydGluIFNjaGVkbGJhdWVyPC9zbWFsbD4iCmVtYWlsOiAibS5zY2hlZGxiYXVlckBuZXUuZWR1IgphZmZpbGl0YXRpb246ICJOb3J0aGVhc3Rlcm4gVW5pdmVyc2l0eSIKb3V0cHV0OiAKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29sbGFwc2VkOiBmYWxzZQogICAgbnVtYmVyX3NlY3Rpb25zOiBmYWxzZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgdGhlbWU6IHNwYWNlbGFiCiAgICBoaWdobGlnaHQ6IHRhbmdvCi0tLQoKLS0tCnRpdGxlOiAiPHNtYWxsPmByIHBhcmFtcyRjYXRlZ29yeWAuYHIgcGFyYW1zJG51bWJlcmA8L3NtYWxsPjxici8+PHNwYW4gc3R5bGU9J2NvbG9yOiAjMkU0MDUzOyBmb250LXNpemU6IDAuOWVtJz5gciBybWFya2Rvd246Om1ldGFkYXRhJHRpdGxlYDwvc3Bhbj4iCi0tLQoKYGBge3IgY29kZT14ZnVuOjpyZWFkX3V0ZjgocGFzdGUwKGhlcmU6OmhlcmUoKSwnL1IvX2luc2VydDJEQi5SJykpLCBpbmNsdWRlID0gRkFMU0V9CmBgYAoKIyMgSW50cm9kdWN0aW9uCgpUZXN0aW5nIGlzIGFuIGludGVncmFsIHBhcnQgb2YgdGhlIHNvZnR3YXJlIGRldmVsb3BtZW50IGxpZmVjeWNsZSwgZW5zdXJpbmcgdGhhdCBzb2Z0d2FyZSBhcHBsaWNhdGlvbnMgYW5kIHRoZWlyIGluZGl2aWR1YWwgY29tcG9uZW50cyBmdW5jdGlvbiBjb3JyZWN0bHkgYW5kIG1lZXQgc3BlY2lmaWVkIHJlcXVpcmVtZW50cy4gVmFyaW91cyB0eXBlcyBvZiB0ZXN0aW5nIGFyZSB1c2VkIHRvIHZhbGlkYXRlIGRpZmZlcmVudCBhc3BlY3RzIG9mIHRoZSBhcHBsaWNhdGlvbiwgZnJvbSBpbmRpdmlkdWFsIHVuaXRzIG9mIGNvZGUsIHN1Y2ggYXMgZnVuY3Rpb25zIG9yIGNsYXNzZXMsIHRvIHRoZSBpbnRlZ3JhdGVkIHN5c3RlbSBhbmQgZXh0ZXJuYWwgY29tcG9uZW50cy4KCiMjIFRlc3QtdG8tUGFzcyB2cyBUZXN0LXRvLUZhaWwKClR3byBmdW5kYW1lbnRhbCBhcHByb2FjaGVzIHRvIHRlc3RpbmcgYXJlICp0ZXN0LXRvLXBhc3MqIGFuZCAqdGVzdC10by1mYWlsKi4gVW5kZXJzdGFuZGluZyB0aGVzZSBhcHByb2FjaGVzIGhlbHBzIGluIGRlc2lnbmluZyBtb3JlIHJvYnVzdCBhbmQgY29tcHJlaGVuc2l2ZSB0ZXN0IGNhc2VzLgoKKipUZXN0LXRvLVBhc3MqKiBjb25maXJtcyB0aGF0IHRoZSBzb2Z0d2FyZSB3b3JrcyBhcyBleHBlY3RlZCB1bmRlciBub3JtYWwgY29uZGl0aW9ucy4gVGhlIGdlbmVyYWwgYXBwcm9hY2ggaXMgdG8gd3JpdGUgdGVzdHMgd2l0aCB2YWxpZCBpbnB1dHMgdG8gdmVyaWZ5IHRoYXQgdGhlIHNvZnR3YXJlIHBlcmZvcm1zIHRoZSBkZXNpcmVkIG9wZXJhdGlvbnMgY29ycmVjdGx5LiBUaGUgZm9jdXMgaXMgb24gdHlwaWNhbCB1c2FnZSBzY2VuYXJpb3MgdG8gZW5zdXJlcyB0aGF0IHRoZSBzb2Z0d2FyZSBtZWV0cyBpdHMgZnVuY3Rpb25hbCByZXF1aXJlbWVudHMgd2hpY2ggaGVscHMgdmVyaWZ5IHRoZSBjb3JyZWN0bmVzcyBvZiB0aGUgbWFpbiBmdW5jdGlvbmFsaXR5LiBIb3dldmVyLCB0aGVzZSB0ZXN0cyBtYXkgbm90IHVuY292ZXIgZWRnZSBjYXNlcyBvciByYXJlIGNvbmRpdGlvbnMgYW5kIHRodXMgYXJlIHByaW1hcmlseSBmb2N1c2VkIG9uIGNvbmZpcm1pbmcgcG9zaXRpdmUgc2NlbmFyaW9zLgoKT24gdGhlIG90aGVyIGhhbmQsICoqVGVzdC10by1GYWlsKiogdGVzdGluZyBpZGVudGlmaWVzIHNjZW5hcmlvcyB3aGVyZSB0aGUgc29mdHdhcmUgbWlnaHQgZmFpbCBhbmQgZW5zdXJlIGl0IGhhbmRsZXMgdGhlbSBncmFjZWZ1bGx5LiBUaGUgaWRlYSBpcyB0byB3cml0ZSB0ZXN0cyB3aXRoIGludmFsaWQgb3IgdW5leHBlY3RlZCBpbnB1dHMgdG8gY2hlY2sgaG93IHRoZSBzb2Z0d2FyZSBoYW5kbGVzIGVycm9ycyBhbmQgZWRnZSBjYXNlcyBhbmQgd2hldGhlciB0aGUgc3lzdGVtJ3Mgb3IgYXBwbGljYXRpb24ncyBwZXJmb3JtYW5jZSBncmFjZWZ1bGx5IGRlZ3JhZGVzIC0tIG9yIHNpbXBseSBjcmFzaGVzLiBUaHVzIHRoZSBmb2N1cyBpcyBvbiByb2J1c3RuZXNzIGFuZCBlcnJvciBoYW5kbGluZyB0byBlbnN1cmUgdGhhdCB0aGUgc29mdHdhcmUgZmFpbHMgaW4gYSBjb250cm9sbGVkIG1hbm5lciBhbmQgcHJvdmlkZXMgbWVhbmluZ2Z1bCBlcnJvciBtZXNzYWdlcyBvciBoYW5kbGVzIGV4Y2VwdGlvbnMgYXBwcm9wcmlhdGVseS4gVGhlIG1haW4gYmVuZWZpdHMgb2YgdGVzdC10by1mYWlsIGluY2x1ZGUgaGVscGluZyB0byBpZGVudGlmeSBhbmQgZml4IHBvdGVudGlhbCB3ZWFrbmVzc2VzIGluIHRoZSBzb2Z0d2FyZSwgZW5zdXJlIHJvYnVzdG5lc3MgYnkgaGFuZGxpbmcgZWRnZSBjYXNlcyBhbmQgdW5leHBlY3RlZCBpbnB1dHMsIGFuZCBpbXByb3ZlIHRoZSByZWxpYWJpbGl0eSBvZiB0aGUgc29mdHdhcmUgYnkgdGVzdGluZyBob3cgaXQgZmFpbHMuIE5hdHVyYWxseSwgaXQgbWF5IG5vdCBjb3ZlciBhbGwgdHlwaWNhbCB1c2FnZSBzY2VuYXJpb3MgYW5kIHJlcXVpcmVzIHN1YnN0YW50aWFsIGVmZm9ydCB0byBpZGVudGlmeSBhbmQgY3JlYXRlIGVkZ2UgY2FzZSB0ZXN0cy4KCkJvdGggdGVzdC10by1wYXNzIGFuZCB0ZXN0LXRvLWZhaWwgYXJlIGVzc2VudGlhbCBjb21wb25lbnRzIG9mIGEgcm9idXN0IHRlc3Rpbmcgc3RyYXRlZ3kuIFdoaWxlIHRlc3QtdG8tcGFzcyBlbnN1cmVzIHRoYXQgdGhlIHNvZnR3YXJlIG1lZXRzIGl0cyBmdW5jdGlvbmFsIHJlcXVpcmVtZW50cywgdGVzdC10by1mYWlsIGlkZW50aWZpZXMgcG90ZW50aWFsIHdlYWtuZXNzZXMgYW5kIGltcHJvdmVzIHRoZSBzb2Z0d2FyZSdzIHJvYnVzdG5lc3MuIEJ5IGludGVncmF0aW5nIGJvdGggYXBwcm9hY2hlcywgdGhlIHNvZnR3YXJlIGRldmVsb3BlciBjYW4gZGV2ZWxvcCBtb3JlIHJlbGlhYmxlIGFuZCByZXNpbGllbnQgc29mdHdhcmUsIHVsdGltYXRlbHkgZW5oYW5jaW5nIHVzZXIgc2F0aXNmYWN0aW9uIGFuZCByZWR1Y2luZyB0aGUgcmlzayBvZiBmYWlsdXJlcyBpbiBwcm9kdWN0aW9uLgoKIyMgVGVzdGluZyBXb3JrZmxvdwoKQSBjb21wcmVoZW5zaXZlIHRlc3Rpbmcgd29ya2Zsb3cgc2hvdWxkIGluY2x1ZGUgYm90aCB0ZXN0LXRvLXBhc3MgYW5kIHRlc3QtdG8tZmFpbCBhcHByb2FjaGVzIGFuZCBnZW5lcmFsbHkgcmVxdWlyZXMgdGhlIGZvbGxvd2luZyBwcm9jZXNzIHN0ZXBzOgoKMS4gICoqRGVmaW5lIENsZWFyIFJlcXVpcmVtZW50cyoqOiBDbGVhcmx5IGRlZmluZSB0aGUgZXhwZWN0ZWQgYmVoYXZpb3Igb2YgdGhlIHNvZnR3YXJlLCBpbmNsdWRpbmcgYm90aCBub3JtYWwgb3BlcmF0aW9ucyBhbmQgZXJyb3IgaGFuZGxpbmcuCgoyLiAgKipEZXZlbG9wIGEgVGVzdCBQbGFuKio6IENyZWF0ZSBhIHRlc3QgcGxhbiB0aGF0IG91dGxpbmVzIHdoaWNoIHNjZW5hcmlvcyB0byB0ZXN0LCBpbmNsdWRpbmcgYm90aCB0eXBpY2FsIHVzZSBjYXNlcyBhbmQgZWRnZSBjYXNlcy4KCjMuICAqKkF1dG9tYXRlIFRlc3RpbmcqKjogVXNlIGF1dG9tYXRlZCB0ZXN0aW5nIHRvb2xzIHRvIHJlZ3VsYXJseSBydW4gYm90aCB0ZXN0LXRvLXBhc3MgYW5kIHRlc3QtdG8tZmFpbCBzY2VuYXJpb3MsIGVuc3VyaW5nIGNvbnRpbnVvdXMgdmFsaWRhdGlvbiBvZiB0aGUgc29mdHdhcmUuCgo0LiAgKipQcmlvcml0aXplIENyaXRpY2FsIEZ1bmN0aW9ucyoqOiBGb2N1cyBvbiBjcml0aWNhbCBmdW5jdGlvbnMgYW5kIGhpZ2gtcmlzayBhcmVhcyBmaXJzdCwgZW5zdXJpbmcgdGhhdCB0aGV5IGFyZSB0aG9yb3VnaGx5IHRlc3RlZCB1bmRlciBib3RoIG5vcm1hbCBhbmQgZXhjZXB0aW9uYWwgY29uZGl0aW9ucy4KCjUuICAqKlJldmlldyBhbmQgUmVmYWN0b3IqKjogQ29udGludW91c2x5IHJldmlldyBhbmQgcmVmYWN0b3IgeW91ciB0ZXN0IGNhc2VzIGJhc2VkIG9uIG5ldyBpbnNpZ2h0cyBhbmQgY2hhbmdpbmcgcmVxdWlyZW1lbnRzLCBlbnN1cmluZyBjb21wcmVoZW5zaXZlIGNvdmVyYWdlLgoKIyMgVHlwZXMgb2YgVGVzdGluZwoKTW9zdCBzb2Z0d2FyZSBkZXZlbG9wbWVudCBvcmdhbml6YXRpb25zIHBlcmZvcm0gc2V2ZW4gZGlmZmVyZW50IGxldmVscyBvZiB0ZXN0aW5nLCBlYWNoIGVuc3VyaW5nIGEgZGlzdGluY3QgZGVncmVlIG9mIGZ1bmN0aW9uYWxpdHkuCgoxLiAgKipVbml0IFRlc3RpbmcqKgoyLiAgKipJbnRlZ3JhdGlvbiBUZXN0aW5nKioKMy4gICoqU3lzdGVtIFRlc3RpbmcqKgo0LiAgKipBY2NlcHRhbmNlIFRlc3RpbmcqKgo1LiAgKipQZXJmb3JtYW5jZSBUZXN0aW5nKioKNi4gICoqU2VjdXJpdHkgVGVzdGluZyoqCjcuICAqKlVzYWJpbGl0eSBUZXN0aW5nKioKCiMjIyBVbml0IFRlc3RpbmcKCioqT2JqZWN0aXZlKio6IFZlcmlmeSB0aGF0IGluZGl2aWR1YWwgdW5pdHMgb3IgY29tcG9uZW50cyBvZiB0aGUgc29mdHdhcmUgd29yayBhcyBpbnRlbmRlZC4KCioqSG93IHRvIFBlcmZvcm0qKjogLSBXcml0ZSB0ZXN0IGNhc2VzIGZvciBlYWNoIGZ1bmN0aW9uIG9yIG1ldGhvZCBpbiBpc29sYXRpb24uIC0gVXNlIGFzc2VydGlvbnMgdG8gY2hlY2sgaWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgZXhwZWN0ZWQgcmVzdWx0cyBmb3IgZ2l2ZW4gaW5wdXRzLiAtICoqVG9vbHMqKjogYEpVbml0YCBmb3IgSmF2YSwgYHB5dGVzdGAgZm9yIFB5dGhvbiwgYHRlc3R0aGF0YCBmb3IgUi4KCiMjIyBJbnRlZ3JhdGlvbiBUZXN0aW5nCgoqKk9iamVjdGl2ZSoqOiBFbnN1cmUgdGhhdCBkaWZmZXJlbnQgbW9kdWxlcyBvciBzZXJ2aWNlcyBpbiBhIHN5c3RlbSB3b3JrIHRvZ2V0aGVyIGFzIGV4cGVjdGVkLgoKKipIb3cgdG8gUGVyZm9ybSoqOiAtIFRlc3QgdGhlIGludGVyYWN0aW9uIGJldHdlZW4gaW50ZWdyYXRlZCBjb21wb25lbnRzLiAtIElkZW50aWZ5IGFuZCB0ZXN0IGNyaXRpY2FsIGludGVncmF0aW9uIHBvaW50cy4gLSAqKlRvb2xzKio6IGBKVW5pdGAgd2l0aCBTcHJpbmcgZm9yIEphdmEsIGBweXRlc3RgIGZvciBQeXRob24sIGB0ZXN0dGhhdGAgZm9yIFIuCgojIyMgU3lzdGVtIFRlc3RpbmcKCioqT2JqZWN0aXZlKio6IFZhbGlkYXRlIHRoZSBjb21wbGV0ZSBhbmQgZnVsbHkgaW50ZWdyYXRlZCBzb2Z0d2FyZSBwcm9kdWN0IHRvIGVuc3VyZSBpdCBtZWV0cyB0aGUgcmVxdWlyZW1lbnRzLiBDcmVhdGUgdXNlciBzdG9yaWVzIGFuZCBhY2NlcHRhbmNlIGNyaXRlcmlhIHRvIHZhbGlkYXRlIGlmIHRoZSBhcml0aG1ldGljIG9wZXJhdGlvbnMgZnVsZmlsbCB0aGUgYnVzaW5lc3MgbmVlZHMuCgoqKkhvdyB0byBQZXJmb3JtKio6IC0gQ29uZHVjdCBlbmQtdG8tZW5kIHRlc3Rpbmcgb2YgdGhlIGFwcGxpY2F0aW9uLiAtIFRlc3Qgc2NlbmFyaW9zIHRoYXQgcmVmbGVjdCByZWFsLXdvcmxkIHVzYWdlLiAtICoqVG9vbHMqKjogU2VsZW5pdW0gZm9yIHdlYiBhcHBsaWNhdGlvbnMsIFFUUC9VRlQgZm9yIGRlc2t0b3AgYXBwbGljYXRpb25zLgoKIyMjIEFjY2VwdGFuY2UgVGVzdGluZwoKKipPYmplY3RpdmUqKjogVmVyaWZ5IHRoYXQgdGhlIHNvZnR3YXJlIG1lZXRzIHRoZSBidXNpbmVzcyByZXF1aXJlbWVudHMgYW5kIGlzIHJlYWR5IGZvciBkZWxpdmVyeS4KCioqSG93IHRvIFBlcmZvcm0qKjogLSBDb25kdWN0ZWQgYnkgdGhlIGVuZC11c2VycyBvciB0ZXN0ZXJzLiAtIFVzZSBwcmVkZWZpbmVkIGFjY2VwdGFuY2UgY3JpdGVyaWEuIC0gKipUb29scyoqOiBDdWN1bWJlciwgRml0TmVzc2UuCgojIyMgUGVyZm9ybWFuY2UgVGVzdGluZwoKKipPYmplY3RpdmUqKjogRW5zdXJlIHRoZSBzb2Z0d2FyZSBwZXJmb3JtcyB3ZWxsIHVuZGVyIGV4cGVjdGVkIGxvYWQgY29uZGl0aW9ucyBhbmQgdGhhdCB0aHJvdWdocHV0IGFuZCByZXNwb25zZSB0aW1lIG1lZXQgbm9uLWZ1bmN0aW9uYWwgcXVhbGl0eS1vZi1zZXJ2aWNlIHJlcXVpcmVtZW50cy4KCioqSG93IHRvIFBlcmZvcm0qKjogLSBNZWFzdXJlIHJlc3BvbnNlIHRpbWUsIHRocm91Z2hwdXQsIGFuZCByZXNvdXJjZSB1dGlsaXphdGlvbi4gLSBDb25kdWN0IHN0cmVzcywgbG9hZCwgYW5kIHNjYWxhYmlsaXR5IHRlc3RzLiAtICoqVG9vbHMqKjogSk1ldGVyLCBMb2FkUnVubmVyLgoKIyMjIFNlY3VyaXR5IFRlc3RpbmcKCioqT2JqZWN0aXZlKio6IElkZW50aWZ5IHZ1bG5lcmFiaWxpdGllcyBhbmQgZW5zdXJlIHRoZSBzb2Z0d2FyZSBpcyBzZWN1cmUsIGZvciBleGFtcGxlIGNoZWNraW5nIGZvciBjb21tb24gdnVsbmVyYWJpbGl0aWVzIHN1Y2ggYXMgU1FMIEluamVjdGlvbiBBdHRhY2tzLCBEZW5pYWwgb2YgU2VydmljZSBBdHRhY2tzLCBhbmQgQnVmZmVyIE92ZXJmbG93IEF0dGFja3MuIEFsc28sIHZlcmlmaWVzIHRoYXQgaW5mb3JtYXRpb24gaXMga2VwdCBzZWN1cmUsIGVuY3J5cHRlZCwgYW5kIGNvbmZpZGVudGlhbC4KCioqSG93IHRvIFBlcmZvcm0qKjogLSBQZXJmb3JtIHBlbmV0cmF0aW9uIHRlc3RpbmcgYW5kIHZ1bG5lcmFiaWxpdHkgc2Nhbm5pbmcuIC0gVGVzdCBmb3IgY29tbW9uIHNlY3VyaXR5IGlzc3VlcyBsaWtlIFNRTCBpbmplY3Rpb24sIFhTUywgZXRjLiAtICoqVG9vbHMqKjogT1dBU1AgWkFQLCBCdXJwIFN1aXRlLgoKIyMjIFVzYWJpbGl0eSBUZXN0aW5nCgoqKk9iamVjdGl2ZSoqOiBWZXJpZnkgdGhhdCB0aGUgc29mdHdhcmUgaXMgdXNlci1mcmllbmRseSBhbmQgbWVldHMgdXNlciBleHBlcmllbmNlIHN0YW5kYXJkcy4gQ29tbW9ubHkgdXNlcyBvYnNlcnZhdGlvbiBhbmQgdGFzayBjb21wbGV0aW9uIHN0dWRpZXMuCgoqKkhvdyB0byBQZXJmb3JtKio6IC0gQ29uZHVjdCB0ZXN0cyB3aXRoIHJlYWwgdXNlcnMuIC0gR2F0aGVyIGZlZWRiYWNrIG9uIGVhc2Ugb2YgdXNlLCBpbnRlcmZhY2UgZGVzaWduLCBldGMuIC0gKipUb29scyoqOiBVc2VyVGVzdGluZy5jb20sIE1vcmFlLgoKIyMjIEJlc3QgUHJhY3RpY2VzCgoxLiAgKipBdXRvbWF0ZSBXaGVyZSBQb3NzaWJsZSoqOiBVc2UgYXV0b21hdGVkIHRlc3RpbmcgdG9vbHMgdG8gc2F2ZSB0aW1lIGFuZCByZWR1Y2UgaHVtYW4gZXJyb3IuCjIuICAqKlRlc3QgRWFybHkgYW5kIE9mdGVuKio6IEludGVncmF0ZSB0ZXN0aW5nIGludG8geW91ciBkZXZlbG9wbWVudCBwcm9jZXNzIGZyb20gdGhlIGJlZ2lubmluZy4KMy4gICoqVXNlIGEgVGVzdCBQbGFuKio6IERldmVsb3AgYSBjb21wcmVoZW5zaXZlIHRlc3QgcGxhbiB0aGF0IG91dGxpbmVzIHRlc3Rpbmcgc3RyYXRlZ2llcywgc2NvcGUsIHJlc291cmNlcywgYW5kIHNjaGVkdWxlLgo0LiAgKipQcmlvcml0aXplIFRlc3RzKio6IEZvY3VzIG9uIGNyaXRpY2FsIGZ1bmN0aW9uYWxpdGllcyBhbmQgaGlnaC1yaXNrIGFyZWFzLgo1LiAgKipSZXZpZXcgYW5kIFJlZmFjdG9yKio6IENvbnRpbnVvdXNseSByZXZpZXcgYW5kIGltcHJvdmUgeW91ciB0ZXN0IGNhc2VzIHRvIGFkYXB0IHRvIGNoYW5naW5nIHJlcXVpcmVtZW50cy4KCiMjIFRlc3QgQXV0b21hdGlvbiB3aXRoICoqdGVzdHRoYXQqKgoKVGVzdGluZyBpcyBhIGNydWNpYWwgcGFydCBvZiBzb2Z0d2FyZSBkZXZlbG9wbWVudCB0aGF0IGVuc3VyZXMgeW91ciBjb2RlIHdvcmtzIGNvcnJlY3RseS4gSW4gUiwgdGhlICoqdGVzdHRoYXQqKiBwYWNrYWdlIHByb3ZpZGVzIGEgcm9idXN0IGZyYW1ld29yayBmb3Igd3JpdGluZyBhbmQgcnVubmluZyB0ZXN0cy4gVGhpcyB0dXRvcmlhbCB3aWxsIGd1aWRlIHlvdSB0aHJvdWdoIHRoZSBjb25jZXB0cyBvZiB1bml0IGFuZCBzeXN0ZW0gdGVzdGluZyB1c2luZyB0aGUgZnJhbWV3b3JrIG9mIHRoZSAqKnRlc3R0aGF0KiogcGFja2FnZS4KCiMjIyBTZXR0aW5nIFVwIHRoZSBFbnZpcm9ubWVudAoKRmlyc3QsIHlvdSBuZWVkIHRvIGluc3RhbGwgdGhlICoqdGVzdHRoYXQqKiBwYWNrYWdlIGlmIHlvdSBoYXZlbid0IGFscmVhZHksIHVzaW5nIGVpdGhlciB0aGUgUiBjb2RlIGZyYWdtZW50IGJlbG93LCBvciBieSBpbnN0YWxsaW5nIGl0IHRocm91Z2ggeW91ciBJREUgKFJTdHVkaW8sIFBvc2l0LCBvciBWUyBDb2RlLCAqZXRjLiopOgoKYGBge3IgZWNobyA9IEYsIGV2YWwgPSBGLCB3YXJuaW5nPUYsIG1lc3NhZ2U9Rn0KaW5zdGFsbC5wYWNrYWdlcygidGVzdHRoYXQiKQpgYGAKCkluc3RhbGxhdGlvbiBpcyBvbmx5IG5lY2Vzc2FyeSBvbmNlLCBidXQgeW91IG5lZWQgdG8gbG9hZCB0aGUgcGFja2FnZSBpbnRvIHlvdXIgUiBzZXNzaW9uIGV2ZXJ5dGltZSB5b3Ugd2lzaCB0byB1c2UgaXQ6CgpgYGB7cn0KbGlicmFyeSh0ZXN0dGhhdCkKYGBgCgojIyMgVW5pdCBUZXN0aW5nCgpVbml0IHRlc3RpbmcgZm9jdXNlcyBvbiB0ZXN0aW5nIGluZGl2aWR1YWwgZnVuY3Rpb25zIG9yIGNvbXBvbmVudHMgb2YgeW91ciBjb2RlLiBUaGUgZ29hbCBpcyB0byB2ZXJpZnkgdGhhdCBlYWNoIGZ1bmN0aW9uIHBlcmZvcm1zIGFzIGV4cGVjdGVkLgoKIyMjIyBXcml0aW5nIFVuaXQgVGVzdHMKCkNvbnNpZGVyIGEgc2ltcGxlIGZ1bmN0aW9uIHRoYXQgYWRkcyB0d28gbnVtYmVyczoKCmBgYHtyfQphZGQgPC0gZnVuY3Rpb24oeCwgeSkgewogIHJldHVybih4ICsgeSkKfQpgYGAKClRvIHdyaXRlIGEgdW5pdCB0ZXN0IGZvciB0aGlzIGZ1bmN0aW9uLCBjcmVhdGUgYSBzZXBhcmF0ZSB0ZXN0IGZpbGUuIEJ5IGNvbnZlbnRpb24sIHRlc3QgZmlsZXMgYXJlIHBsYWNlZCBpbiBhICJ0ZXN0cy90ZXN0dGhhdCIgZGlyZWN0b3J5IHdpdGhpbiB5b3VyIHByb2plY3QgZm9sZGVyLiBMZXQncyBuYW1lIG91ciB0ZXN0IGZpbGUgKnRlc3QtYWRkLlIqLgoKSW4gKnRlc3QtYWRkLlIqLCB5b3Ugd291bGQgd3JpdGUgdGhlIGZvbGxvd2luZyB0ZXN0czoKCmBgYHtyfQojIFRFU1QgU0NSSVBUOiB0ZXN0LWFkZC5SCgpsaWJyYXJ5KHRlc3R0aGF0KQoKdGVzdF90aGF0KCJhZGRpdGlvbiB3b3JrcyIsIHsKICBleHBlY3RfZXF1YWwoYWRkKDEsIDEpLCAyKQogIGV4cGVjdF9lcXVhbChhZGQoLTEsIC0xKSwgLTIpCiAgZXhwZWN0X2VxdWFsKGFkZCgxLCAtMSksIDApCn0pCmBgYAoKSW4gdGhlIGFib3ZlIGNvZGUsIHRoZSBmdW5jdGlvbiBgdGVzdF90aGF0YCBkZWZpbmVzIGEgdGVzdCBibG9jaywgYW5kIGBleHBlY3RfZXF1YWxgIGNoZWNrcyBpZiB0aGUgZnVuY3Rpb24gb3V0cHV0IG1hdGNoZXMgdGhlIGV4cGVjdGVkIHJlc3VsdC4KCiMjIyMgUnVubmluZyBVbml0IFRlc3RzCgpZb3UgY2FuIHJ1biB0aGUgdGVzdHMgdXNpbmcgdGhlIGZvbGxvd2luZyBjb21tYW5kIChhc3N1bWluZyB0aGF0IHlvdSBoYXZlIHlvdXIgdGVzdHMgZGVmaW5lZCBpbiB0aGUgZm9sZGVyICp0ZXN0cy90ZXN0dGhhdCo6CgpgYGB7ciBldmFsPUZ9CnRlc3RfZGlyKCJ0ZXN0cy90ZXN0dGhhdCIpCmBgYAoKQWx0ZXJuYXRpdmVseSwgaWYgeW91IGFyZSB1c2luZyBSU3R1ZGlvL1Bvc2l0LCB5b3UgY2FuIHVzZSB0aGUgIkJ1aWxkIiBwYW5lIHRvIHJ1biBhbGwgdGVzdHMuIEluIGFkZGl0aW9uLCB5b3UgY2FuIHJ1biB0aGUgYWJvdmUgY29tbWFuZCBmcm9tIHRoZSBSIENvbnNvbGUgd2l0aGluIFJTdHVkaW8vUG9zaXQgd2hpY2ggd291bGQgYWxsb3cgeW91IHRvIGtlZXAgdGhlIHRlc3RpbmcgbWVjaGFuaXNtIG91dHNpZGUgeW91ciBwcm9ncmFtL3NjcmlwdCBjb2RlLgoKIyMjIFN5c3RlbSBUZXN0aW5nCgpTeXN0ZW0gdGVzdGluZywgYWxzbyBzb21ldGltZXMgcmVmZXJyZWQgdG8gYXMgaW50ZWdyYXRpb24gdGVzdGluZyAoZXZlbiB0aG91Z2ggaXQgaXMgbm90IHF1aXRlIHRoZSBzYW1lKSwgaW52b2x2ZXMgdGVzdGluZyB0aGUgY29tcGxldGUgc3lzdGVtIG9yIGFwcGxpY2F0aW9uLiBJdCBlbnN1cmVzIHRoYXQgZGlmZmVyZW50IHBhcnRzIG9mIHRoZSBhcHBsaWNhdGlvbiB3b3JrIHRvZ2V0aGVyIGFzIGV4cGVjdGVkLgoKIyMjIyBXcml0aW5nIFN5c3RlbSBUZXN0cwoKTGV0J3MgZXhwYW5kIG91ciBleGFtcGxlIHRvIGEgc21hbGwgc3lzdGVtIHRoYXQgcGVyZm9ybXMgYmFzaWMgYXJpdGhtZXRpYyBvcGVyYXRpb25zLiBXZSdsbCBjcmVhdGUgZnVuY3Rpb25zIGZvciBhZGRpdGlvbiwgc3VidHJhY3Rpb24sIG11bHRpcGxpY2F0aW9uLCBhbmQgZGl2aXNpb246CgpgYGB7cn0KYWRkIDwtIGZ1bmN0aW9uKHgsIHkpIHsKICByZXR1cm4oeCArIHkpCn0KCnN1YnRyYWN0IDwtIGZ1bmN0aW9uKHgsIHkpIHsKICByZXR1cm4oeCAtIHkpCn0KCm11bHRpcGx5IDwtIGZ1bmN0aW9uKHgsIHkpIHsKICByZXR1cm4oeCAqIHkpCn0KCmRpdmlkZSA8LSBmdW5jdGlvbih4LCB5KSB7CiAgaWYgKHkgPT0gMCkgewogICAgc3RvcCgiRGl2aXNpb24gYnkgemVybyBlcnJvciIpCiAgfQogIHJldHVybih4IC8geSkKfQpgYGAKCk5leHQsIHdlIHdpbGwgY3JlYXRlIGEgbmV3IHRlc3QgZmlsZSBpbiB0aGUgZm9sZGVyICp0ZXN0cy90ZXN0dGhhdCogbmFtZWQgKnRlc3QtYXJpdGhtZXRpYy5SKiBmb3Igc3lzdGVtIHRlc3RzOgoKYGBge3IgZXZhbD1GfQojIFRFU1QgRklMRTogdGVzdC1hcml0aG1ldGljLlIKCmxpYnJhcnkodGVzdHRoYXQpCgp0ZXN0X3RoYXQoImFyaXRobWV0aWMgb3BlcmF0aW9ucyB3b3JrIGNvcnJlY3RseSIsIHsKICBleHBlY3RfZXF1YWwoYWRkKDIsIDMpLCA1KQogIGV4cGVjdF9lcXVhbChzdWJ0cmFjdCg1LCAzKSwgMikKICBleHBlY3RfZXF1YWwobXVsdGlwbHkoMiwgMyksIDYpCiAgZXhwZWN0X2VxdWFsKGRpdmlkZSg2LCAzKSwgMikKICAKICAjIFRlc3RpbmcgZWRnZSBjYXNlcwogIGV4cGVjdF9lcnJvcihkaXZpZGUoMSwgMCksICJEaXZpc2lvbiBieSB6ZXJvIGVycm9yIikKfSkKYGBgCgpJbiB0aGlzIHRlc3QsIHdlIGFyZSBjaGVja2luZyB0aGUgY29ycmVjdG5lc3Mgb2YgYWxsIGFyaXRobWV0aWMgZnVuY3Rpb25zIHRvZ2V0aGVyLCBpbmNsdWRpbmcgaGFuZGxpbmcgZWRnZSBjYXNlcyBsaWtlIGRpdmlzaW9uIGJ5IHplcm8uCgojIyMjIFJ1bm5pbmcgU3lzdGVtIFRlc3RzCgpSdW4gdGhlIHRlc3RzIHVzaW5nIHRoZSBzYW1lIGNvbW1hbmQgYXMgZm9yIHVuaXQgdGVzdHMgKGFnYWluLCBhc3N1bWluZyB0aGF0IHRoZSBhYm92ZSB0ZXN0IGNvZGUgZXhpc3RzIGluIHRoZSBmb2xkZXIpOgoKYGBge3J9CnRlc3RfZGlyKCJ0ZXN0cy90ZXN0dGhhdCIpCmBgYAoKTm90ZSB0aGF0IHRoaXMgY29tbWFuZCBydW5zICoqYWxsIHRlc3RzKiogaW4gdGhlIGZvbGRlciAqdGVzdHMvdGVzdHRoYXQqLiBUaGlzIGFsbG93cyB0ZXN0cyB0byBiZSBzZWdtZW50ZWQgYW5kIG1vcmUgZWFzaWx5IG1hbmFnZWQuCgojIyMgQmVzdCBQcmFjdGljZXMgZm9yIFRlc3RpbmcgaW4gUgoKMS4gICoqV3JpdGUgVGVzdHMgRWFybHkqKjogRGV2ZWxvcCB5b3VyIHRlc3RzIGFsb25nc2lkZSB5b3VyIGNvZGUgdG8gY2F0Y2ggaXNzdWVzIGVhcmx5LiBTb21lIHNvZnR3YXJlIGRldmVsb3BtZW50IGZyYW1ld29ya3MgcmVxdWlyZSB0ZXN0cyB0byBiZSB3cml0dGVuIGJlZm9yZSB0aGUgY29kZSBpcyBjcmVhdGVkIHRvIGVuc3VyZSB0aGF0IHRoZSBjb2RlIG1hdGNoZXMgdGhlIHJlcXVpcmVtZW50czogd3JpdGUgYWdhaW5zdCB0ZXN0cy4KMi4gICoqVGVzdCBFZGdlIENhc2VzKio6IEFsd2F5cyBjb25zaWRlciBhbmQgdGVzdCBmb3IgZWRnZSBjYXNlcyBhbmQgdW51c3VhbCBpbnB1dHMsIGVzcGVjaWFsbHkgY2hlY2tpbmcgYm91bmRhcnkgY29uZGl0aW9ucy4gTW9zdCBlcnJvcnMgb2NjdXIgb24gYm91bmRhcmllcywgKmUuZy4qLCBpZiBhIG51bWJlciBpcyBzdXBwb3NlZCB0byBiZSAxMCBvciBtb3JlLCB0aGVuIHRlc3QgZm9yIDkgKGZhaWwpIGFuZCAxMCAocGFzcykuCjMuICAqKktlZXAgVGVzdHMgU21hbGwgYW5kIEZvY3VzZWQqKjogRWFjaCB0ZXN0IHNob3VsZCBmb2N1cyBvbiBhIHNpbmdsZSBhc3BlY3Qgb2YgdGhlIGZ1bmN0aW9uJ3MgYmVoYXZpb3IuCjQuICAqKlVzZSBEZXNjcmlwdGl2ZSBOYW1lcyoqOiBVc2UgZGVzY3JpcHRpdmUgbmFtZXMgZm9yIHlvdXIgdGVzdCBjYXNlcyB0byBtYWtlIGl0IGNsZWFyIHdoYXQgaXMgYmVpbmcgdGVzdGVkLgo1LiAgKipBdXRvbWF0ZSBUZXN0aW5nKio6IEludGVncmF0ZSB5b3VyIHRlc3RzIGludG8geW91ciBkZXZlbG9wbWVudCB3b3JrZmxvdyB0byBydW4gdGhlbSBhdXRvbWF0aWNhbGx5LgoKIyMgVGVzdGluZyBTaWRlIEVmZmVjdHMKCiMjIyBTaWRlIEVmZmVjdHMgaW4gUHJvZ3JhbW1pbmcKCkluIHByb2dyYW1taW5nLCBhIHNpZGUgZWZmZWN0IG9jY3VycyB3aGVuIGEgZnVuY3Rpb24gb3IgZXhwcmVzc2lvbiBtb2RpZmllcyBzb21lIHN0YXRlIG9yIGludGVyYWN0cyB3aXRoIHRoZSBleHRlcm5hbCB3b3JsZCBpbiB3YXlzIGJleW9uZCByZXR1cm5pbmcgYSB2YWx1ZS4gU2lkZSBlZmZlY3RzIGNhbiBpbmNsdWRlIGFsdGVyaW5nIGEgdmFyaWFibGUsIG1vZGlmeWluZyBhIGRhdGEgc3RydWN0dXJlLCB3cml0aW5nIHRvIGEgZmlsZSwgd3JpdGluZyB0byBhIGRhdGFiYXNlLCBzZW5kaW5nIGEgbWVzc2FnZSB0byBhbm90aGVyIHByb2Nlc3MsIG9yIGNoYW5naW5nIHRoZSBzdGF0ZSBvZiB0aGUgdXNlciBpbnRlcmZhY2UuCgpUaGVyZSBhcmUgc2V2ZXJhbCBjaGFyYWN0ZXJpc3RpY3Mgb2Ygc2lkZSBlZmZlY3RzLCBpbmNsdWRpbmcKCjEuICAqKk1vZGlmeWluZyBWYXJpYWJsZXMqKjogQ2hhbmdpbmcgdGhlIHZhbHVlIG9mIHZhcmlhYmxlcyB0aGF0IGV4aXN0IG91dHNpZGUgdGhlIGZ1bmN0aW9uJ3MgbG9jYWwgc2NvcGUuCjIuICAqKkkvTyBPcGVyYXRpb25zKio6IFJlYWRpbmcgZnJvbSBvciB3cml0aW5nIHRvIGV4dGVybmFsIHNvdXJjZXMgbGlrZSBmaWxlcywgZGF0YWJhc2VzLCBvciBuZXR3b3JrIHNvY2tldHMuCjMuICAqKlN0YXRlIENoYW5nZXMqKjogTW9kaWZ5aW5nIHRoZSBzdGF0ZSBvZiBvYmplY3RzIG9yIGRhdGEgc3RydWN0dXJlcyBpbiB3YXlzIHRoYXQgcGVyc2lzdCBiZXlvbmQgdGhlIGZ1bmN0aW9uIGNhbGwuCjQuICAqKkludGVyYWN0aW9uIHdpdGggRXh0ZXJuYWwgU3lzdGVtcyoqOiBDYWxsaW5nIGV4dGVybmFsIEFQSXMgb3IgaW50ZXJhY3Rpbmcgd2l0aCBoYXJkd2FyZSBjb21wb25lbnRzLgoKQ29uc2lkZXIgYSBmdW5jdGlvbiB0aGF0IGluY3JlbWVudHMgYSBnbG9iYWwgdmFyaWFibGU6CgpgYGAgcgpjb3VudGVyIDwtIDAKCmluY3JlbWVudF9jb3VudGVyIDwtIGZ1bmN0aW9uKCkgewogIGNvdW50ZXIgPDwtIGNvdW50ZXIgKyAxCn0KYGBgCgpIZXJlLCBgaW5jcmVtZW50X2NvdW50ZXJgIG1vZGlmaWVzIHRoZSBnbG9iYWwgdmFyaWFibGUgYGNvdW50ZXJgLCBjYXVzaW5nIGEgc2lkZSBlZmZlY3QuCgpBbm90aGVyIGV4YW1wbGUgaXMgd2hlbiBhIGZ1bmN0aW9uIHdyaXRlcyB0byBhIGZpbGU6CgpgYGAgcgp3cml0ZV90b19maWxlIDwtIGZ1bmN0aW9uKHRleHQpIHsKICB3cml0ZSh0ZXh0LCBmaWxlID0gIm91dHB1dC50eHQiKQp9CmBgYAoKV3JpdGluZyB0byBhIGZpbGUgaXMgYSBzaWRlIGVmZmVjdCBiZWNhdXNlIGl0IGNoYW5nZXMgdGhlIHN0YXRlIG9mIHRoZSBmaWxlIHN5c3RlbS4KCiMjIyBGdW5jdGlvbmFsIFByb2dyYW1taW5nCgpJbiBmdW5jdGlvbmFsIHByb2dyYW1taW5nLCBzaWRlIGVmZmVjdHMgYXJlIG1pbmltaXplZCBvciBlbGltaW5hdGVkIHRvIGVuc3VyZSBmdW5jdGlvbnMgYXJlIHB1cmUuIEEgcHVyZSBmdW5jdGlvbiBpcyBvbmUgdGhhdCwgZ2l2ZW4gdGhlIHNhbWUgaW5wdXQsIGFsd2F5cyByZXR1cm5zIHRoZSBzYW1lIG91dHB1dCBhbmQgZG9lcyBub3QgY2F1c2UgYW55IHNpZGUgZWZmZWN0cy4KCioqRXhhbXBsZSBvZiBhIFB1cmUgRnVuY3Rpb24qKjoKCmBgYCByCmFkZCA8LSBmdW5jdGlvbih4LCB5KSB7CiAgcmV0dXJuKHggKyB5KQp9CmBgYAoKVGhpcyBmdW5jdGlvbiBpcyBwdXJlIGJlY2F1c2UgaXQgZG9lcyBub3QgbW9kaWZ5IGFueSBzdGF0ZSBvciBpbnRlcmFjdCB3aXRoIHRoZSBvdXRzaWRlIHdvcmxkLgoKIyMjIFByYWN0aWNhbCBTaWRlIEVmZmVjdHMKCkludGVyYWN0aW9ucyB3aXRoIHRoZSBvdXRzaWRlIHdvcmxkIChlLmcuLCB1c2VyIGlucHV0LCBmaWxlIG9wZXJhdGlvbnMpIGFyZSBpbmhlcmVudGx5IHNpZGUgZWZmZWN0cyBhbmQgYXJlIGVzc2VudGlhbCBmb3IgcmVhbC13b3JsZCBhcHBsaWNhdGlvbnMuIFRoZXkgd291bGQgbm90IGJlIHBvc3NpYmxlIHRvIGJ1aWxkIHdpdGhvdXQgc2lkZSBlZmZlY3RzLiBTaWRlIGVmZmVjdHMgY2FuIGJlIHVzZWZ1bCBmb3IgbWFuYWdpbmcgc3RhdGUgYW5kIGNvbnRyb2xsaW5nIHByb2dyYW0gZmxvdy4KCkhvd2V2ZXIsIGZ1bmN0aW9ucyB3aXRoIHNpZGUgZWZmZWN0cyBhcmUgbW9yZSBjaGFsbGVuZ2luZyB0byB0ZXN0IGJlY2F1c2UgdGhlaXIgYmVoYXZpb3IgY2FuIGRlcGVuZCBvbiBleHRlcm5hbCBzdGF0ZS4gSW4gYWRkaXRpb24sIHNpZGUgZWZmZWN0cyBjYW4gaW50cm9kdWNlIGRlZmVjdHMgKGJ1Z3MpIHRoYXQgYXJlIGRpZmZpY3VsdCB0byB0cmFjZSwgZXNwZWNpYWxseSBpbiBsYXJnZSBjb2RlYmFzZXMuIENvbnNlcXVlbnRseSwgZnVuY3Rpb25zIHdpdGggc2lkZSBlZmZlY3RzIGFyZSBsZXNzIHByZWRpY3RhYmxlLCBhcyB0aGV5IG1heSBiZWhhdmUgZGlmZmVyZW50bHkgYmFzZWQgb24gZXh0ZXJuYWwgY29uZGl0aW9ucy4KCkluIHByYWN0aWNlLCB3aGlsZSB3ZSBvZnRlbiBuZWVkIHNpZGUgZWZmZWN0LCBpdCBpcyBhZHZpc2FibGUgdG8gbWFuYWdlIHNpZGUgZWZmZWN0cyBlZmZlY3RpdmVseSBhbmQgdG8gbWluaW1pemUgdGhlbSBhcyBtdWNoIGFzIGZlYXNpYmxlLiBVc2UgcHVyZSBmdW5jdGlvbnMgd2hlcmV2ZXIgcG9zc2libGUgYW5kIGxpbWl0IHNpZGUgZWZmZWN0cyB0byBzcGVjaWZpYyBwYXJ0cyBvZiB0aGUgY29kZS4gRW5jYXBzdWxhdGUgc2lkZSBlZmZlY3RzIHdpdGhpbiB3ZWxsLWRlZmluZWQgYm91bmRhcmllcywgc3VjaCBhcyBzcGVjaWZpYyBtb2R1bGVzLCBjbGFzc2VzLCBvciBsYXllcnMgb2YgdGhlIGFwcGxpY2F0aW9uLiBQcmVmZXIgaW1tdXRhYmxlIGRhdGEgc3RydWN0dXJlcyB0aGF0IGRvIG5vdCBjaGFuZ2Ugc3RhdGUgYWZ0ZXIgY3JlYXRpb24uIEFuZCwgZmluYWxseSwgaXNvbGF0ZSBzaWRlIGVmZmVjdHMgaW4gdGVzdHMsIHVzaW5nIHRlY2huaXF1ZXMgbGlrZSBtb2NraW5nIHRvIHNpbXVsYXRlIGludGVyYWN0aW9ucyB3aXRoIGV4dGVybmFsIHN5c3RlbXMuCgojIyBUZXN0aW5nIERhdGFiYXNlIENvZGUKCk1vZGlmaWNhdGlvbnMgb2YgZGF0YWJhc2VzIHRocm91Z2ggU1FMIHN0YXRlbWVudHMgb3IgdHJpZ2dlcnMgaXMgYSB0eXBlIG9mIHNpZGUgZWZmZWN0LiBUbyB0ZXN0IFNRTCBjb2RlIGFuZCB0cmlnZ2VycyB1c2luZyB0aGUgKip0ZXN0dGhhdCoqIHBhY2thZ2UsIHdlIG5lZWQgdG8gd3JpdGUgZnVuY3Rpb25zIHRoYXQgaW50ZXJhY3Qgd2l0aCB0aGUgZGF0YWJhc2UgYW5kIHBlcmZvcm0gdGhlIHJlcXVpcmVkIGNoZWNrcy4KCkxldCdzIHdhbGsgdGhyb3VnaCBhbiBleGFtcGxlIHVzaW5nIFNRTGl0ZS4gVGhlIHN0ZXBzIGFyZSBzaG93biBiZWxvdwoKIyMjIDEuICoqQ3JlYXRpbmcgYSBUZXN0IEVudmlyb25tZW50KioKCkNyZWF0ZSBhIHRlbXBvcmFyeSBTUUxpdGUgZGF0YWJhc2UsIHNldCB1cCB0aGUgbmVjZXNzYXJ5IHRhYmxlcyBhbmQgdHJpZ2dlcnMsIGFuZCBwb3B1bGF0ZSB0aGUgZGF0YWJhc2Ugd2l0aCBzeW50aGV0aWMgc2FtcGxlIGRhdGEuIEluIHRoZSBleGFtcGxlIGJlbG93LCB3ZSB1c2UgdGhlIHNwZWNpYWwgZGF0YWJhc2UgbmFtZSAiOm1lbW9yeToiIHdoaWNoIGNyZWF0ZXMgYSBTUUxpdGUgZGF0YWJhc2UgaW4gbWVtb3J5IHJhdGhlciB0aGFuIGluIHRoZSBmaWxlIHN5c3RlbS4gVGhlIGZ1bmN0aW9uIGBkYkV4ZWN1dGUoKWAgcmV0dXJucyBhIHN0YXR1cyBvZiAqMCogd2hlbiB0aGUgU1FMIGNvZGUgd2FzIGV4ZWN1dGVkIGNvcnJlY3RseS4gV2UgYXJlIG9taXR0aW5nIHRoZSBjaGVja3MgaW4gdGhlIGNvZGUgYmVsb3cgZm9yIGJyZXZpdHkuCgpgYGB7cn0KbGlicmFyeShSU1FMaXRlKQoKIyBDcmVhdGUgYSB0ZW1wb3JhcnkgaW4tbWVtb3ByeSBTUUxpdGUgZGF0YWJhc2UKY29uIDwtIGRiQ29ubmVjdChSU1FMaXRlOjpTUUxpdGUoKSwgIjptZW1vcnk6IikKCiMgQ3JlYXRlIHRhYmxlcwpzIDwtIGRiRXhlY3V0ZShjb24sIHBhc3RlMCgiQ1JFQVRFIFRBQkxFIHVzZXJzICgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiICBpZCBJTlRFR0VSIFBSSU1BUlkgS0VZLCAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiICBuYW1lIFRFWFQsICIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICIgIGxhc3RfdXBkYXRlZCBURVhUKSIpKQpzIDwtIGRiRXhlY3V0ZShjb24sIHBhc3RlMCgiQ1JFQVRFIFRBQkxFIG9yZGVycyAoIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIiAgb3JkZXJfaWQgSU5URUdFUiBQUklNQVJZIEtFWSwgIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIiAgdXNlcl9pZCBJTlRFR0VSLCAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiICBzdGF0dXMgVEVYVCwgIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIiAgRk9SRUlHTiBLRVkgKHVzZXJfaWQpIFJFRkVSRU5DRVMgdXNlcnMoaWQpKSIpKQpzIDwtIGRiRXhlY3V0ZShjb24sICJDUkVBVEUgVEFCTEUgYXVkaXRfbG9nIChsb2dfaWQgSU5URUdFUiBQUklNQVJZIEtFWSwgdXNlcl9pZCBJTlRFR0VSLCBhY3Rpb24gVEVYVCkiKQoKIyBDcmVhdGUgYSB0cmlnZ2VyCnMgPC0gZGJFeGVjdXRlKGNvbiwgIgogIENSRUFURSBUUklHR0VSIHVwZGF0ZV90aW1lc3RhbXAKICBBRlRFUiBVUERBVEUgT04gdXNlcnMKICBGT1IgRUFDSCBST1cKICBCRUdJTgogICAgVVBEQVRFIHVzZXJzIFNFVCBsYXN0X3VwZGF0ZWQgPSBDVVJSRU5UX1RJTUVTVEFNUCBXSEVSRSBpZCA9IE5FVy5pZDsKICAgIElOU0VSVCBJTlRPIGF1ZGl0X2xvZyAodXNlcl9pZCwgYWN0aW9uKSBWQUxVRVMgKE5FVy5pZCwgJ3VwZGF0ZWQnKTsKICBFTkQKIikKYGBgCgojIyMgMi4gKipXcml0aW5nIFRlc3RzIFVzaW5nKiogdGVzdHRoYXRcKlwqCgpOZXh0LCB3ZSB3cml0ZSB0ZXN0IGNhc2VzIGZvciB1bml0IHRlc3RpbmcsIGludGVncmF0aW9uIHRlc3RpbmcsIGFuZCBkYXRhIGludGVncml0eSB0ZXN0aW5nLgoKIyMjIyBVbml0IFRlc3RpbmcKCmBgYHtyfQpsaWJyYXJ5KHRlc3R0aGF0KQoKdGVzdF90aGF0KCJ0cmlnZ2VyIHVwZGF0ZXMgdGltZXN0YW1wIiwgewogICMgSW5zZXJ0IGEgdGVzdCByZWNvcmQKICBkYkV4ZWN1dGUoY29uLCAiSU5TRVJUIElOVE8gdXNlcnMgKGlkLCBuYW1lLCBsYXN0X3VwZGF0ZWQpIFZBTFVFUyAoMSwgJ0FsaWNlJywgJzIwMjMtMDEtMDEgMDA6MDA6MDAnKSIpCgogICMgVXBkYXRlIHRoZSB0ZXN0IHJlY29yZAogIGRiRXhlY3V0ZShjb24sICJVUERBVEUgdXNlcnMgU0VUIG5hbWUgPSAnQWxpY2UgVXBkYXRlZCcgV0hFUkUgaWQgPSAxIikKCiAgIyBDaGVjayBpZiB0aGUgdHJpZ2dlciB1cGRhdGVkIHRoZSB0aW1lc3RhbXAKICByZXN1bHQgPC0gZGJHZXRRdWVyeShjb24sICJTRUxFQ1QgbGFzdF91cGRhdGVkIEZST00gdXNlcnMgV0hFUkUgaWQgPSAxIikKICBleHBlY3RfZmFsc2UocmVzdWx0JGxhc3RfdXBkYXRlZCA9PSAnMjAyMy0wMS0wMSAwMDowMDowMCcpCn0pCmBgYAoKIyMjIyBJbnRlZ3JhdGlvbiBUZXN0aW5nCgpgYGB7cn0KdGVzdF90aGF0KCJpbnRlZ3JhdGlvbiBvZiB1c2VycyBhbmQgYXVkaXRfbG9nIiwgewogICMgSW5zZXJ0IGEgdGVzdCByZWNvcmQKICBkYkV4ZWN1dGUoY29uLCAiSU5TRVJUIElOVE8gdXNlcnMgKGlkLCBuYW1lKSBWQUxVRVMgKDIsICdCb2InKSIpCgogICMgVXBkYXRlIHRoZSB0ZXN0IHJlY29yZAogIGRiRXhlY3V0ZShjb24sICJVUERBVEUgdXNlcnMgU0VUIG5hbWUgPSAnQm9iIFVwZGF0ZWQnIFdIRVJFIGlkID0gMiIpCgogICMgQ2hlY2sgaWYgdGhlIHRyaWdnZXIgaW5zZXJ0ZWQgaW50byB0aGUgYXVkaXRfbG9nCiAgcmVzdWx0IDwtIGRiR2V0UXVlcnkoY29uLCAiU0VMRUNUICogRlJPTSBhdWRpdF9sb2cgV0hFUkUgdXNlcl9pZCA9IDIiKQogIGV4cGVjdF9lcXVhbChucm93KHJlc3VsdCksIDEpCiAgZXhwZWN0X2VxdWFsKHJlc3VsdCRhY3Rpb24sICd1cGRhdGVkJykKfSkKYGBgCgojIyMjIERhdGEgSW50ZWdyaXR5IFRlc3RpbmcKCmBgYHtyIGV2YWw9Rn0KdGVzdF90aGF0KCJmb3JlaWduIGtleSBjb25zdHJhaW50IHByZXZlbnRzIGRlbGV0aW9uIiwgewogICMgSW5zZXJ0IHRlc3QgcmVjb3JkcwogIGRiRXhlY3V0ZShjb24sICJJTlNFUlQgSU5UTyB1c2VycyAoaWQsIG5hbWUpIFZBTFVFUyAoMywgJ0NoYXJsaWUnKSIpCiAgZGJFeGVjdXRlKGNvbiwgIklOU0VSVCBJTlRPIG9yZGVycyAob3JkZXJfaWQsIHVzZXJfaWQsIHN0YXR1cykgVkFMVUVTICgxLCAzLCAncGVuZGluZycpIikKCiAgIyBBdHRlbXB0IHRvIGRlbGV0ZSB0aGUgdXNlciAoc2hvdWxkIGZhaWwgZHVlIHRvIGZvcmVpZ24ga2V5IGNvbnN0cmFpbnQpCiAgZXhwZWN0X2Vycm9yKGRiRXhlY3V0ZShjb24sICJERUxFVEUgRlJPTSB1c2VycyBXSEVSRSBpZCA9IDMiKSkKCiAgIyBWZXJpZnkgdGhhdCB0aGUgdXNlciBpcyBzdGlsbCBwcmVzZW50CiAgcmVzdWx0IDwtIGRiR2V0UXVlcnkoY29uLCAiU0VMRUNUICogRlJPTSB1c2VycyBXSEVSRSBpZCA9IDMiKQogIGV4cGVjdF9lcXVhbChucm93KHJlc3VsdCksIDEpCn0pCmBgYAoKIyMjIDMuICoqUnVubmluZyB0aGUgVGVzdHMqKgoKQXMgc2hvd24gYmVmb3JlLCB0byBydW4gdGhlIHRlc3RzLCB1c2UgdGhlIGB0ZXN0X2RpcmAgb3IgYHRlc3RfZmlsZWAgZnVuY3Rpb25zIGZyb20gdGhlIGB0ZXN0dGhhdGAgcGFja2FnZS4gSWYgeW91ciB0ZXN0cyBhcmUgaW4gYSBkaXJlY3RvcnkgY2FsbGVkICp0ZXN0cy90ZXN0dGhhdCosIHlvdSBjYW4gcnVuIHRoZW0gYWxsIHdpdGg6CgpgYGB7ciBldmFsPUZ9CnRlc3R0aGF0Ojp0ZXN0X2RpcigidGVzdHMvdGVzdHRoYXQiKQpgYGAKCk9yLCBpZiB5b3UgaGF2ZSB5b3VyIHRlc3RzIGluIGEgc2luZ2xlIGZpbGUsIHlvdSBjYW4gcnVuOgoKYGBge3IgZXZhbD1GfQp0ZXN0dGhhdDo6dGVzdF9maWxlKCJ0ZXN0cy90ZXN0dGhhdC90ZXN0X3NxbC5SIikKYGBgCgojIyBDb25jbHVzaW9uCgpFZmZlY3RpdmUgdGVzdGluZyBpcyB2aXRhbCBmb3IgZGVsaXZlcmluZyBoaWdoLXF1YWxpdHkgc29mdHdhcmUuIEJ5IHVuZGVyc3RhbmRpbmcgYW5kIGltcGxlbWVudGluZyBkaWZmZXJlbnQgdHlwZXMgb2YgdGVzdGluZywgeW91IGNhbiBlbnN1cmUgdGhhdCB5b3VyIHNvZnR3YXJlIG5vdCBvbmx5IG1lZXRzIHJlcXVpcmVtZW50cyBidXQgYWxzbyBwZXJmb3JtcyB3ZWxsIGluIHJlYWwtd29ybGQgc2NlbmFyaW9zLiBBZG9wdGluZyBhIGNvbXByZWhlbnNpdmUgdGVzdGluZyBzdHJhdGVneSBoZWxwcyBpbiBpZGVudGlmeWluZyBpc3N1ZXMgZWFybHksIHJlZHVjaW5nIGNvc3RzLCBhbmQgZW5oYW5jaW5nIHRoZSBvdmVyYWxsIHJlbGlhYmlsaXR5IGFuZCB1c2VyIHNhdGlzZmFjdGlvbiBvZiB5b3VyIHNvZnR3YXJlIHByb2R1Y3QuCgpVc2luZyB0aGUgKip0ZXN0dGhhdCoqIHBhY2thZ2UgaW4gUiwgeW91IGNhbiBlYXNpbHkgY3JlYXRlIGFuZCBydW4gYm90aCB1bml0IGFuZCBzeXN0ZW0gdGVzdHMgdG8gZW5zdXJlIHlvdXIgY29kZSBmdW5jdGlvbnMgYXMgaW50ZW5kZWQuIEJ5IGFkb3B0aW5nIGEgY29tcHJlaGVuc2l2ZSB0ZXN0aW5nIHN0cmF0ZWd5LCB5b3UgY2FuIGltcHJvdmUgdGhlIHJlbGlhYmlsaXR5IGFuZCBtYWludGFpbmFiaWxpdHkgb2YgeW91ciBSIHByb2plY3RzLgoKU2lkZSBlZmZlY3RzIGFyZSBhIGZ1bmRhbWVudGFsIGNvbmNlcHQgaW4gcHJvZ3JhbW1pbmcsIHJlcHJlc2VudGluZyBhbnkgaW50ZXJhY3Rpb24gd2l0aCBvciBtb2RpZmljYXRpb24gb2YgZXh0ZXJuYWwgc3RhdGUuIFdoaWxlIHRoZXkgYXJlIG5lY2Vzc2FyeSBmb3IgcmVhbC13b3JsZCBhcHBsaWNhdGlvbnMsIG1hbmFnaW5nIHRoZW0gZWZmZWN0aXZlbHkgaXMgY3J1Y2lhbCBmb3Igd3JpdGluZyByZWxpYWJsZSwgbWFpbnRhaW5hYmxlLCBhbmQgdGVzdGFibGUgY29kZS4gVW5kZXJzdGFuZGluZyBhbmQgY29udHJvbGxpbmcgc2lkZSBlZmZlY3RzIGNhbiBzaWduaWZpY2FudGx5IGltcHJvdmUgdGhlIHF1YWxpdHkgYW5kIHByZWRpY3RhYmlsaXR5IG9mIHNvZnR3YXJlLgoKQnkgdXNpbmcgKip0ZXN0dGhhdCoqLCB5b3UgY2FuIGVmZmVjdGl2ZWx5IHRlc3QgU1FMIGNvZGUgYW5kIHRyaWdnZXJzIHdpdGhpbiBSLiBUaGlzIGFwcHJvYWNoIGFsbG93cyB5b3UgdG8gd3JpdGUgY29tcHJlaGVuc2l2ZSB1bml0LCBpbnRlZ3JhdGlvbiwgYW5kIGRhdGEgaW50ZWdyaXR5IHRlc3RzLCBlbnN1cmluZyB5b3VyIFNRTCBvcGVyYXRpb25zIHBlcmZvcm0gYXMgZXhwZWN0ZWQgYW5kIG1haW50YWluIGRhdGEgaW50ZWdyaXR5LiBJbnRlZ3JhdGluZyB0aGVzZSB0ZXN0cyBpbnRvIHlvdXIgZGV2ZWxvcG1lbnQgd29ya2Zsb3cgaGVscHMgaWRlbnRpZnkgaXNzdWVzIGVhcmx5IGFuZCBpbXByb3ZlcyB0aGUgcmVsaWFiaWxpdHkgb2YgeW91ciBkYXRhYmFzZSBvcGVyYXRpb25zLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyBGaWxlcyAmIFJlc291cmNlcwoKYGBge3IgemlwRmlsZXMsIGVjaG89RkFMU0V9CnppcE5hbWUgPSBzcHJpbnRmKCJMZXNzb25GaWxlcy0lcy0lcy56aXAiLCAKICAgICAgICAgICAgICAgICBwYXJhbXMkY2F0ZWdvcnksCiAgICAgICAgICAgICAgICAgcGFyYW1zJG51bWJlcikKCnRleHRBTGluayA9IHBhc3RlMCgiQWxsIEZpbGVzIGZvciBMZXNzb24gIiwgCiAgICAgICAgICAgICAgIHBhcmFtcyRjYXRlZ29yeSwiLiIscGFyYW1zJG51bWJlcikKCiMgZG93bmxvYWRGaWxlc0xpbmsoKSBpcyBpbmNsdWRlZCBmcm9tIF9pbnNlcnQyREIuUgprbml0cjo6cmF3X2h0bWwoZG93bmxvYWRGaWxlc0xpbmsoIi4iLCB6aXBOYW1lLCB0ZXh0QUxpbmspKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMgUmVmZXJlbmNlcwoKTm9uZSB5ZXQuCgojIyBFcnJhdGEKCltMZXQgdXMga25vd10oaHR0cHM6Ly9mb3JtLmpvdGZvcm0uY29tLzIxMjE4NzA3Mjc4NDE1Nyl7dGFyZ2V0PSJfYmxhbmsifS4K