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:
Define Clear Requirements: Clearly define the expected behavior of the software, including both normal operations and error handling.
Develop a Test Plan: Create a test plan that outlines which scenarios to test, including both typical use cases and edge cases.
Automate Testing: Use automated testing tools to regularly run both test-to-pass and test-to-fail scenarios, ensuring continuous validation of the software.
Prioritize Critical Functions: Focus on critical functions and high-risk areas first, ensuring that they are thoroughly tested under both normal and exceptional conditions.
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.
- Unit Testing
- Integration Testing
- System Testing
- Acceptance Testing
- Performance Testing
- Security Testing
- 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.
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
- Automate Where Possible: Use automated testing tools to save time and reduce human error.
- Test Early and Often: Integrate testing into your development process from the beginning.
- Use a Test Plan: Develop a comprehensive test plan that outlines testing strategies, scope, resources, and schedule.
- Prioritize Tests: Focus on critical functionalities and high-risk areas.
- 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:
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
- 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.
- 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).
- Keep Tests Small and Focused: Each test should focus on a single aspect of the functionβs behavior.
- Use Descriptive Names: Use descriptive names for your test cases to make it clear what is being tested.
- 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
- Modifying Variables: Changing the value of variables that exist outside the functionβs local scope.
- I/O Operations: Reading from or writing to external sources like files, databases, or network sockets.
- State Changes: Modifying the state of objects or data structures in ways that persist beyond the function call.
- 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.
LS0tCnRpdGxlOiAiQXV0b21hdGVkIFVuaXQgYW5kIEludGVncml0eSBUZXN0aW5nIGluIFIiCnBhcmFtczoKICBjYXRlZ29yeTogNgogIG51bWJlcjogMTk0CiAgdGltZTogNDUKICBsZXZlbDogYmVnaW5uZXIKICB0YWdzOiAicix0ZXN0dGhhdCx1bml0IHRlc3RpbmcsdGVzdGluZyIKICBkZXNjcmlwdGlvbjogIkRlbW9uc3RyYXRlcyBob3cgdG8gYnVpbGQgc2ltcGxlIHVuaXQgdGVzdHMgaW4gUiB1c2luZyB0aGUKICAgICAgICAgICAgICAgICd0ZXN0dGhhdCcgcGFja2FnZS4gRXhwbGFpbnMgY29tbW9uIHVuaXQgYW5kIHN5c3RlbSB0ZXN0aW5nCiAgICAgICAgICAgICAgICBwcmluY2lwbGVzLiBTaG93cyBob3cgdG8gdGVzdCBkYXRhYmFzZSBjb2RlLiIKZGF0ZTogIjxzbWFsbD5gciBTeXMuRGF0ZSgpYDwvc21hbGw+IgphdXRob3I6ICI8c21hbGw+TWFydGluIFNjaGVkbGJhdWVyPC9zbWFsbD4iCmVtYWlsOiAibS5zY2hlZGxiYXVlckBuZXUuZWR1IgphZmZpbGl0YXRpb246ICJOb3J0aGVhc3Rlcm4gVW5pdmVyc2l0eSIKb3V0cHV0OiAKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29sbGFwc2VkOiBmYWxzZQogICAgbnVtYmVyX3NlY3Rpb25zOiBmYWxzZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgdGhlbWU6IHNwYWNlbGFiCiAgICBoaWdobGlnaHQ6IHRhbmdvCi0tLQoKLS0tCnRpdGxlOiAiPHNtYWxsPmByIHBhcmFtcyRjYXRlZ29yeWAuYHIgcGFyYW1zJG51bWJlcmA8L3NtYWxsPjxici8+PHNwYW4gc3R5bGU9J2NvbG9yOiAjMkU0MDUzOyBmb250LXNpemU6IDAuOWVtJz5gciBybWFya2Rvd246Om1ldGFkYXRhJHRpdGxlYDwvc3Bhbj4iCi0tLQoKYGBge3IgY29kZT14ZnVuOjpyZWFkX3V0ZjgocGFzdGUwKGhlcmU6OmhlcmUoKSwnL1IvX2luc2VydDJEQi5SJykpLCBpbmNsdWRlID0gRkFMU0V9CmBgYAoKIyMgSW50cm9kdWN0aW9uCgpUZXN0aW5nIGlzIGFuIGludGVncmFsIHBhcnQgb2YgdGhlIHNvZnR3YXJlIGRldmVsb3BtZW50IGxpZmVjeWNsZSwgZW5zdXJpbmcgdGhhdCBzb2Z0d2FyZSBhcHBsaWNhdGlvbnMgYW5kIHRoZWlyIGluZGl2aWR1YWwgY29tcG9uZW50cyBmdW5jdGlvbiBjb3JyZWN0bHkgYW5kIG1lZXQgc3BlY2lmaWVkIHJlcXVpcmVtZW50cy4gVmFyaW91cyB0eXBlcyBvZiB0ZXN0aW5nIGFyZSB1c2VkIHRvIHZhbGlkYXRlIGRpZmZlcmVudCBhc3BlY3RzIG9mIHRoZSBhcHBsaWNhdGlvbiwgZnJvbSBpbmRpdmlkdWFsIHVuaXRzIG9mIGNvZGUsIHN1Y2ggYXMgZnVuY3Rpb25zIG9yIGNsYXNzZXMsIHRvIHRoZSBpbnRlZ3JhdGVkIHN5c3RlbSBhbmQgZXh0ZXJuYWwgY29tcG9uZW50cy4KCiMjIFRlc3QtdG8tUGFzcyB2cyBUZXN0LXRvLUZhaWwKClR3byBmdW5kYW1lbnRhbCBhcHByb2FjaGVzIHRvIHRlc3RpbmcgYXJlICp0ZXN0LXRvLXBhc3MqIGFuZCAqdGVzdC10by1mYWlsKi4gVW5kZXJzdGFuZGluZyB0aGVzZSBhcHByb2FjaGVzIGhlbHBzIGluIGRlc2lnbmluZyBtb3JlIHJvYnVzdCBhbmQgY29tcHJlaGVuc2l2ZSB0ZXN0IGNhc2VzLgoKKipUZXN0LXRvLVBhc3MqKiBjb25maXJtcyB0aGF0IHRoZSBzb2Z0d2FyZSB3b3JrcyBhcyBleHBlY3RlZCB1bmRlciBub3JtYWwgY29uZGl0aW9ucy4gVGhlIGdlbmVyYWwgYXBwcm9hY2ggaXMgdG8gd3JpdGUgdGVzdHMgd2l0aCB2YWxpZCBpbnB1dHMgdG8gdmVyaWZ5IHRoYXQgdGhlIHNvZnR3YXJlIHBlcmZvcm1zIHRoZSBkZXNpcmVkIG9wZXJhdGlvbnMgY29ycmVjdGx5LiBUaGUgZm9jdXMgaXMgb24gdHlwaWNhbCB1c2FnZSBzY2VuYXJpb3MgdG8gZW5zdXJlcyB0aGF0IHRoZSBzb2Z0d2FyZSBtZWV0cyBpdHMgZnVuY3Rpb25hbCByZXF1aXJlbWVudHMgd2hpY2ggaGVscHMgdmVyaWZ5IHRoZSBjb3JyZWN0bmVzcyBvZiB0aGUgbWFpbiBmdW5jdGlvbmFsaXR5LiBIb3dldmVyLCB0aGVzZSB0ZXN0cyBtYXkgbm90IHVuY292ZXIgZWRnZSBjYXNlcyBvciByYXJlIGNvbmRpdGlvbnMgYW5kIHRodXMgYXJlIHByaW1hcmlseSBmb2N1c2VkIG9uIGNvbmZpcm1pbmcgcG9zaXRpdmUgc2NlbmFyaW9zLgoKT24gdGhlIG90aGVyIGhhbmQsICoqVGVzdC10by1GYWlsKiogdGVzdGluZyBpZGVudGlmaWVzIHNjZW5hcmlvcyB3aGVyZSB0aGUgc29mdHdhcmUgbWlnaHQgZmFpbCBhbmQgZW5zdXJlIGl0IGhhbmRsZXMgdGhlbSBncmFjZWZ1bGx5LiBUaGUgaWRlYSBpcyB0byB3cml0ZSB0ZXN0cyB3aXRoIGludmFsaWQgb3IgdW5leHBlY3RlZCBpbnB1dHMgdG8gY2hlY2sgaG93IHRoZSBzb2Z0d2FyZSBoYW5kbGVzIGVycm9ycyBhbmQgZWRnZSBjYXNlcyBhbmQgd2hldGhlciB0aGUgc3lzdGVtJ3Mgb3IgYXBwbGljYXRpb24ncyBwZXJmb3JtYW5jZSBncmFjZWZ1bGx5IGRlZ3JhZGVzIC0tIG9yIHNpbXBseSBjcmFzaGVzLiBUaHVzIHRoZSBmb2N1cyBpcyBvbiByb2J1c3RuZXNzIGFuZCBlcnJvciBoYW5kbGluZyB0byBlbnN1cmUgdGhhdCB0aGUgc29mdHdhcmUgZmFpbHMgaW4gYSBjb250cm9sbGVkIG1hbm5lciBhbmQgcHJvdmlkZXMgbWVhbmluZ2Z1bCBlcnJvciBtZXNzYWdlcyBvciBoYW5kbGVzIGV4Y2VwdGlvbnMgYXBwcm9wcmlhdGVseS4gVGhlIG1haW4gYmVuZWZpdHMgb2YgdGVzdC10by1mYWlsIGluY2x1ZGUgaGVscGluZyB0byBpZGVudGlmeSBhbmQgZml4IHBvdGVudGlhbCB3ZWFrbmVzc2VzIGluIHRoZSBzb2Z0d2FyZSwgZW5zdXJlIHJvYnVzdG5lc3MgYnkgaGFuZGxpbmcgZWRnZSBjYXNlcyBhbmQgdW5leHBlY3RlZCBpbnB1dHMsIGFuZCBpbXByb3ZlIHRoZSByZWxpYWJpbGl0eSBvZiB0aGUgc29mdHdhcmUgYnkgdGVzdGluZyBob3cgaXQgZmFpbHMuIE5hdHVyYWxseSwgaXQgbWF5IG5vdCBjb3ZlciBhbGwgdHlwaWNhbCB1c2FnZSBzY2VuYXJpb3MgYW5kIHJlcXVpcmVzIHN1YnN0YW50aWFsIGVmZm9ydCB0byBpZGVudGlmeSBhbmQgY3JlYXRlIGVkZ2UgY2FzZSB0ZXN0cy4KCkJvdGggdGVzdC10by1wYXNzIGFuZCB0ZXN0LXRvLWZhaWwgYXJlIGVzc2VudGlhbCBjb21wb25lbnRzIG9mIGEgcm9idXN0IHRlc3Rpbmcgc3RyYXRlZ3kuIFdoaWxlIHRlc3QtdG8tcGFzcyBlbnN1cmVzIHRoYXQgdGhlIHNvZnR3YXJlIG1lZXRzIGl0cyBmdW5jdGlvbmFsIHJlcXVpcmVtZW50cywgdGVzdC10by1mYWlsIGlkZW50aWZpZXMgcG90ZW50aWFsIHdlYWtuZXNzZXMgYW5kIGltcHJvdmVzIHRoZSBzb2Z0d2FyZSdzIHJvYnVzdG5lc3MuIEJ5IGludGVncmF0aW5nIGJvdGggYXBwcm9hY2hlcywgdGhlIHNvZnR3YXJlIGRldmVsb3BlciBjYW4gZGV2ZWxvcCBtb3JlIHJlbGlhYmxlIGFuZCByZXNpbGllbnQgc29mdHdhcmUsIHVsdGltYXRlbHkgZW5oYW5jaW5nIHVzZXIgc2F0aXNmYWN0aW9uIGFuZCByZWR1Y2luZyB0aGUgcmlzayBvZiBmYWlsdXJlcyBpbiBwcm9kdWN0aW9uLgoKIyMgVGVzdGluZyBXb3JrZmxvdwoKQSBjb21wcmVoZW5zaXZlIHRlc3Rpbmcgd29ya2Zsb3cgc2hvdWxkIGluY2x1ZGUgYm90aCB0ZXN0LXRvLXBhc3MgYW5kIHRlc3QtdG8tZmFpbCBhcHByb2FjaGVzIGFuZCBnZW5lcmFsbHkgcmVxdWlyZXMgdGhlIGZvbGxvd2luZyBwcm9jZXNzIHN0ZXBzOgoKMS4gICoqRGVmaW5lIENsZWFyIFJlcXVpcmVtZW50cyoqOiBDbGVhcmx5IGRlZmluZSB0aGUgZXhwZWN0ZWQgYmVoYXZpb3Igb2YgdGhlIHNvZnR3YXJlLCBpbmNsdWRpbmcgYm90aCBub3JtYWwgb3BlcmF0aW9ucyBhbmQgZXJyb3IgaGFuZGxpbmcuCgoyLiAgKipEZXZlbG9wIGEgVGVzdCBQbGFuKio6IENyZWF0ZSBhIHRlc3QgcGxhbiB0aGF0IG91dGxpbmVzIHdoaWNoIHNjZW5hcmlvcyB0byB0ZXN0LCBpbmNsdWRpbmcgYm90aCB0eXBpY2FsIHVzZSBjYXNlcyBhbmQgZWRnZSBjYXNlcy4KCjMuICAqKkF1dG9tYXRlIFRlc3RpbmcqKjogVXNlIGF1dG9tYXRlZCB0ZXN0aW5nIHRvb2xzIHRvIHJlZ3VsYXJseSBydW4gYm90aCB0ZXN0LXRvLXBhc3MgYW5kIHRlc3QtdG8tZmFpbCBzY2VuYXJpb3MsIGVuc3VyaW5nIGNvbnRpbnVvdXMgdmFsaWRhdGlvbiBvZiB0aGUgc29mdHdhcmUuCgo0LiAgKipQcmlvcml0aXplIENyaXRpY2FsIEZ1bmN0aW9ucyoqOiBGb2N1cyBvbiBjcml0aWNhbCBmdW5jdGlvbnMgYW5kIGhpZ2gtcmlzayBhcmVhcyBmaXJzdCwgZW5zdXJpbmcgdGhhdCB0aGV5IGFyZSB0aG9yb3VnaGx5IHRlc3RlZCB1bmRlciBib3RoIG5vcm1hbCBhbmQgZXhjZXB0aW9uYWwgY29uZGl0aW9ucy4KCjUuICAqKlJldmlldyBhbmQgUmVmYWN0b3IqKjogQ29udGludW91c2x5IHJldmlldyBhbmQgcmVmYWN0b3IgeW91ciB0ZXN0IGNhc2VzIGJhc2VkIG9uIG5ldyBpbnNpZ2h0cyBhbmQgY2hhbmdpbmcgcmVxdWlyZW1lbnRzLCBlbnN1cmluZyBjb21wcmVoZW5zaXZlIGNvdmVyYWdlLgoKIyMgVHlwZXMgb2YgVGVzdGluZwoKTW9zdCBzb2Z0d2FyZSBkZXZlbG9wbWVudCBvcmdhbml6YXRpb25zIHBlcmZvcm0gc2V2ZW4gZGlmZmVyZW50IGxldmVscyBvZiB0ZXN0aW5nLCBlYWNoIGVuc3VyaW5nIGEgZGlzdGluY3QgZGVncmVlIG9mIGZ1bmN0aW9uYWxpdHkuCgoxLiAgKipVbml0IFRlc3RpbmcqKgoyLiAgKipJbnRlZ3JhdGlvbiBUZXN0aW5nKioKMy4gICoqU3lzdGVtIFRlc3RpbmcqKgo0LiAgKipBY2NlcHRhbmNlIFRlc3RpbmcqKgo1LiAgKipQZXJmb3JtYW5jZSBUZXN0aW5nKioKNi4gICoqU2VjdXJpdHkgVGVzdGluZyoqCjcuICAqKlVzYWJpbGl0eSBUZXN0aW5nKioKCiMjIyBVbml0IFRlc3RpbmcKCioqT2JqZWN0aXZlKio6IFZlcmlmeSB0aGF0IGluZGl2aWR1YWwgdW5pdHMgb3IgY29tcG9uZW50cyBvZiB0aGUgc29mdHdhcmUgd29yayBhcyBpbnRlbmRlZC4KCioqSG93IHRvIFBlcmZvcm0qKjogLSBXcml0ZSB0ZXN0IGNhc2VzIGZvciBlYWNoIGZ1bmN0aW9uIG9yIG1ldGhvZCBpbiBpc29sYXRpb24uIC0gVXNlIGFzc2VydGlvbnMgdG8gY2hlY2sgaWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgZXhwZWN0ZWQgcmVzdWx0cyBmb3IgZ2l2ZW4gaW5wdXRzLiAtICoqVG9vbHMqKjogYEpVbml0YCBmb3IgSmF2YSwgYHB5dGVzdGAgZm9yIFB5dGhvbiwgYHRlc3R0aGF0YCBmb3IgUi4KCiMjIyBJbnRlZ3JhdGlvbiBUZXN0aW5nCgoqKk9iamVjdGl2ZSoqOiBFbnN1cmUgdGhhdCBkaWZmZXJlbnQgbW9kdWxlcyBvciBzZXJ2aWNlcyBpbiBhIHN5c3RlbSB3b3JrIHRvZ2V0aGVyIGFzIGV4cGVjdGVkLgoKKipIb3cgdG8gUGVyZm9ybSoqOiAtIFRlc3QgdGhlIGludGVyYWN0aW9uIGJldHdlZW4gaW50ZWdyYXRlZCBjb21wb25lbnRzLiAtIElkZW50aWZ5IGFuZCB0ZXN0IGNyaXRpY2FsIGludGVncmF0aW9uIHBvaW50cy4gLSAqKlRvb2xzKio6IGBKVW5pdGAgd2l0aCBTcHJpbmcgZm9yIEphdmEsIGBweXRlc3RgIGZvciBQeXRob24sIGB0ZXN0dGhhdGAgZm9yIFIuCgojIyMgU3lzdGVtIFRlc3RpbmcKCioqT2JqZWN0aXZlKio6IFZhbGlkYXRlIHRoZSBjb21wbGV0ZSBhbmQgZnVsbHkgaW50ZWdyYXRlZCBzb2Z0d2FyZSBwcm9kdWN0IHRvIGVuc3VyZSBpdCBtZWV0cyB0aGUgcmVxdWlyZW1lbnRzLiBDcmVhdGUgdXNlciBzdG9yaWVzIGFuZCBhY2NlcHRhbmNlIGNyaXRlcmlhIHRvIHZhbGlkYXRlIGlmIHRoZSBhcml0aG1ldGljIG9wZXJhdGlvbnMgZnVsZmlsbCB0aGUgYnVzaW5lc3MgbmVlZHMuCgoqKkhvdyB0byBQZXJmb3JtKio6IC0gQ29uZHVjdCBlbmQtdG8tZW5kIHRlc3Rpbmcgb2YgdGhlIGFwcGxpY2F0aW9uLiAtIFRlc3Qgc2NlbmFyaW9zIHRoYXQgcmVmbGVjdCByZWFsLXdvcmxkIHVzYWdlLiAtICoqVG9vbHMqKjogU2VsZW5pdW0gZm9yIHdlYiBhcHBsaWNhdGlvbnMsIFFUUC9VRlQgZm9yIGRlc2t0b3AgYXBwbGljYXRpb25zLgoKIyMjIEFjY2VwdGFuY2UgVGVzdGluZwoKKipPYmplY3RpdmUqKjogVmVyaWZ5IHRoYXQgdGhlIHNvZnR3YXJlIG1lZXRzIHRoZSBidXNpbmVzcyByZXF1aXJlbWVudHMgYW5kIGlzIHJlYWR5IGZvciBkZWxpdmVyeS4KCioqSG93IHRvIFBlcmZvcm0qKjogLSBDb25kdWN0ZWQgYnkgdGhlIGVuZC11c2VycyBvciB0ZXN0ZXJzLiAtIFVzZSBwcmVkZWZpbmVkIGFjY2VwdGFuY2UgY3JpdGVyaWEuIC0gKipUb29scyoqOiBDdWN1bWJlciwgRml0TmVzc2UuCgojIyMgUGVyZm9ybWFuY2UgVGVzdGluZwoKKipPYmplY3RpdmUqKjogRW5zdXJlIHRoZSBzb2Z0d2FyZSBwZXJmb3JtcyB3ZWxsIHVuZGVyIGV4cGVjdGVkIGxvYWQgY29uZGl0aW9ucyBhbmQgdGhhdCB0aHJvdWdocHV0IGFuZCByZXNwb25zZSB0aW1lIG1lZXQgbm9uLWZ1bmN0aW9uYWwgcXVhbGl0eS1vZi1zZXJ2aWNlIHJlcXVpcmVtZW50cy4KCioqSG93IHRvIFBlcmZvcm0qKjogLSBNZWFzdXJlIHJlc3BvbnNlIHRpbWUsIHRocm91Z2hwdXQsIGFuZCByZXNvdXJjZSB1dGlsaXphdGlvbi4gLSBDb25kdWN0IHN0cmVzcywgbG9hZCwgYW5kIHNjYWxhYmlsaXR5IHRlc3RzLiAtICoqVG9vbHMqKjogSk1ldGVyLCBMb2FkUnVubmVyLgoKIyMjIFNlY3VyaXR5IFRlc3RpbmcKCioqT2JqZWN0aXZlKio6IElkZW50aWZ5IHZ1bG5lcmFiaWxpdGllcyBhbmQgZW5zdXJlIHRoZSBzb2Z0d2FyZSBpcyBzZWN1cmUsIGZvciBleGFtcGxlIGNoZWNraW5nIGZvciBjb21tb24gdnVsbmVyYWJpbGl0aWVzIHN1Y2ggYXMgU1FMIEluamVjdGlvbiBBdHRhY2tzLCBEZW5pYWwgb2YgU2VydmljZSBBdHRhY2tzLCBhbmQgQnVmZmVyIE92ZXJmbG93IEF0dGFja3MuIEFsc28sIHZlcmlmaWVzIHRoYXQgaW5mb3JtYXRpb24gaXMga2VwdCBzZWN1cmUsIGVuY3J5cHRlZCwgYW5kIGNvbmZpZGVudGlhbC4KCioqSG93IHRvIFBlcmZvcm0qKjogLSBQZXJmb3JtIHBlbmV0cmF0aW9uIHRlc3RpbmcgYW5kIHZ1bG5lcmFiaWxpdHkgc2Nhbm5pbmcuIC0gVGVzdCBmb3IgY29tbW9uIHNlY3VyaXR5IGlzc3VlcyBsaWtlIFNRTCBpbmplY3Rpb24sIFhTUywgZXRjLiAtICoqVG9vbHMqKjogT1dBU1AgWkFQLCBCdXJwIFN1aXRlLgoKIyMjIFVzYWJpbGl0eSBUZXN0aW5nCgoqKk9iamVjdGl2ZSoqOiBWZXJpZnkgdGhhdCB0aGUgc29mdHdhcmUgaXMgdXNlci1mcmllbmRseSBhbmQgbWVldHMgdXNlciBleHBlcmllbmNlIHN0YW5kYXJkcy4gQ29tbW9ubHkgdXNlcyBvYnNlcnZhdGlvbiBhbmQgdGFzayBjb21wbGV0aW9uIHN0dWRpZXMuCgoqKkhvdyB0byBQZXJmb3JtKio6IC0gQ29uZHVjdCB0ZXN0cyB3aXRoIHJlYWwgdXNlcnMuIC0gR2F0aGVyIGZlZWRiYWNrIG9uIGVhc2Ugb2YgdXNlLCBpbnRlcmZhY2UgZGVzaWduLCBldGMuIC0gKipUb29scyoqOiBVc2VyVGVzdGluZy5jb20sIE1vcmFlLgoKIyMjIEJlc3QgUHJhY3RpY2VzCgoxLiAgKipBdXRvbWF0ZSBXaGVyZSBQb3NzaWJsZSoqOiBVc2UgYXV0b21hdGVkIHRlc3RpbmcgdG9vbHMgdG8gc2F2ZSB0aW1lIGFuZCByZWR1Y2UgaHVtYW4gZXJyb3IuCjIuICAqKlRlc3QgRWFybHkgYW5kIE9mdGVuKio6IEludGVncmF0ZSB0ZXN0aW5nIGludG8geW91ciBkZXZlbG9wbWVudCBwcm9jZXNzIGZyb20gdGhlIGJlZ2lubmluZy4KMy4gICoqVXNlIGEgVGVzdCBQbGFuKio6IERldmVsb3AgYSBjb21wcmVoZW5zaXZlIHRlc3QgcGxhbiB0aGF0IG91dGxpbmVzIHRlc3Rpbmcgc3RyYXRlZ2llcywgc2NvcGUsIHJlc291cmNlcywgYW5kIHNjaGVkdWxlLgo0LiAgKipQcmlvcml0aXplIFRlc3RzKio6IEZvY3VzIG9uIGNyaXRpY2FsIGZ1bmN0aW9uYWxpdGllcyBhbmQgaGlnaC1yaXNrIGFyZWFzLgo1LiAgKipSZXZpZXcgYW5kIFJlZmFjdG9yKio6IENvbnRpbnVvdXNseSByZXZpZXcgYW5kIGltcHJvdmUgeW91ciB0ZXN0IGNhc2VzIHRvIGFkYXB0IHRvIGNoYW5naW5nIHJlcXVpcmVtZW50cy4KCiMjIFRlc3QgQXV0b21hdGlvbiB3aXRoICoqdGVzdHRoYXQqKgoKVGVzdGluZyBpcyBhIGNydWNpYWwgcGFydCBvZiBzb2Z0d2FyZSBkZXZlbG9wbWVudCB0aGF0IGVuc3VyZXMgeW91ciBjb2RlIHdvcmtzIGNvcnJlY3RseS4gSW4gUiwgdGhlICoqdGVzdHRoYXQqKiBwYWNrYWdlIHByb3ZpZGVzIGEgcm9idXN0IGZyYW1ld29yayBmb3Igd3JpdGluZyBhbmQgcnVubmluZyB0ZXN0cy4gVGhpcyB0dXRvcmlhbCB3aWxsIGd1aWRlIHlvdSB0aHJvdWdoIHRoZSBjb25jZXB0cyBvZiB1bml0IGFuZCBzeXN0ZW0gdGVzdGluZyB1c2luZyB0aGUgZnJhbWV3b3JrIG9mIHRoZSAqKnRlc3R0aGF0KiogcGFja2FnZS4KCiMjIyBTZXR0aW5nIFVwIHRoZSBFbnZpcm9ubWVudAoKRmlyc3QsIHlvdSBuZWVkIHRvIGluc3RhbGwgdGhlICoqdGVzdHRoYXQqKiBwYWNrYWdlIGlmIHlvdSBoYXZlbid0IGFscmVhZHksIHVzaW5nIGVpdGhlciB0aGUgUiBjb2RlIGZyYWdtZW50IGJlbG93LCBvciBieSBpbnN0YWxsaW5nIGl0IHRocm91Z2ggeW91ciBJREUgKFJTdHVkaW8sIFBvc2l0LCBvciBWUyBDb2RlLCAqZXRjLiopOgoKYGBge3IgZWNobyA9IEYsIGV2YWwgPSBGLCB3YXJuaW5nPUYsIG1lc3NhZ2U9Rn0KaW5zdGFsbC5wYWNrYWdlcygidGVzdHRoYXQiKQpgYGAKCkluc3RhbGxhdGlvbiBpcyBvbmx5IG5lY2Vzc2FyeSBvbmNlLCBidXQgeW91IG5lZWQgdG8gbG9hZCB0aGUgcGFja2FnZSBpbnRvIHlvdXIgUiBzZXNzaW9uIGV2ZXJ5dGltZSB5b3Ugd2lzaCB0byB1c2UgaXQ6CgpgYGB7cn0KbGlicmFyeSh0ZXN0dGhhdCkKYGBgCgojIyMgVW5pdCBUZXN0aW5nCgpVbml0IHRlc3RpbmcgZm9jdXNlcyBvbiB0ZXN0aW5nIGluZGl2aWR1YWwgZnVuY3Rpb25zIG9yIGNvbXBvbmVudHMgb2YgeW91ciBjb2RlLiBUaGUgZ29hbCBpcyB0byB2ZXJpZnkgdGhhdCBlYWNoIGZ1bmN0aW9uIHBlcmZvcm1zIGFzIGV4cGVjdGVkLgoKIyMjIyBXcml0aW5nIFVuaXQgVGVzdHMKCkNvbnNpZGVyIGEgc2ltcGxlIGZ1bmN0aW9uIHRoYXQgYWRkcyB0d28gbnVtYmVyczoKCmBgYHtyfQphZGQgPC0gZnVuY3Rpb24oeCwgeSkgewogIHJldHVybih4ICsgeSkKfQpgYGAKClRvIHdyaXRlIGEgdW5pdCB0ZXN0IGZvciB0aGlzIGZ1bmN0aW9uLCBjcmVhdGUgYSBzZXBhcmF0ZSB0ZXN0IGZpbGUuIEJ5IGNvbnZlbnRpb24sIHRlc3QgZmlsZXMgYXJlIHBsYWNlZCBpbiBhICJ0ZXN0cy90ZXN0dGhhdCIgZGlyZWN0b3J5IHdpdGhpbiB5b3VyIHByb2plY3QgZm9sZGVyLiBMZXQncyBuYW1lIG91ciB0ZXN0IGZpbGUgKnRlc3QtYWRkLlIqLgoKSW4gKnRlc3QtYWRkLlIqLCB5b3Ugd291bGQgd3JpdGUgdGhlIGZvbGxvd2luZyB0ZXN0czoKCmBgYHtyfQojIFRFU1QgU0NSSVBUOiB0ZXN0LWFkZC5SCgpsaWJyYXJ5KHRlc3R0aGF0KQoKdGVzdF90aGF0KCJhZGRpdGlvbiB3b3JrcyIsIHsKICBleHBlY3RfZXF1YWwoYWRkKDEsIDEpLCAyKQogIGV4cGVjdF9lcXVhbChhZGQoLTEsIC0xKSwgLTIpCiAgZXhwZWN0X2VxdWFsKGFkZCgxLCAtMSksIDApCn0pCmBgYAoKSW4gdGhlIGFib3ZlIGNvZGUsIHRoZSBmdW5jdGlvbiBgdGVzdF90aGF0YCBkZWZpbmVzIGEgdGVzdCBibG9jaywgYW5kIGBleHBlY3RfZXF1YWxgIGNoZWNrcyBpZiB0aGUgZnVuY3Rpb24gb3V0cHV0IG1hdGNoZXMgdGhlIGV4cGVjdGVkIHJlc3VsdC4KCiMjIyMgUnVubmluZyBVbml0IFRlc3RzCgpZb3UgY2FuIHJ1biB0aGUgdGVzdHMgdXNpbmcgdGhlIGZvbGxvd2luZyBjb21tYW5kIChhc3N1bWluZyB0aGF0IHlvdSBoYXZlIHlvdXIgdGVzdHMgZGVmaW5lZCBpbiB0aGUgZm9sZGVyICp0ZXN0cy90ZXN0dGhhdCo6CgpgYGB7ciBldmFsPUZ9CnRlc3RfZGlyKCJ0ZXN0cy90ZXN0dGhhdCIpCmBgYAoKQWx0ZXJuYXRpdmVseSwgaWYgeW91IGFyZSB1c2luZyBSU3R1ZGlvL1Bvc2l0LCB5b3UgY2FuIHVzZSB0aGUgIkJ1aWxkIiBwYW5lIHRvIHJ1biBhbGwgdGVzdHMuIEluIGFkZGl0aW9uLCB5b3UgY2FuIHJ1biB0aGUgYWJvdmUgY29tbWFuZCBmcm9tIHRoZSBSIENvbnNvbGUgd2l0aGluIFJTdHVkaW8vUG9zaXQgd2hpY2ggd291bGQgYWxsb3cgeW91IHRvIGtlZXAgdGhlIHRlc3RpbmcgbWVjaGFuaXNtIG91dHNpZGUgeW91ciBwcm9ncmFtL3NjcmlwdCBjb2RlLgoKIyMjIFN5c3RlbSBUZXN0aW5nCgpTeXN0ZW0gdGVzdGluZywgYWxzbyBzb21ldGltZXMgcmVmZXJyZWQgdG8gYXMgaW50ZWdyYXRpb24gdGVzdGluZyAoZXZlbiB0aG91Z2ggaXQgaXMgbm90IHF1aXRlIHRoZSBzYW1lKSwgaW52b2x2ZXMgdGVzdGluZyB0aGUgY29tcGxldGUgc3lzdGVtIG9yIGFwcGxpY2F0aW9uLiBJdCBlbnN1cmVzIHRoYXQgZGlmZmVyZW50IHBhcnRzIG9mIHRoZSBhcHBsaWNhdGlvbiB3b3JrIHRvZ2V0aGVyIGFzIGV4cGVjdGVkLgoKIyMjIyBXcml0aW5nIFN5c3RlbSBUZXN0cwoKTGV0J3MgZXhwYW5kIG91ciBleGFtcGxlIHRvIGEgc21hbGwgc3lzdGVtIHRoYXQgcGVyZm9ybXMgYmFzaWMgYXJpdGhtZXRpYyBvcGVyYXRpb25zLiBXZSdsbCBjcmVhdGUgZnVuY3Rpb25zIGZvciBhZGRpdGlvbiwgc3VidHJhY3Rpb24sIG11bHRpcGxpY2F0aW9uLCBhbmQgZGl2aXNpb246CgpgYGB7cn0KYWRkIDwtIGZ1bmN0aW9uKHgsIHkpIHsKICByZXR1cm4oeCArIHkpCn0KCnN1YnRyYWN0IDwtIGZ1bmN0aW9uKHgsIHkpIHsKICByZXR1cm4oeCAtIHkpCn0KCm11bHRpcGx5IDwtIGZ1bmN0aW9uKHgsIHkpIHsKICByZXR1cm4oeCAqIHkpCn0KCmRpdmlkZSA8LSBmdW5jdGlvbih4LCB5KSB7CiAgaWYgKHkgPT0gMCkgewogICAgc3RvcCgiRGl2aXNpb24gYnkgemVybyBlcnJvciIpCiAgfQogIHJldHVybih4IC8geSkKfQpgYGAKCk5leHQsIHdlIHdpbGwgY3JlYXRlIGEgbmV3IHRlc3QgZmlsZSBpbiB0aGUgZm9sZGVyICp0ZXN0cy90ZXN0dGhhdCogbmFtZWQgKnRlc3QtYXJpdGhtZXRpYy5SKiBmb3Igc3lzdGVtIHRlc3RzOgoKYGBge3IgZXZhbD1GfQojIFRFU1QgRklMRTogdGVzdC1hcml0aG1ldGljLlIKCmxpYnJhcnkodGVzdHRoYXQpCgp0ZXN0X3RoYXQoImFyaXRobWV0aWMgb3BlcmF0aW9ucyB3b3JrIGNvcnJlY3RseSIsIHsKICBleHBlY3RfZXF1YWwoYWRkKDIsIDMpLCA1KQogIGV4cGVjdF9lcXVhbChzdWJ0cmFjdCg1LCAzKSwgMikKICBleHBlY3RfZXF1YWwobXVsdGlwbHkoMiwgMyksIDYpCiAgZXhwZWN0X2VxdWFsKGRpdmlkZSg2LCAzKSwgMikKICAKICAjIFRlc3RpbmcgZWRnZSBjYXNlcwogIGV4cGVjdF9lcnJvcihkaXZpZGUoMSwgMCksICJEaXZpc2lvbiBieSB6ZXJvIGVycm9yIikKfSkKYGBgCgpJbiB0aGlzIHRlc3QsIHdlIGFyZSBjaGVja2luZyB0aGUgY29ycmVjdG5lc3Mgb2YgYWxsIGFyaXRobWV0aWMgZnVuY3Rpb25zIHRvZ2V0aGVyLCBpbmNsdWRpbmcgaGFuZGxpbmcgZWRnZSBjYXNlcyBsaWtlIGRpdmlzaW9uIGJ5IHplcm8uCgojIyMjIFJ1bm5pbmcgU3lzdGVtIFRlc3RzCgpSdW4gdGhlIHRlc3RzIHVzaW5nIHRoZSBzYW1lIGNvbW1hbmQgYXMgZm9yIHVuaXQgdGVzdHMgKGFnYWluLCBhc3N1bWluZyB0aGF0IHRoZSBhYm92ZSB0ZXN0IGNvZGUgZXhpc3RzIGluIHRoZSBmb2xkZXIpOgoKYGBge3J9CnRlc3RfZGlyKCJ0ZXN0cy90ZXN0dGhhdCIpCmBgYAoKTm90ZSB0aGF0IHRoaXMgY29tbWFuZCBydW5zICoqYWxsIHRlc3RzKiogaW4gdGhlIGZvbGRlciAqdGVzdHMvdGVzdHRoYXQqLiBUaGlzIGFsbG93cyB0ZXN0cyB0byBiZSBzZWdtZW50ZWQgYW5kIG1vcmUgZWFzaWx5IG1hbmFnZWQuCgojIyMgQmVzdCBQcmFjdGljZXMgZm9yIFRlc3RpbmcgaW4gUgoKMS4gICoqV3JpdGUgVGVzdHMgRWFybHkqKjogRGV2ZWxvcCB5b3VyIHRlc3RzIGFsb25nc2lkZSB5b3VyIGNvZGUgdG8gY2F0Y2ggaXNzdWVzIGVhcmx5LiBTb21lIHNvZnR3YXJlIGRldmVsb3BtZW50IGZyYW1ld29ya3MgcmVxdWlyZSB0ZXN0cyB0byBiZSB3cml0dGVuIGJlZm9yZSB0aGUgY29kZSBpcyBjcmVhdGVkIHRvIGVuc3VyZSB0aGF0IHRoZSBjb2RlIG1hdGNoZXMgdGhlIHJlcXVpcmVtZW50czogd3JpdGUgYWdhaW5zdCB0ZXN0cy4KMi4gICoqVGVzdCBFZGdlIENhc2VzKio6IEFsd2F5cyBjb25zaWRlciBhbmQgdGVzdCBmb3IgZWRnZSBjYXNlcyBhbmQgdW51c3VhbCBpbnB1dHMsIGVzcGVjaWFsbHkgY2hlY2tpbmcgYm91bmRhcnkgY29uZGl0aW9ucy4gTW9zdCBlcnJvcnMgb2NjdXIgb24gYm91bmRhcmllcywgKmUuZy4qLCBpZiBhIG51bWJlciBpcyBzdXBwb3NlZCB0byBiZSAxMCBvciBtb3JlLCB0aGVuIHRlc3QgZm9yIDkgKGZhaWwpIGFuZCAxMCAocGFzcykuCjMuICAqKktlZXAgVGVzdHMgU21hbGwgYW5kIEZvY3VzZWQqKjogRWFjaCB0ZXN0IHNob3VsZCBmb2N1cyBvbiBhIHNpbmdsZSBhc3BlY3Qgb2YgdGhlIGZ1bmN0aW9uJ3MgYmVoYXZpb3IuCjQuICAqKlVzZSBEZXNjcmlwdGl2ZSBOYW1lcyoqOiBVc2UgZGVzY3JpcHRpdmUgbmFtZXMgZm9yIHlvdXIgdGVzdCBjYXNlcyB0byBtYWtlIGl0IGNsZWFyIHdoYXQgaXMgYmVpbmcgdGVzdGVkLgo1LiAgKipBdXRvbWF0ZSBUZXN0aW5nKio6IEludGVncmF0ZSB5b3VyIHRlc3RzIGludG8geW91ciBkZXZlbG9wbWVudCB3b3JrZmxvdyB0byBydW4gdGhlbSBhdXRvbWF0aWNhbGx5LgoKIyMgVGVzdGluZyBTaWRlIEVmZmVjdHMKCiMjIyBTaWRlIEVmZmVjdHMgaW4gUHJvZ3JhbW1pbmcKCkluIHByb2dyYW1taW5nLCBhIHNpZGUgZWZmZWN0IG9jY3VycyB3aGVuIGEgZnVuY3Rpb24gb3IgZXhwcmVzc2lvbiBtb2RpZmllcyBzb21lIHN0YXRlIG9yIGludGVyYWN0cyB3aXRoIHRoZSBleHRlcm5hbCB3b3JsZCBpbiB3YXlzIGJleW9uZCByZXR1cm5pbmcgYSB2YWx1ZS4gU2lkZSBlZmZlY3RzIGNhbiBpbmNsdWRlIGFsdGVyaW5nIGEgdmFyaWFibGUsIG1vZGlmeWluZyBhIGRhdGEgc3RydWN0dXJlLCB3cml0aW5nIHRvIGEgZmlsZSwgd3JpdGluZyB0byBhIGRhdGFiYXNlLCBzZW5kaW5nIGEgbWVzc2FnZSB0byBhbm90aGVyIHByb2Nlc3MsIG9yIGNoYW5naW5nIHRoZSBzdGF0ZSBvZiB0aGUgdXNlciBpbnRlcmZhY2UuCgpUaGVyZSBhcmUgc2V2ZXJhbCBjaGFyYWN0ZXJpc3RpY3Mgb2Ygc2lkZSBlZmZlY3RzLCBpbmNsdWRpbmcKCjEuICAqKk1vZGlmeWluZyBWYXJpYWJsZXMqKjogQ2hhbmdpbmcgdGhlIHZhbHVlIG9mIHZhcmlhYmxlcyB0aGF0IGV4aXN0IG91dHNpZGUgdGhlIGZ1bmN0aW9uJ3MgbG9jYWwgc2NvcGUuCjIuICAqKkkvTyBPcGVyYXRpb25zKio6IFJlYWRpbmcgZnJvbSBvciB3cml0aW5nIHRvIGV4dGVybmFsIHNvdXJjZXMgbGlrZSBmaWxlcywgZGF0YWJhc2VzLCBvciBuZXR3b3JrIHNvY2tldHMuCjMuICAqKlN0YXRlIENoYW5nZXMqKjogTW9kaWZ5aW5nIHRoZSBzdGF0ZSBvZiBvYmplY3RzIG9yIGRhdGEgc3RydWN0dXJlcyBpbiB3YXlzIHRoYXQgcGVyc2lzdCBiZXlvbmQgdGhlIGZ1bmN0aW9uIGNhbGwuCjQuICAqKkludGVyYWN0aW9uIHdpdGggRXh0ZXJuYWwgU3lzdGVtcyoqOiBDYWxsaW5nIGV4dGVybmFsIEFQSXMgb3IgaW50ZXJhY3Rpbmcgd2l0aCBoYXJkd2FyZSBjb21wb25lbnRzLgoKQ29uc2lkZXIgYSBmdW5jdGlvbiB0aGF0IGluY3JlbWVudHMgYSBnbG9iYWwgdmFyaWFibGU6CgpgYGAgcgpjb3VudGVyIDwtIDAKCmluY3JlbWVudF9jb3VudGVyIDwtIGZ1bmN0aW9uKCkgewogIGNvdW50ZXIgPDwtIGNvdW50ZXIgKyAxCn0KYGBgCgpIZXJlLCBgaW5jcmVtZW50X2NvdW50ZXJgIG1vZGlmaWVzIHRoZSBnbG9iYWwgdmFyaWFibGUgYGNvdW50ZXJgLCBjYXVzaW5nIGEgc2lkZSBlZmZlY3QuCgpBbm90aGVyIGV4YW1wbGUgaXMgd2hlbiBhIGZ1bmN0aW9uIHdyaXRlcyB0byBhIGZpbGU6CgpgYGAgcgp3cml0ZV90b19maWxlIDwtIGZ1bmN0aW9uKHRleHQpIHsKICB3cml0ZSh0ZXh0LCBmaWxlID0gIm91dHB1dC50eHQiKQp9CmBgYAoKV3JpdGluZyB0byBhIGZpbGUgaXMgYSBzaWRlIGVmZmVjdCBiZWNhdXNlIGl0IGNoYW5nZXMgdGhlIHN0YXRlIG9mIHRoZSBmaWxlIHN5c3RlbS4KCiMjIyBGdW5jdGlvbmFsIFByb2dyYW1taW5nCgpJbiBmdW5jdGlvbmFsIHByb2dyYW1taW5nLCBzaWRlIGVmZmVjdHMgYXJlIG1pbmltaXplZCBvciBlbGltaW5hdGVkIHRvIGVuc3VyZSBmdW5jdGlvbnMgYXJlIHB1cmUuIEEgcHVyZSBmdW5jdGlvbiBpcyBvbmUgdGhhdCwgZ2l2ZW4gdGhlIHNhbWUgaW5wdXQsIGFsd2F5cyByZXR1cm5zIHRoZSBzYW1lIG91dHB1dCBhbmQgZG9lcyBub3QgY2F1c2UgYW55IHNpZGUgZWZmZWN0cy4KCioqRXhhbXBsZSBvZiBhIFB1cmUgRnVuY3Rpb24qKjoKCmBgYCByCmFkZCA8LSBmdW5jdGlvbih4LCB5KSB7CiAgcmV0dXJuKHggKyB5KQp9CmBgYAoKVGhpcyBmdW5jdGlvbiBpcyBwdXJlIGJlY2F1c2UgaXQgZG9lcyBub3QgbW9kaWZ5IGFueSBzdGF0ZSBvciBpbnRlcmFjdCB3aXRoIHRoZSBvdXRzaWRlIHdvcmxkLgoKIyMjIFByYWN0aWNhbCBTaWRlIEVmZmVjdHMKCkludGVyYWN0aW9ucyB3aXRoIHRoZSBvdXRzaWRlIHdvcmxkIChlLmcuLCB1c2VyIGlucHV0LCBmaWxlIG9wZXJhdGlvbnMpIGFyZSBpbmhlcmVudGx5IHNpZGUgZWZmZWN0cyBhbmQgYXJlIGVzc2VudGlhbCBmb3IgcmVhbC13b3JsZCBhcHBsaWNhdGlvbnMuIFRoZXkgd291bGQgbm90IGJlIHBvc3NpYmxlIHRvIGJ1aWxkIHdpdGhvdXQgc2lkZSBlZmZlY3RzLiBTaWRlIGVmZmVjdHMgY2FuIGJlIHVzZWZ1bCBmb3IgbWFuYWdpbmcgc3RhdGUgYW5kIGNvbnRyb2xsaW5nIHByb2dyYW0gZmxvdy4KCkhvd2V2ZXIsIGZ1bmN0aW9ucyB3aXRoIHNpZGUgZWZmZWN0cyBhcmUgbW9yZSBjaGFsbGVuZ2luZyB0byB0ZXN0IGJlY2F1c2UgdGhlaXIgYmVoYXZpb3IgY2FuIGRlcGVuZCBvbiBleHRlcm5hbCBzdGF0ZS4gSW4gYWRkaXRpb24sIHNpZGUgZWZmZWN0cyBjYW4gaW50cm9kdWNlIGRlZmVjdHMgKGJ1Z3MpIHRoYXQgYXJlIGRpZmZpY3VsdCB0byB0cmFjZSwgZXNwZWNpYWxseSBpbiBsYXJnZSBjb2RlYmFzZXMuIENvbnNlcXVlbnRseSwgZnVuY3Rpb25zIHdpdGggc2lkZSBlZmZlY3RzIGFyZSBsZXNzIHByZWRpY3RhYmxlLCBhcyB0aGV5IG1heSBiZWhhdmUgZGlmZmVyZW50bHkgYmFzZWQgb24gZXh0ZXJuYWwgY29uZGl0aW9ucy4KCkluIHByYWN0aWNlLCB3aGlsZSB3ZSBvZnRlbiBuZWVkIHNpZGUgZWZmZWN0LCBpdCBpcyBhZHZpc2FibGUgdG8gbWFuYWdlIHNpZGUgZWZmZWN0cyBlZmZlY3RpdmVseSBhbmQgdG8gbWluaW1pemUgdGhlbSBhcyBtdWNoIGFzIGZlYXNpYmxlLiBVc2UgcHVyZSBmdW5jdGlvbnMgd2hlcmV2ZXIgcG9zc2libGUgYW5kIGxpbWl0IHNpZGUgZWZmZWN0cyB0byBzcGVjaWZpYyBwYXJ0cyBvZiB0aGUgY29kZS4gRW5jYXBzdWxhdGUgc2lkZSBlZmZlY3RzIHdpdGhpbiB3ZWxsLWRlZmluZWQgYm91bmRhcmllcywgc3VjaCBhcyBzcGVjaWZpYyBtb2R1bGVzLCBjbGFzc2VzLCBvciBsYXllcnMgb2YgdGhlIGFwcGxpY2F0aW9uLiBQcmVmZXIgaW1tdXRhYmxlIGRhdGEgc3RydWN0dXJlcyB0aGF0IGRvIG5vdCBjaGFuZ2Ugc3RhdGUgYWZ0ZXIgY3JlYXRpb24uIEFuZCwgZmluYWxseSwgaXNvbGF0ZSBzaWRlIGVmZmVjdHMgaW4gdGVzdHMsIHVzaW5nIHRlY2huaXF1ZXMgbGlrZSBtb2NraW5nIHRvIHNpbXVsYXRlIGludGVyYWN0aW9ucyB3aXRoIGV4dGVybmFsIHN5c3RlbXMuCgojIyBUZXN0aW5nIERhdGFiYXNlIENvZGUKCk1vZGlmaWNhdGlvbnMgb2YgZGF0YWJhc2VzIHRocm91Z2ggU1FMIHN0YXRlbWVudHMgb3IgdHJpZ2dlcnMgaXMgYSB0eXBlIG9mIHNpZGUgZWZmZWN0LiBUbyB0ZXN0IFNRTCBjb2RlIGFuZCB0cmlnZ2VycyB1c2luZyB0aGUgKip0ZXN0dGhhdCoqIHBhY2thZ2UsIHdlIG5lZWQgdG8gd3JpdGUgZnVuY3Rpb25zIHRoYXQgaW50ZXJhY3Qgd2l0aCB0aGUgZGF0YWJhc2UgYW5kIHBlcmZvcm0gdGhlIHJlcXVpcmVkIGNoZWNrcy4KCkxldCdzIHdhbGsgdGhyb3VnaCBhbiBleGFtcGxlIHVzaW5nIFNRTGl0ZS4gVGhlIHN0ZXBzIGFyZSBzaG93biBiZWxvdwoKIyMjIDEuICoqQ3JlYXRpbmcgYSBUZXN0IEVudmlyb25tZW50KioKCkNyZWF0ZSBhIHRlbXBvcmFyeSBTUUxpdGUgZGF0YWJhc2UsIHNldCB1cCB0aGUgbmVjZXNzYXJ5IHRhYmxlcyBhbmQgdHJpZ2dlcnMsIGFuZCBwb3B1bGF0ZSB0aGUgZGF0YWJhc2Ugd2l0aCBzeW50aGV0aWMgc2FtcGxlIGRhdGEuIEluIHRoZSBleGFtcGxlIGJlbG93LCB3ZSB1c2UgdGhlIHNwZWNpYWwgZGF0YWJhc2UgbmFtZSAiOm1lbW9yeToiIHdoaWNoIGNyZWF0ZXMgYSBTUUxpdGUgZGF0YWJhc2UgaW4gbWVtb3J5IHJhdGhlciB0aGFuIGluIHRoZSBmaWxlIHN5c3RlbS4gVGhlIGZ1bmN0aW9uIGBkYkV4ZWN1dGUoKWAgcmV0dXJucyBhIHN0YXR1cyBvZiAqMCogd2hlbiB0aGUgU1FMIGNvZGUgd2FzIGV4ZWN1dGVkIGNvcnJlY3RseS4gV2UgYXJlIG9taXR0aW5nIHRoZSBjaGVja3MgaW4gdGhlIGNvZGUgYmVsb3cgZm9yIGJyZXZpdHkuCgpgYGB7cn0KbGlicmFyeShSU1FMaXRlKQoKIyBDcmVhdGUgYSB0ZW1wb3JhcnkgaW4tbWVtb3ByeSBTUUxpdGUgZGF0YWJhc2UKY29uIDwtIGRiQ29ubmVjdChSU1FMaXRlOjpTUUxpdGUoKSwgIjptZW1vcnk6IikKCiMgQ3JlYXRlIHRhYmxlcwpzIDwtIGRiRXhlY3V0ZShjb24sIHBhc3RlMCgiQ1JFQVRFIFRBQkxFIHVzZXJzICgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiICBpZCBJTlRFR0VSIFBSSU1BUlkgS0VZLCAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiICBuYW1lIFRFWFQsICIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICIgIGxhc3RfdXBkYXRlZCBURVhUKSIpKQpzIDwtIGRiRXhlY3V0ZShjb24sIHBhc3RlMCgiQ1JFQVRFIFRBQkxFIG9yZGVycyAoIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIiAgb3JkZXJfaWQgSU5URUdFUiBQUklNQVJZIEtFWSwgIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIiAgdXNlcl9pZCBJTlRFR0VSLCAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiICBzdGF0dXMgVEVYVCwgIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIiAgRk9SRUlHTiBLRVkgKHVzZXJfaWQpIFJFRkVSRU5DRVMgdXNlcnMoaWQpKSIpKQpzIDwtIGRiRXhlY3V0ZShjb24sICJDUkVBVEUgVEFCTEUgYXVkaXRfbG9nIChsb2dfaWQgSU5URUdFUiBQUklNQVJZIEtFWSwgdXNlcl9pZCBJTlRFR0VSLCBhY3Rpb24gVEVYVCkiKQoKIyBDcmVhdGUgYSB0cmlnZ2VyCnMgPC0gZGJFeGVjdXRlKGNvbiwgIgogIENSRUFURSBUUklHR0VSIHVwZGF0ZV90aW1lc3RhbXAKICBBRlRFUiBVUERBVEUgT04gdXNlcnMKICBGT1IgRUFDSCBST1cKICBCRUdJTgogICAgVVBEQVRFIHVzZXJzIFNFVCBsYXN0X3VwZGF0ZWQgPSBDVVJSRU5UX1RJTUVTVEFNUCBXSEVSRSBpZCA9IE5FVy5pZDsKICAgIElOU0VSVCBJTlRPIGF1ZGl0X2xvZyAodXNlcl9pZCwgYWN0aW9uKSBWQUxVRVMgKE5FVy5pZCwgJ3VwZGF0ZWQnKTsKICBFTkQKIikKYGBgCgojIyMgMi4gKipXcml0aW5nIFRlc3RzIFVzaW5nKiogdGVzdHRoYXRcKlwqCgpOZXh0LCB3ZSB3cml0ZSB0ZXN0IGNhc2VzIGZvciB1bml0IHRlc3RpbmcsIGludGVncmF0aW9uIHRlc3RpbmcsIGFuZCBkYXRhIGludGVncml0eSB0ZXN0aW5nLgoKIyMjIyBVbml0IFRlc3RpbmcKCmBgYHtyfQpsaWJyYXJ5KHRlc3R0aGF0KQoKdGVzdF90aGF0KCJ0cmlnZ2VyIHVwZGF0ZXMgdGltZXN0YW1wIiwgewogICMgSW5zZXJ0IGEgdGVzdCByZWNvcmQKICBkYkV4ZWN1dGUoY29uLCAiSU5TRVJUIElOVE8gdXNlcnMgKGlkLCBuYW1lLCBsYXN0X3VwZGF0ZWQpIFZBTFVFUyAoMSwgJ0FsaWNlJywgJzIwMjMtMDEtMDEgMDA6MDA6MDAnKSIpCgogICMgVXBkYXRlIHRoZSB0ZXN0IHJlY29yZAogIGRiRXhlY3V0ZShjb24sICJVUERBVEUgdXNlcnMgU0VUIG5hbWUgPSAnQWxpY2UgVXBkYXRlZCcgV0hFUkUgaWQgPSAxIikKCiAgIyBDaGVjayBpZiB0aGUgdHJpZ2dlciB1cGRhdGVkIHRoZSB0aW1lc3RhbXAKICByZXN1bHQgPC0gZGJHZXRRdWVyeShjb24sICJTRUxFQ1QgbGFzdF91cGRhdGVkIEZST00gdXNlcnMgV0hFUkUgaWQgPSAxIikKICBleHBlY3RfZmFsc2UocmVzdWx0JGxhc3RfdXBkYXRlZCA9PSAnMjAyMy0wMS0wMSAwMDowMDowMCcpCn0pCmBgYAoKIyMjIyBJbnRlZ3JhdGlvbiBUZXN0aW5nCgpgYGB7cn0KdGVzdF90aGF0KCJpbnRlZ3JhdGlvbiBvZiB1c2VycyBhbmQgYXVkaXRfbG9nIiwgewogICMgSW5zZXJ0IGEgdGVzdCByZWNvcmQKICBkYkV4ZWN1dGUoY29uLCAiSU5TRVJUIElOVE8gdXNlcnMgKGlkLCBuYW1lKSBWQUxVRVMgKDIsICdCb2InKSIpCgogICMgVXBkYXRlIHRoZSB0ZXN0IHJlY29yZAogIGRiRXhlY3V0ZShjb24sICJVUERBVEUgdXNlcnMgU0VUIG5hbWUgPSAnQm9iIFVwZGF0ZWQnIFdIRVJFIGlkID0gMiIpCgogICMgQ2hlY2sgaWYgdGhlIHRyaWdnZXIgaW5zZXJ0ZWQgaW50byB0aGUgYXVkaXRfbG9nCiAgcmVzdWx0IDwtIGRiR2V0UXVlcnkoY29uLCAiU0VMRUNUICogRlJPTSBhdWRpdF9sb2cgV0hFUkUgdXNlcl9pZCA9IDIiKQogIGV4cGVjdF9lcXVhbChucm93KHJlc3VsdCksIDEpCiAgZXhwZWN0X2VxdWFsKHJlc3VsdCRhY3Rpb24sICd1cGRhdGVkJykKfSkKYGBgCgojIyMjIERhdGEgSW50ZWdyaXR5IFRlc3RpbmcKCmBgYHtyIGV2YWw9Rn0KdGVzdF90aGF0KCJmb3JlaWduIGtleSBjb25zdHJhaW50IHByZXZlbnRzIGRlbGV0aW9uIiwgewogICMgSW5zZXJ0IHRlc3QgcmVjb3JkcwogIGRiRXhlY3V0ZShjb24sICJJTlNFUlQgSU5UTyB1c2VycyAoaWQsIG5hbWUpIFZBTFVFUyAoMywgJ0NoYXJsaWUnKSIpCiAgZGJFeGVjdXRlKGNvbiwgIklOU0VSVCBJTlRPIG9yZGVycyAob3JkZXJfaWQsIHVzZXJfaWQsIHN0YXR1cykgVkFMVUVTICgxLCAzLCAncGVuZGluZycpIikKCiAgIyBBdHRlbXB0IHRvIGRlbGV0ZSB0aGUgdXNlciAoc2hvdWxkIGZhaWwgZHVlIHRvIGZvcmVpZ24ga2V5IGNvbnN0cmFpbnQpCiAgZXhwZWN0X2Vycm9yKGRiRXhlY3V0ZShjb24sICJERUxFVEUgRlJPTSB1c2VycyBXSEVSRSBpZCA9IDMiKSkKCiAgIyBWZXJpZnkgdGhhdCB0aGUgdXNlciBpcyBzdGlsbCBwcmVzZW50CiAgcmVzdWx0IDwtIGRiR2V0UXVlcnkoY29uLCAiU0VMRUNUICogRlJPTSB1c2VycyBXSEVSRSBpZCA9IDMiKQogIGV4cGVjdF9lcXVhbChucm93KHJlc3VsdCksIDEpCn0pCmBgYAoKIyMjIDMuICoqUnVubmluZyB0aGUgVGVzdHMqKgoKQXMgc2hvd24gYmVmb3JlLCB0byBydW4gdGhlIHRlc3RzLCB1c2UgdGhlIGB0ZXN0X2RpcmAgb3IgYHRlc3RfZmlsZWAgZnVuY3Rpb25zIGZyb20gdGhlIGB0ZXN0dGhhdGAgcGFja2FnZS4gSWYgeW91ciB0ZXN0cyBhcmUgaW4gYSBkaXJlY3RvcnkgY2FsbGVkICp0ZXN0cy90ZXN0dGhhdCosIHlvdSBjYW4gcnVuIHRoZW0gYWxsIHdpdGg6CgpgYGB7ciBldmFsPUZ9CnRlc3R0aGF0Ojp0ZXN0X2RpcigidGVzdHMvdGVzdHRoYXQiKQpgYGAKCk9yLCBpZiB5b3UgaGF2ZSB5b3VyIHRlc3RzIGluIGEgc2luZ2xlIGZpbGUsIHlvdSBjYW4gcnVuOgoKYGBge3IgZXZhbD1GfQp0ZXN0dGhhdDo6dGVzdF9maWxlKCJ0ZXN0cy90ZXN0dGhhdC90ZXN0X3NxbC5SIikKYGBgCgojIyBDb25jbHVzaW9uCgpFZmZlY3RpdmUgdGVzdGluZyBpcyB2aXRhbCBmb3IgZGVsaXZlcmluZyBoaWdoLXF1YWxpdHkgc29mdHdhcmUuIEJ5IHVuZGVyc3RhbmRpbmcgYW5kIGltcGxlbWVudGluZyBkaWZmZXJlbnQgdHlwZXMgb2YgdGVzdGluZywgeW91IGNhbiBlbnN1cmUgdGhhdCB5b3VyIHNvZnR3YXJlIG5vdCBvbmx5IG1lZXRzIHJlcXVpcmVtZW50cyBidXQgYWxzbyBwZXJmb3JtcyB3ZWxsIGluIHJlYWwtd29ybGQgc2NlbmFyaW9zLiBBZG9wdGluZyBhIGNvbXByZWhlbnNpdmUgdGVzdGluZyBzdHJhdGVneSBoZWxwcyBpbiBpZGVudGlmeWluZyBpc3N1ZXMgZWFybHksIHJlZHVjaW5nIGNvc3RzLCBhbmQgZW5oYW5jaW5nIHRoZSBvdmVyYWxsIHJlbGlhYmlsaXR5IGFuZCB1c2VyIHNhdGlzZmFjdGlvbiBvZiB5b3VyIHNvZnR3YXJlIHByb2R1Y3QuCgpVc2luZyB0aGUgKip0ZXN0dGhhdCoqIHBhY2thZ2UgaW4gUiwgeW91IGNhbiBlYXNpbHkgY3JlYXRlIGFuZCBydW4gYm90aCB1bml0IGFuZCBzeXN0ZW0gdGVzdHMgdG8gZW5zdXJlIHlvdXIgY29kZSBmdW5jdGlvbnMgYXMgaW50ZW5kZWQuIEJ5IGFkb3B0aW5nIGEgY29tcHJlaGVuc2l2ZSB0ZXN0aW5nIHN0cmF0ZWd5LCB5b3UgY2FuIGltcHJvdmUgdGhlIHJlbGlhYmlsaXR5IGFuZCBtYWludGFpbmFiaWxpdHkgb2YgeW91ciBSIHByb2plY3RzLgoKU2lkZSBlZmZlY3RzIGFyZSBhIGZ1bmRhbWVudGFsIGNvbmNlcHQgaW4gcHJvZ3JhbW1pbmcsIHJlcHJlc2VudGluZyBhbnkgaW50ZXJhY3Rpb24gd2l0aCBvciBtb2RpZmljYXRpb24gb2YgZXh0ZXJuYWwgc3RhdGUuIFdoaWxlIHRoZXkgYXJlIG5lY2Vzc2FyeSBmb3IgcmVhbC13b3JsZCBhcHBsaWNhdGlvbnMsIG1hbmFnaW5nIHRoZW0gZWZmZWN0aXZlbHkgaXMgY3J1Y2lhbCBmb3Igd3JpdGluZyByZWxpYWJsZSwgbWFpbnRhaW5hYmxlLCBhbmQgdGVzdGFibGUgY29kZS4gVW5kZXJzdGFuZGluZyBhbmQgY29udHJvbGxpbmcgc2lkZSBlZmZlY3RzIGNhbiBzaWduaWZpY2FudGx5IGltcHJvdmUgdGhlIHF1YWxpdHkgYW5kIHByZWRpY3RhYmlsaXR5IG9mIHNvZnR3YXJlLgoKQnkgdXNpbmcgKip0ZXN0dGhhdCoqLCB5b3UgY2FuIGVmZmVjdGl2ZWx5IHRlc3QgU1FMIGNvZGUgYW5kIHRyaWdnZXJzIHdpdGhpbiBSLiBUaGlzIGFwcHJvYWNoIGFsbG93cyB5b3UgdG8gd3JpdGUgY29tcHJlaGVuc2l2ZSB1bml0LCBpbnRlZ3JhdGlvbiwgYW5kIGRhdGEgaW50ZWdyaXR5IHRlc3RzLCBlbnN1cmluZyB5b3VyIFNRTCBvcGVyYXRpb25zIHBlcmZvcm0gYXMgZXhwZWN0ZWQgYW5kIG1haW50YWluIGRhdGEgaW50ZWdyaXR5LiBJbnRlZ3JhdGluZyB0aGVzZSB0ZXN0cyBpbnRvIHlvdXIgZGV2ZWxvcG1lbnQgd29ya2Zsb3cgaGVscHMgaWRlbnRpZnkgaXNzdWVzIGVhcmx5IGFuZCBpbXByb3ZlcyB0aGUgcmVsaWFiaWxpdHkgb2YgeW91ciBkYXRhYmFzZSBvcGVyYXRpb25zLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyBGaWxlcyAmIFJlc291cmNlcwoKYGBge3IgemlwRmlsZXMsIGVjaG89RkFMU0V9CnppcE5hbWUgPSBzcHJpbnRmKCJMZXNzb25GaWxlcy0lcy0lcy56aXAiLCAKICAgICAgICAgICAgICAgICBwYXJhbXMkY2F0ZWdvcnksCiAgICAgICAgICAgICAgICAgcGFyYW1zJG51bWJlcikKCnRleHRBTGluayA9IHBhc3RlMCgiQWxsIEZpbGVzIGZvciBMZXNzb24gIiwgCiAgICAgICAgICAgICAgIHBhcmFtcyRjYXRlZ29yeSwiLiIscGFyYW1zJG51bWJlcikKCiMgZG93bmxvYWRGaWxlc0xpbmsoKSBpcyBpbmNsdWRlZCBmcm9tIF9pbnNlcnQyREIuUgprbml0cjo6cmF3X2h0bWwoZG93bmxvYWRGaWxlc0xpbmsoIi4iLCB6aXBOYW1lLCB0ZXh0QUxpbmspKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMgUmVmZXJlbmNlcwoKTm9uZSB5ZXQuCgojIyBFcnJhdGEKCltMZXQgdXMga25vd10oaHR0cHM6Ly9mb3JtLmpvdGZvcm0uY29tLzIxMjE4NzA3Mjc4NDE1Nyl7dGFyZ2V0PSJfYmxhbmsifS4K