Date: 05/06/2022
To: The Univesity of Wyoming
From: Md Ashraful Islam Bhuiya
Subject: Estimation of the required number of
testings to estimate the prevalence of the asymptomatic disease in the
campus population as a whole
We analyzed the previous data to learn about the prevalence of the
asymptomatic disease on the University of Wyoming (UW) campus and used a
probability model to understand the effects of the number of tests on
the level of uncertainty of the prevalence. Surveillance testing informs
us if an asymptomatic person is positive or negative for the disease. As
the outcome from testing is either one of two possibilities (positive or
negative), and beta distribution ((the probability of positive cases))
tells us the probability of prevalence given the data, we analyzed the
data based on the beta distribution model. In this study, we used a
probability model to estimate how the number of tests relates to the
uncertainty of the prevalence of asymptomatic cases. We found that ~ 150
to ~250 testings per week give an estimate of the prevalence with a
fairly low level of uncertainty in the current situation.
1. Estimated prevalence throughout the semester including the
estimated level of uncertainty.
covid <- read.csv("uw_covidsurv_2022_updated.csv") # Load the dataset
covid <- covid[-10, ]
mean.prevalence <- (covid$NumberPositive + 1) / ( covid$NumberPositive + 1 + covid$NumberTested - covid$NumberPositive + 1 ) # Calculate mean prevalence using the equation for beta distribution.
plot(mean.prevalence, # plot mean prevalence.
yaxt="n", # remove the tick labels of the Y axis.
type="o",
xlab="week",
ylim = c(0, 0.16),
ylab = "Mean prevalence with uncertainty (95% ETPI)",
lwd=2,
main="Graph 1: Estimated prevalence with estimated level of uncertainty")
axis(2, at = seq(0.0, 0.18, by=0.01), las=1) # add specified tick labels to the Y axis.
abline(h=0.05, col="magenta", lwd=1.5) # add horizontal line in the graph.
text(10, 0.05, "Prevalence= 5%", pos=3) # add text at the specific location in the graph.
segments(1:nrow(covid), qbeta(0.975, covid$NumberPositive + 1, covid$NumberTested - covid$NumberPositive +1), 1:nrow(covid), qbeta(0.025, covid$NumberPositive + 1, covid$NumberTested - covid$NumberPositive +1), col = "blue", lwd=2) # add line segments for the estimated uncertainty of the prevalence for each time point. Uncertainty is estimated using qbeta() function for 95% equal tail probability interval.

In graph 1, we observe the mean prevalence (indicated by black
circles) of the disease each week throughout the semester. Blue lines
indicate the range of uncertainty of the given prevalence within the 95%
equal tail probability interval (ETPI) (from here onwards, I will refer
to this as the level of uncertainty) at each time point.The magenta line
indicates 5% prevalence. The maximum prevalence was found at week 3 when
the estimated prevalence was 12.4%, and from the estimated level of
uncertainty, we are 95% confident that the uncertainty for this
prevalence is only ~0.05 (~0.10 - ~0.15). For the estimated prevalence
of other weeks, the level of uncertainty is ~ 0.05 or less. For this low
level of uncertainty, we are confident enough about the prevalence in
each week as shown in the above graph. We can clearly distinguish the
prevalence from one week to another. We see that the highest prevalence
was at week 3 and the lowest was at week 7. The prevalence increased a
bit at week 14 compared to week 7 (~1% to ~4%). In subsequent analyses,
we will use a probability model (beta distribution model) to understand
how the prevalence and sample size (number of total tests) affects the
level of uncertainty.
2. Uncertainty regarding the numbner of positive of cases in the
campus population.
data_250 <- data.frame(tested= 250, # create a dataframe for 250 tests.
positive = 0:250)
plot(data_250$positive, (qbeta(0.975, data_250$positive + 1, data_250$tested - data_250$positive +1)- qbeta(0.025, data_250$positive + 1, data_250$tested - data_250$positive +1)), # plotting uncertainty vs prevalence.
yaxt="n",
type = 'l',
lwd=2,
col="orange",
xlab = "Number of positive cases out of 250 tests", ylab = "Uncertainty (95% ETPI)",
main = "Graph 2: Uncertainty vs positive cases")
axis(2, at = seq(0.0, 0.13, by=0.01), las=1 ) # add defined Y axis
points(3, (qbeta(0.975, 3+1, 250-3+1)-qbeta(0.025, 3+1, 250-3+1)), col='blue', pch=16, cex=1.5) # add points to the specific location of the graph.
text(3, (qbeta(0.975, 3+1, 250-3+1)-qbeta(0.025, 3+1, 250-3+1))+0.004, "3 '+ve' cases", cex=0.8, pos= 4, col= "black") # add texts at the specific location of the graph.
points(247, (qbeta(0.975, 247+1, 250-247+1)-qbeta(0.025, 247+1, 250-247+1)), col='blue', pch=16, cex=1.5)
text(247, (qbeta(0.975, 247+1, 250-247+1)-qbeta(0.025, 247+1, 250-247+1))+0.004, "247 '+ve' cases", cex=0.8, pos= 2, col= "black")
abline(h=(qbeta(0.975, 3+1, 250-3+1)-qbeta(0.025, 3+1, 250-3+1)), col="purple", lwd=1.5) # add horizontal line based on estimated uncertainty.
text(125, (qbeta(0.975, 3+1, 250-3+1)-qbeta(0.025, 3+1, 250-3+1)), "Uncertainty ~ 0.03", cex=0.8, pos= 1, col= "black")
points(75, (qbeta(0.975, 75+1, 250-75+1)-qbeta(0.025, 75+1, 250-75+1)), col='brown', pch=16, cex=1.5)
text(75, (qbeta(0.975, 75+1, 250-75+1)-qbeta(0.025, 75+1, 250-75+1))+0.004, "75 '+ve' cases", cex=0.8, pos= 2, col= "black")
points(175, (qbeta(0.975, 175+1, 250-175+1)-qbeta(0.025, 175+1, 250-175+1)), col='brown', pch=16, cex=1.5)
text(175, (qbeta(0.975, 175+1, 250-175+1)-qbeta(0.025, 175+1, 250-175+1))+0.004, "175 '+ve' cases", cex=0.8, pos= 4, col= "black")
abline(h=(qbeta(0.975, 75+1, 250-75+1)-qbeta(0.025, 75+1, 250-75+1)), col="magenta", lwd=1.5)
text(125, (qbeta(0.975, 75+1, 250-75+1)-qbeta(0.025, 75+1, 250-75+1)), "Uncertainty > 0.11", cex=0.8, pos= 1, col= "black")

Graph 2 shows how the level of uncertainty changes according to
different prevalence (different number of positive tests out of certain
number of tests). Here, uncertainty levels are plotted (orange line)
against 0% to 100% prevalence (0 to 250 positive cases out of 250
tests). Blue circles indicate the level of uncertainty for 3 and 247
positive tests. Magenta circles indicate the level of uncertainty for 75
and 175 positive cases. Purple line indicates the level of uncertainty ~
0.03 and magenta line indicates the level of uncertainty >0.11. We
find that with the increasing number of positive cases, the level of
uncertainty is also increased. If half of the total samples tested are
positive, the level of uncertainty is the highest at that point.
However, if more than half of the samples tested are positive, the level
of uncertainty again starts to decrease. After that mid point, the level
of uncertainty continue to decrease as more samples are found positive.
As examples, for 3 and 247 positive cases (near the left and right ends
of the graph) out of 250 tests, the level of uncertainty is only ~0.03
(shown with purple line), whereas, for 75 and 175 positive cases (around
the middle point of the graph), the level of uncertainty is >0.11
(shown with magenta line).
3. Uncertaintly is also affected by the sample size to some
extent.
# create different data frames of different number of tests.
data_1_percent <- data.frame(tested= seq(100, 2000, by=5),
positive = 0.01*(seq(100, 2000, by=5)))
data_3_percent <- data.frame(tested= seq(100, 2000, by=5),
positive = 0.03*(seq(100, 2000, by=5)))
data_5_percent <- data.frame(tested= seq(100, 2000, by=5),
positive = 0.05*(seq(100, 2000, by=5)))
data_25_percent <- data.frame(tested= seq(100, 2000, by=5),
positive = 0.25*(seq(100, 2000, by=5)))
data_50_percent <- data.frame(tested= seq(100, 2000, by=5),
positive = 0.5*(seq(100, 2000, by=5)))
data_100_percent <- data.frame(tested= seq(100, 2000, by=5),
positive = 1*(seq(100, 2000, by=5)))
# Plot data from above data frames for uncertainty vs sample size (number of tests).
plot(seq(100, 2000, by=5), (qbeta(0.975, data_1_percent$positive + 1, data_1_percent$tested - data_1_percent$positive +1)- qbeta(0.025, data_1_percent$positive + 1, data_1_percent$tested - data_1_percent$positive +1)),
xaxt="n",
yaxt= "n",
type = 'l',
lwd=2,
ylim = c(0, 0.2),
col="green",
xlab = "Number of tests (sample size)",
ylab = "Uncertainty (95% ETPI)",
main = "Graph 3: Uncertainty vs sample sizes and prevalence")
axis(1, at = seq(100, 2000, by=100), las=2 )
axis(2, at = seq(0.0, 0.2, by=0.01), las=1 )
legend(1500,0.2,
title = "Prevalence",
legend = c("0.5", "0.25", "0.05", "0.03", "0.01"),
lty = 1,
lwd = 2,
col=c("brown", "red", "orange", "blue", "green"),
cex= 0.8)
# add line in the graph for uncertainty vs number of tests for different prevalence. The following lines were added in the similar way.
lines(data_3_percent$tested, (qbeta(0.975, data_3_percent$positive + 1, data_3_percent$tested - data_3_percent$positive +1)- qbeta(0.025, data_3_percent$positive + 1, data_3_percent$tested - data_3_percent$positive +1)), type = 'l', lwd=2, ylim = c(0, 0.2), col="blue")
lines(data_5_percent$tested, (qbeta(0.975, data_5_percent$positive + 1, data_5_percent$tested - data_5_percent$positive +1)- qbeta(0.025, data_5_percent$positive + 1, data_5_percent$tested - data_5_percent$positive +1)), type = 'l', lwd=2, ylim = c(0, 0.2), col="orange")
lines(data_25_percent$tested, (qbeta(0.975, data_25_percent$positive + 1, data_25_percent$tested - data_25_percent$positive +1)- qbeta(0.025, data_25_percent$positive + 1, data_25_percent$tested - data_25_percent$positive +1)), type = 'l', lwd=2, ylim = c(0, 0.2), col="red")
lines(data_50_percent$tested, (qbeta(0.975, data_50_percent$positive + 1, data_50_percent$tested - data_50_percent$positive +1)- qbeta(0.025, data_50_percent$positive + 1, data_50_percent$tested - data_50_percent$positive +1)), type = 'l', lwd=2, ylim = c(0, 0.2), col="brown")
# add line segments and texts for a certain number of tests.
segments(300, 0.01, 300, 0.06, col="purple", lwd = 2)
segments(700,0.05, 700, 0.10, col="magenta", lwd = 2)
text(360, 0.06, "Tests = 300", srt=90, pos=3, cex=0.55)
text(755, 0.09, "Tests = 700", srt=90, pos=3, cex=0.55)

Graph 3 shows how uncertainty changes according to different number
of tests and different prevalence. Legend in the top right side of the
graph indicates specific colors of lines corresponding to specific
prevalence. Purple line segment indicates sample size = 300 and magenta
line segment indicates sample size= 700. We observe that the level of
uncertainty is clearly decreased as the sample size increases for a
certain prevalence. However, after some point, the changes in
uncertainty become very subtle as the sample size increases further.For
prevalence of 1% to 5%, the changes in uncertainty become subtle between
the number of tests ~ 250 to 350. So, we can suggest that if the
prevalence is low (0.01 - 0.05), number of tests from 250 to 350 is
enough to estimate the prevalence within overall population with
confidence (with very low level of uncertainty). Same for the sample
size 650 to 750 for the prevalence between 25% to 50%. As we can see
from graph 1, most of the time of the semester, especially in the recent
time, the prevalence is between 0% to <5%. Therefore, the current
level of sampling of the UW population (~3%, 250-500 people) should be
sufficient enough to track changes in disease prevalence and inform
policy.
4. An estimation of an optimum sample size given the level of
prevalence.
# Create different data frames of different sample sizes.
data_100 <- data.frame(tested= 100,
positive = 0:100)
data_250 <- data.frame(tested= 250,
positive = 0:250)
data_350 <- data.frame(tested= 350,
positive = 0:350)
data_500 <- data.frame(tested= 500,
positive = 0:500)
data_1000 <- data.frame(tested= 1000,
positive = 0:1000)
# Plot data from the above data frame for Uncertainty vs Prevalence for sample size=250.
plot((0:250)/250, (qbeta(0.975, data_250$positive + 1, data_250$tested - data_250$positive +1)- qbeta(0.025, data_250$positive + 1, data_250$tested - data_250$positive +1)),
xaxt="n",
yaxt= "n",
type = 'l',
col="Blue",
lwd=2,
ylim = c(0.0, 0.2),
xlab = "Prevalence",
ylab = "Uncertainty (95% ETPI)",
main = "Graph 4: Sample size affects uncertainty as a function of prevalences")
#specify the tick labels of X and Y axis manually.
axis(1, at = seq(0, 1, by=0.1), las=2 )
axis(2, at = seq(0, 0.2, by=0.01), las=1 )
text(250/500, max((qbeta(0.975, data_250$positive + 1, data_250$tested - data_250$positive +1)- qbeta(0.025, data_250$positive + 1, data_250$tested - data_250$positive +1))), "Samples tested=250", cex = 0.7, pos = 1, col = "blue") # Add text at the specific location in the graph.
abline(v=0.124, col="purple", lwd=1) # add a vertical line.
text(0.124, 0.2, "Prevalence= 12.4%", col = "purple", cex=0.7, pos= 2, srt= 90, lwd=1.5)
abline(v=0.05, col= "black")
text(0.04, 0.15, "Prevalence= 5%", col = "black", cex=0.7, pos= 2, srt= 90, lwd=1.5)
# Add lines to the graph for Uncertainty vs Prevalence for sample sizes 100, 350, 500, 1000.
lines((0:100)/100, (qbeta(0.975, data_100$positive + 1, data_100$tested - data_100$positive +1)- qbeta(0.025, data_100$positive + 1, data_100$tested - data_100$positive +1)), type = 'l', col="magenta", lwd=2)
text(250/500, max((qbeta(0.975, data_100$positive + 1, data_100$tested - data_100$positive +1)- qbeta(0.025, data_100$positive + 1, data_100$tested - data_100$positive +1))), "Samples tested=100", cex = 0.7, pos = 1, col = "magenta")
lines((0:350)/350, (qbeta(0.975, data_350$positive + 1, data_350$tested - data_350$positive +1)- qbeta(0.025, data_350$positive + 1, data_350$tested - data_350$positive +1)), type = 'l', col="orange", lwd=2)
text(250/500, max((qbeta(0.975, data_350$positive + 1, data_350$tested - data_350$positive +1)- qbeta(0.025, data_350$positive + 1, data_350$tested - data_350$positive +1))), "Samples tested=350", cex = 0.7, pos = 1, col = "orange")
lines((0:500)/500, (qbeta(0.975, data_500$positive + 1, data_500$tested - data_500$positive +1)- qbeta(0.025, data_500$positive + 1, data_500$tested - data_500$positive +1)), type = 'l', col="red", lwd=2)
text(250/500, max((qbeta(0.975, data_500$positive + 1, data_500$tested - data_500$positive +1)- qbeta(0.025, data_500$positive + 1, data_500$tested - data_500$positive +1))), "Samples tested=500", cex = 0.7, pos = 1, col = "red")
lines((0:1000)/1000, (qbeta(0.975, data_1000$positive + 1, data_1000$tested - data_1000$positive +1)- qbeta(0.025, data_1000$positive + 1, data_1000$tested - data_1000$positive +1)), type = 'l', col="brown", lwd=2)
text(250/500, max((qbeta(0.975, data_1000$positive + 1, data_1000$tested - data_1000$positive +1)- qbeta(0.025, data_1000$positive + 1, data_1000$tested - data_1000$positive +1))), "Samples tested=1000", cex = 0.7, pos = 1, col = "brown")

Graph 4 shows how the sample size affects the level of uncertainty
when estimated by accounting all prevalence. Here brown, red, orange,
blue, and magenta lines indicate uncertainty for sample sizes 1000, 500,
350, 250, and 100 respectively. The purple vertical line indicates the
prevalence of 12.4% and black vertical line indicates the prevalence of
5%. Overall, as the sample size is increased, the uncertainty is
decreased. If we consider the original prevalence throughout the
semester, the highest prevalence was 12.4%. At this point the highest
level of uncertainty is ~0.13 for the sample size 100 and the lowest is
~0.04 for sample size 1000 as indicated in the graph. So, with more 900
individual being tested, the uncertainty is reduced by only 0.09 when
the prevalence is 12.4%. The current prevalence is much lower (only
<5%), which itself reduces the uncertainty significantly as indicated
in graph 2, you will find it also in graph 4. Considering the above
phenomena that 900 more test reduces the uncertainty only 0.09 at the
time of highest (12.4%) prevalence and current situation of lower
prevalence (~ only 5%), I would not advise to sample more individuals if
the prevalence is not significantly higher than now. I would suggest to
tests even less samples (tests = ~150 - 250) than now (tests=250-350)
given the current prevalence. However, based on the above graph, if the
prevalence become ~15% (which never happened during the semester, so
highly unlikely) , I will suggest to increase the sample size up-to 300
- 350 (~ 100 - 150 more samples) to keep the level of uncertainty very
low (<0.1). If the prevalence is higher than this, the campus may be
closed to keep the spreading of disease under control.
5. Final recommendation
From the discussion above based on our probability model, we
understand how prevalence and sample size may affect the level of
uncertainty and their co-relationship. As a recap, for very low and high
prevalence, the level of uncertainty is very low compared to around the
middle value (50%) of the prevalence (graph 2 and 4) for any given
number of sample size. On the other hand, after a certain number of
sample size, the change in uncertainty become very low even for the
mid-prevalence (prevalence =50%, when uncertainty is the highest for a
given sample size)(graph 3 and 4). Which means regardless of how many
more samples you tests further, the level of uncertainty won’t change
noticeably. However, the scale (numbers of individuals to be tested each
week) depends on how precisely you want to estimate the prevalence, Or
in other words, how much uncertainty you want to tolerate for a given
prevalence. Lets see more precisely in the following table how scale are
related to precision (how low the uncertainty is).
library(kableExtra) # load library kableExtra for kable() function.
# create data frame as above.
data_5_percent <- data.frame(tested= seq(50, 1000, by=100),
positive = 0.05*(seq(50, 1000, by=100)))
data_5_percent$uncertainty <- (qbeta(0.975, data_5_percent$positive + 1, data_5_percent$tested - data_5_percent$positive +1)- qbeta(0.025, data_5_percent$positive + 1, data_5_percent$tested - data_5_percent$positive +1))
data_15_percent <- data.frame(tested= seq(50, 1000, by=100),
positive = 0.15*(seq(50, 1000, by=100)))
data_15_percent$uncertainty <- (qbeta(0.975, data_15_percent$positive + 1, data_15_percent$tested - data_15_percent$positive +1)- qbeta(0.025, data_15_percent$positive + 1, data_15_percent$tested - data_15_percent$positive +1))
data_compare <- data.frame(Tests= data_15_percent$tested,
Uncertainty_lowPreval. = round(data_5_percent$uncertainty, digits = 2),
Uncertainty_highPreval. = round(data_15_percent$uncertainty, digits = 2)
)
tbl1<- kable(data_compare, caption = "Table 1: An example of precision (how low the uncertainty is) vs sample size(Tests). lowPreval.= 5% prevalence, highPreval. = 15% prevalence") # convert the data frame into a customizable table.
column_spec(tbl1, 1:3, width = "2in") # customize the table with a caption and defined width of columns.
Table 1: An example of precision (how low the uncertainty is) vs sample size(Tests). lowPreval.= 5% prevalence, highPreval. = 15% prevalence
| Tests |
Uncertainty_lowPreval. |
Uncertainty_highPreval. |
| 50 |
0.13 |
0.20 |
| 150 |
0.07 |
0.11 |
| 250 |
0.06 |
0.09 |
| 350 |
0.05 |
0.07 |
| 450 |
0.04 |
0.07 |
| 550 |
0.04 |
0.06 |
| 650 |
0.03 |
0.05 |
| 750 |
0.03 |
0.05 |
| 850 |
0.03 |
0.05 |
| 950 |
0.03 |
0.05 |
In general, as we see from the table 1 (also from graph 4), higher
the sample size, more precise the estimation of the prevalence would be,
however, after a certain number of tests (for example, 650 tests, in
table 1) the change in the level of uncertainty does not noticeable.
Therefore, even to estimate the prevalence very precisely you don’t need
to perform unlimited number of tests for any given prevalence. As you
see in the above table, you can calculate exact scales based on
prevalence and expected precision level and then decide at which scale
you want to perform surveillance tests.
In my opinion, for the current low prevalence (< 5%, see graph 1)
in the UW campus, testing from ~150 to ~ 250 people each week even less
than that to some extent is sufficient to estimate the prevalence with
uncertainty only ~0.07 or less (table1, and graph 3). Final decision on
scale depends on the expectation of the UW testing program as discussed
earlier.
LS0tDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6DQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQotLS0NCg0KIyMjIyBEYXRlOiAwNS8wNi8yMDIyDQoNCiMjIyMgVG86ICAgIFRoZSBVbml2ZXNpdHkgb2YgV3lvbWluZw0KDQojIyMjIEZyb206ICBNZCBBc2hyYWZ1bCBJc2xhbSBCaHVpeWENCg0KIyMjIF9TdWJqZWN0OiAqKipFc3RpbWF0aW9uIG9mIHRoZSByZXF1aXJlZCBudW1iZXIgb2YgdGVzdGluZ3MgdG8gZXN0aW1hdGUgdGhlIHByZXZhbGVuY2Ugb2YgdGhlIGFzeW1wdG9tYXRpYyBkaXNlYXNlIGluIHRoZSBjYW1wdXMgcG9wdWxhdGlvbiBhcyBhIHdob2xlKioqIF8NCg0KV2UgYW5hbHl6ZWQgdGhlIHByZXZpb3VzIGRhdGEgdG8gbGVhcm4gYWJvdXQgdGhlIHByZXZhbGVuY2Ugb2YgdGhlIGFzeW1wdG9tYXRpYyBkaXNlYXNlIG9uIHRoZSBVbml2ZXJzaXR5IG9mIFd5b21pbmcgKFVXKSBjYW1wdXMgYW5kIHVzZWQgYSBwcm9iYWJpbGl0eSBtb2RlbCB0byB1bmRlcnN0YW5kIHRoZSBlZmZlY3RzIG9mIHRoZSBudW1iZXIgb2YgdGVzdHMgb24gdGhlIGxldmVsIG9mIHVuY2VydGFpbnR5IG9mIHRoZSBwcmV2YWxlbmNlLiBTdXJ2ZWlsbGFuY2UgdGVzdGluZyBpbmZvcm1zIHVzIGlmIGFuIGFzeW1wdG9tYXRpYyBwZXJzb24gaXMgcG9zaXRpdmUgb3IgbmVnYXRpdmUgZm9yIHRoZSBkaXNlYXNlLiBBcyB0aGUgb3V0Y29tZSBmcm9tIHRlc3RpbmcgaXMgZWl0aGVyIG9uZSBvZiB0d28gcG9zc2liaWxpdGllcyAocG9zaXRpdmUgb3IgbmVnYXRpdmUpLCBhbmQgYmV0YSBkaXN0cmlidXRpb24gKCh0aGUgcHJvYmFiaWxpdHkgb2YgcG9zaXRpdmUgY2FzZXMpKSB0ZWxscyB1cyB0aGUgcHJvYmFiaWxpdHkgb2YgcHJldmFsZW5jZSBnaXZlbiB0aGUgZGF0YSwgd2UgYW5hbHl6ZWQgdGhlIGRhdGEgYmFzZWQgb24gdGhlIGJldGEgZGlzdHJpYnV0aW9uIG1vZGVsLiBJbiB0aGlzIHN0dWR5LCB3ZSB1c2VkIGEgcHJvYmFiaWxpdHkgbW9kZWwgdG8gZXN0aW1hdGUgaG93IHRoZSBudW1iZXIgb2YgdGVzdHMgcmVsYXRlcyB0byB0aGUgdW5jZXJ0YWludHkgb2YgdGhlIHByZXZhbGVuY2Ugb2YgYXN5bXB0b21hdGljIGNhc2VzLiBXZSBmb3VuZCB0aGF0IH4gMTUwIHRvIH4yNTAgdGVzdGluZ3MgcGVyIHdlZWsgZ2l2ZSBhbiBlc3RpbWF0ZSBvZiB0aGUgcHJldmFsZW5jZSB3aXRoIGEgZmFpcmx5IGxvdyBsZXZlbCBvZiB1bmNlcnRhaW50eSBpbiB0aGUgY3VycmVudCBzaXR1YXRpb24uIA0KDQojIyMgMS4gRXN0aW1hdGVkIHByZXZhbGVuY2UgdGhyb3VnaG91dCB0aGUgc2VtZXN0ZXIgaW5jbHVkaW5nIHRoZSBlc3RpbWF0ZWQgbGV2ZWwgb2YgdW5jZXJ0YWludHkuDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRSB9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQprbml0cjo6b3B0c19rbml0JHNldChyb290LmRpciA9ICJHOi9NeSBEcml2ZS9Db3Vyc2VzL1NwcmluZzIwMjIvQ29tcHV0YXRpb25hbF9iaW9sb2d5L1Byb2plY3QtNF9TdXJ2ZWlsbGFuY2VfdGVzdGluZ19vZl9hc3ltcHRvbWF0aWNfZGlzZWFzZSIpDQpnZXR3ZCgpDQpgYGANCg0KYGBge3IsIGZpZy5oZWlnaHQ9NX0NCmNvdmlkIDwtIHJlYWQuY3N2KCJ1d19jb3ZpZHN1cnZfMjAyMl91cGRhdGVkLmNzdiIpICMgTG9hZCB0aGUgZGF0YXNldA0KY292aWQgPC0gY292aWRbLTEwLCBdDQptZWFuLnByZXZhbGVuY2UgPC0gKGNvdmlkJE51bWJlclBvc2l0aXZlICsgMSkgLyAoIGNvdmlkJE51bWJlclBvc2l0aXZlICsgMSArIGNvdmlkJE51bWJlclRlc3RlZCAtIGNvdmlkJE51bWJlclBvc2l0aXZlICsgMSApICMgQ2FsY3VsYXRlIG1lYW4gcHJldmFsZW5jZSB1c2luZyB0aGUgZXF1YXRpb24gZm9yIGJldGEgZGlzdHJpYnV0aW9uLg0KDQpwbG90KG1lYW4ucHJldmFsZW5jZSwgICAgICAjIHBsb3QgbWVhbiBwcmV2YWxlbmNlLg0KICAgICB5YXh0PSJuIiwgICAgICAgICAgICAgIyByZW1vdmUgdGhlIHRpY2sgbGFiZWxzIG9mIHRoZSBZIGF4aXMuDQogICAgIHR5cGU9Im8iLCANCiAgICAgeGxhYj0id2VlayIsIA0KICAgICB5bGltID0gYygwLCAwLjE2KSwgDQogICAgIHlsYWIgPSAiTWVhbiBwcmV2YWxlbmNlIHdpdGggdW5jZXJ0YWludHkgKDk1JSBFVFBJKSIsIA0KICAgICBsd2Q9MiwgDQogICAgIG1haW49IkdyYXBoIDE6IEVzdGltYXRlZCBwcmV2YWxlbmNlIHdpdGggZXN0aW1hdGVkIGxldmVsIG9mIHVuY2VydGFpbnR5IikNCmF4aXMoMiwgYXQgPSBzZXEoMC4wLCAwLjE4LCBieT0wLjAxKSwgbGFzPTEpICMgYWRkIHNwZWNpZmllZCB0aWNrIGxhYmVscyB0byB0aGUgWSBheGlzLg0KYWJsaW5lKGg9MC4wNSwgY29sPSJtYWdlbnRhIiwgbHdkPTEuNSkgICAgICAgIyBhZGQgaG9yaXpvbnRhbCBsaW5lIGluIHRoZSBncmFwaC4NCnRleHQoMTAsIDAuMDUsICJQcmV2YWxlbmNlPSA1JSIsIHBvcz0zKSAgICAgICMgYWRkIHRleHQgYXQgdGhlIHNwZWNpZmljIGxvY2F0aW9uIGluIHRoZSBncmFwaC4NCiANCnNlZ21lbnRzKDE6bnJvdyhjb3ZpZCksIHFiZXRhKDAuOTc1LCBjb3ZpZCROdW1iZXJQb3NpdGl2ZSArIDEsIGNvdmlkJE51bWJlclRlc3RlZCAtIGNvdmlkJE51bWJlclBvc2l0aXZlICsxKSwgMTpucm93KGNvdmlkKSwgcWJldGEoMC4wMjUsIGNvdmlkJE51bWJlclBvc2l0aXZlICsgMSwgY292aWQkTnVtYmVyVGVzdGVkIC0gY292aWQkTnVtYmVyUG9zaXRpdmUgKzEpLCBjb2wgPSAiYmx1ZSIsIGx3ZD0yKSAjIGFkZCBsaW5lIHNlZ21lbnRzIGZvciB0aGUgZXN0aW1hdGVkIHVuY2VydGFpbnR5IG9mIHRoZSBwcmV2YWxlbmNlIGZvciBlYWNoIHRpbWUgcG9pbnQuIFVuY2VydGFpbnR5IGlzIGVzdGltYXRlZCB1c2luZyBxYmV0YSgpIGZ1bmN0aW9uIGZvciA5NSUgZXF1YWwgdGFpbCBwcm9iYWJpbGl0eSBpbnRlcnZhbC4gIA0KYGBgDQpJbiBncmFwaCAxLCB3ZSBvYnNlcnZlIHRoZSBtZWFuIHByZXZhbGVuY2UgKGluZGljYXRlZCBieSBibGFjayBjaXJjbGVzKSBvZiB0aGUgZGlzZWFzZSBlYWNoIHdlZWsgdGhyb3VnaG91dCB0aGUgc2VtZXN0ZXIuIEJsdWUgbGluZXMgaW5kaWNhdGUgdGhlIHJhbmdlIG9mIHVuY2VydGFpbnR5IG9mIHRoZSBnaXZlbiBwcmV2YWxlbmNlIHdpdGhpbiB0aGUgOTUlIGVxdWFsIHRhaWwgcHJvYmFiaWxpdHkgaW50ZXJ2YWwgKEVUUEkpIChmcm9tIGhlcmUgb253YXJkcywgSSB3aWxsIHJlZmVyIHRvIHRoaXMgYXMgdGhlIGxldmVsIG9mIHVuY2VydGFpbnR5KSBhdCBlYWNoIHRpbWUgcG9pbnQuVGhlIG1hZ2VudGEgbGluZSBpbmRpY2F0ZXMgNSUgcHJldmFsZW5jZS4gVGhlIG1heGltdW0gcHJldmFsZW5jZSB3YXMgZm91bmQgYXQgd2VlayAzIHdoZW4gdGhlIGVzdGltYXRlZCBwcmV2YWxlbmNlIHdhcyAxMi40JSwgYW5kIGZyb20gdGhlIGVzdGltYXRlZCBsZXZlbCBvZiB1bmNlcnRhaW50eSwgd2UgYXJlIDk1JSBjb25maWRlbnQgdGhhdCB0aGUgdW5jZXJ0YWludHkgZm9yIHRoaXMgcHJldmFsZW5jZSBpcyBvbmx5IH4wLjA1ICh+MC4xMCAtIH4wLjE1KS4gRm9yIHRoZSBlc3RpbWF0ZWQgcHJldmFsZW5jZSBvZiBvdGhlciB3ZWVrcywgdGhlIGxldmVsIG9mIHVuY2VydGFpbnR5IGlzIH4gMC4wNSBvciBsZXNzLiBGb3IgdGhpcyBsb3cgbGV2ZWwgb2YgdW5jZXJ0YWludHksIHdlIGFyZSBjb25maWRlbnQgZW5vdWdoIGFib3V0IHRoZSBwcmV2YWxlbmNlIGluIGVhY2ggd2VlayBhcyBzaG93biBpbiB0aGUgYWJvdmUgZ3JhcGguIFdlIGNhbiBjbGVhcmx5IGRpc3Rpbmd1aXNoIHRoZSBwcmV2YWxlbmNlIGZyb20gb25lIHdlZWsgdG8gYW5vdGhlci4gV2Ugc2VlIHRoYXQgdGhlIGhpZ2hlc3QgcHJldmFsZW5jZSB3YXMgYXQgd2VlayAzIGFuZCB0aGUgbG93ZXN0IHdhcyBhdCB3ZWVrIDcuIFRoZSBwcmV2YWxlbmNlIGluY3JlYXNlZCBhIGJpdCBhdCB3ZWVrIDE0IGNvbXBhcmVkIHRvIHdlZWsgNyAofjElIHRvIH40JSkuIEluIHN1YnNlcXVlbnQgYW5hbHlzZXMsIHdlIHdpbGwgdXNlIGEgcHJvYmFiaWxpdHkgbW9kZWwgKGJldGEgZGlzdHJpYnV0aW9uIG1vZGVsKSB0byB1bmRlcnN0YW5kIGhvdyB0aGUgcHJldmFsZW5jZSBhbmQgc2FtcGxlIHNpemUgKG51bWJlciBvZiB0b3RhbCB0ZXN0cykgYWZmZWN0cyB0aGUgbGV2ZWwgb2YgdW5jZXJ0YWludHkuICANCg0KDQojIyMgMi4gVW5jZXJ0YWludHkgcmVnYXJkaW5nIHRoZSBudW1ibmVyIG9mIHBvc2l0aXZlIG9mIGNhc2VzIGluIHRoZSBjYW1wdXMgcG9wdWxhdGlvbi4NCmBgYHtyLCBmaWcuaGVpZ2h0PTV9DQpkYXRhXzI1MCA8LSBkYXRhLmZyYW1lKHRlc3RlZD0gMjUwLCAgIyBjcmVhdGUgYSBkYXRhZnJhbWUgZm9yIDI1MCB0ZXN0cy4NCiAgICAgICAgICAgICAgICAgICAgICBwb3NpdGl2ZSA9IDA6MjUwKQ0KcGxvdChkYXRhXzI1MCRwb3NpdGl2ZSwgKHFiZXRhKDAuOTc1LCBkYXRhXzI1MCRwb3NpdGl2ZSArIDEsIGRhdGFfMjUwJHRlc3RlZCAtIGRhdGFfMjUwJHBvc2l0aXZlICsxKS0gcWJldGEoMC4wMjUsIGRhdGFfMjUwJHBvc2l0aXZlICsgMSwgZGF0YV8yNTAkdGVzdGVkIC0gZGF0YV8yNTAkcG9zaXRpdmUgKzEpKSwgIyBwbG90dGluZyB1bmNlcnRhaW50eSB2cyBwcmV2YWxlbmNlLiANCiAgICAgeWF4dD0ibiIsDQogICAgIHR5cGUgPSAnbCcsIA0KICAgICBsd2Q9MiwgDQogICAgIGNvbD0ib3JhbmdlIiwgDQogICAgIHhsYWIgPSAiTnVtYmVyIG9mIHBvc2l0aXZlIGNhc2VzIG91dCBvZiAyNTAgdGVzdHMiLCB5bGFiID0gIlVuY2VydGFpbnR5ICg5NSUgRVRQSSkiLCANCiAgICAgbWFpbiA9ICJHcmFwaCAyOiBVbmNlcnRhaW50eSB2cyBwb3NpdGl2ZSBjYXNlcyIpDQpheGlzKDIsIGF0ID0gc2VxKDAuMCwgMC4xMywgYnk9MC4wMSksIGxhcz0xICkgIyBhZGQgZGVmaW5lZCBZIGF4aXMNCg0KcG9pbnRzKDMsIChxYmV0YSgwLjk3NSwgMysxLCAyNTAtMysxKS1xYmV0YSgwLjAyNSwgMysxLCAyNTAtMysxKSksIGNvbD0nYmx1ZScsIHBjaD0xNiwgY2V4PTEuNSkgICAgICAgICAgICAgICAgICAgICAgICAjIGFkZCBwb2ludHMgdG8gdGhlIHNwZWNpZmljIGxvY2F0aW9uIG9mIHRoZSBncmFwaC4gDQp0ZXh0KDMsIChxYmV0YSgwLjk3NSwgMysxLCAyNTAtMysxKS1xYmV0YSgwLjAyNSwgMysxLCAyNTAtMysxKSkrMC4wMDQsICIzICcrdmUnIGNhc2VzIiwgY2V4PTAuOCwgcG9zPSA0LCBjb2w9ICJibGFjayIpICMgYWRkIHRleHRzIGF0IHRoZSBzcGVjaWZpYyBsb2NhdGlvbiBvZiB0aGUgZ3JhcGguDQpwb2ludHMoMjQ3LCAocWJldGEoMC45NzUsIDI0NysxLCAyNTAtMjQ3KzEpLXFiZXRhKDAuMDI1LCAyNDcrMSwgMjUwLTI0NysxKSksIGNvbD0nYmx1ZScsIHBjaD0xNiwgY2V4PTEuNSkNCnRleHQoMjQ3LCAocWJldGEoMC45NzUsIDI0NysxLCAyNTAtMjQ3KzEpLXFiZXRhKDAuMDI1LCAyNDcrMSwgMjUwLTI0NysxKSkrMC4wMDQsICIyNDcgJyt2ZScgY2FzZXMiLCBjZXg9MC44LCBwb3M9IDIsIGNvbD0gImJsYWNrIikNCmFibGluZShoPShxYmV0YSgwLjk3NSwgMysxLCAyNTAtMysxKS1xYmV0YSgwLjAyNSwgMysxLCAyNTAtMysxKSksIGNvbD0icHVycGxlIiwgbHdkPTEuNSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBhZGQgaG9yaXpvbnRhbCBsaW5lIGJhc2VkIG9uIGVzdGltYXRlZCB1bmNlcnRhaW50eS4NCnRleHQoMTI1LCAocWJldGEoMC45NzUsIDMrMSwgMjUwLTMrMSktcWJldGEoMC4wMjUsIDMrMSwgMjUwLTMrMSkpLCAiVW5jZXJ0YWludHkgfiAwLjAzIiwgY2V4PTAuOCwgcG9zPSAxLCBjb2w9ICJibGFjayIpDQoNCnBvaW50cyg3NSwgKHFiZXRhKDAuOTc1LCA3NSsxLCAyNTAtNzUrMSktcWJldGEoMC4wMjUsIDc1KzEsIDI1MC03NSsxKSksIGNvbD0nYnJvd24nLCBwY2g9MTYsIGNleD0xLjUpDQp0ZXh0KDc1LCAocWJldGEoMC45NzUsIDc1KzEsIDI1MC03NSsxKS1xYmV0YSgwLjAyNSwgNzUrMSwgMjUwLTc1KzEpKSswLjAwNCwgIjc1ICcrdmUnIGNhc2VzIiwgY2V4PTAuOCwgcG9zPSAyLCBjb2w9ICJibGFjayIpDQpwb2ludHMoMTc1LCAocWJldGEoMC45NzUsIDE3NSsxLCAyNTAtMTc1KzEpLXFiZXRhKDAuMDI1LCAxNzUrMSwgMjUwLTE3NSsxKSksIGNvbD0nYnJvd24nLCBwY2g9MTYsIGNleD0xLjUpDQp0ZXh0KDE3NSwgKHFiZXRhKDAuOTc1LCAxNzUrMSwgMjUwLTE3NSsxKS1xYmV0YSgwLjAyNSwgMTc1KzEsIDI1MC0xNzUrMSkpKzAuMDA0LCAiMTc1ICcrdmUnIGNhc2VzIiwgY2V4PTAuOCwgcG9zPSA0LCBjb2w9ICJibGFjayIpDQphYmxpbmUoaD0ocWJldGEoMC45NzUsIDc1KzEsIDI1MC03NSsxKS1xYmV0YSgwLjAyNSwgNzUrMSwgMjUwLTc1KzEpKSwgY29sPSJtYWdlbnRhIiwgbHdkPTEuNSkgDQp0ZXh0KDEyNSwgKHFiZXRhKDAuOTc1LCA3NSsxLCAyNTAtNzUrMSktcWJldGEoMC4wMjUsIDc1KzEsIDI1MC03NSsxKSksICJVbmNlcnRhaW50eSA+IDAuMTEiLCBjZXg9MC44LCBwb3M9IDEsIGNvbD0gImJsYWNrIikNCmBgYA0KR3JhcGggMiBzaG93cyBob3cgdGhlIGxldmVsIG9mIHVuY2VydGFpbnR5IGNoYW5nZXMgYWNjb3JkaW5nIHRvIGRpZmZlcmVudCBwcmV2YWxlbmNlIChkaWZmZXJlbnQgbnVtYmVyIG9mIHBvc2l0aXZlIHRlc3RzIG91dCBvZiBjZXJ0YWluIG51bWJlciBvZiB0ZXN0cykuIEhlcmUsIHVuY2VydGFpbnR5IGxldmVscyBhcmUgcGxvdHRlZCAob3JhbmdlIGxpbmUpIGFnYWluc3QgMCUgdG8gMTAwJSBwcmV2YWxlbmNlICgwIHRvIDI1MCBwb3NpdGl2ZSBjYXNlcyBvdXQgb2YgMjUwIHRlc3RzKS4gQmx1ZSBjaXJjbGVzIGluZGljYXRlIHRoZSBsZXZlbCBvZiB1bmNlcnRhaW50eSBmb3IgMyBhbmQgMjQ3IHBvc2l0aXZlIHRlc3RzLiBNYWdlbnRhIGNpcmNsZXMgaW5kaWNhdGUgdGhlIGxldmVsIG9mIHVuY2VydGFpbnR5IGZvciA3NSBhbmQgMTc1IHBvc2l0aXZlIGNhc2VzLiBQdXJwbGUgbGluZSBpbmRpY2F0ZXMgdGhlIGxldmVsIG9mIHVuY2VydGFpbnR5IH4gMC4wMyBhbmQgbWFnZW50YSBsaW5lIGluZGljYXRlcyB0aGUgbGV2ZWwgb2YgdW5jZXJ0YWludHkgPjAuMTEuIFdlIGZpbmQgdGhhdCB3aXRoIHRoZSBpbmNyZWFzaW5nIG51bWJlciBvZiBwb3NpdGl2ZSBjYXNlcywgdGhlIGxldmVsIG9mIHVuY2VydGFpbnR5IGlzIGFsc28gaW5jcmVhc2VkLiBJZiBoYWxmIG9mIHRoZSB0b3RhbCBzYW1wbGVzIHRlc3RlZCBhcmUgcG9zaXRpdmUsIHRoZSBsZXZlbCBvZiB1bmNlcnRhaW50eSBpcyB0aGUgaGlnaGVzdCBhdCB0aGF0IHBvaW50LiBIb3dldmVyLCBpZiBtb3JlIHRoYW4gaGFsZiBvZiB0aGUgc2FtcGxlcyB0ZXN0ZWQgYXJlIHBvc2l0aXZlLCB0aGUgbGV2ZWwgb2YgdW5jZXJ0YWludHkgYWdhaW4gc3RhcnRzIHRvIGRlY3JlYXNlLiBBZnRlciB0aGF0IG1pZCBwb2ludCwgdGhlIGxldmVsIG9mIHVuY2VydGFpbnR5IGNvbnRpbnVlIHRvIGRlY3JlYXNlIGFzIG1vcmUgc2FtcGxlcyBhcmUgZm91bmQgcG9zaXRpdmUuIEFzIGV4YW1wbGVzLCBmb3IgMyBhbmQgMjQ3IHBvc2l0aXZlIGNhc2VzIChuZWFyIHRoZSBsZWZ0IGFuZCByaWdodCBlbmRzIG9mIHRoZSBncmFwaCkgb3V0IG9mIDI1MCB0ZXN0cywgdGhlIGxldmVsIG9mIHVuY2VydGFpbnR5IGlzIG9ubHkgfjAuMDMgKHNob3duIHdpdGggcHVycGxlIGxpbmUpLCB3aGVyZWFzLCBmb3IgNzUgYW5kIDE3NSBwb3NpdGl2ZSBjYXNlcyAoYXJvdW5kIHRoZSBtaWRkbGUgcG9pbnQgb2YgdGhlIGdyYXBoKSwgdGhlIGxldmVsIG9mIHVuY2VydGFpbnR5IGlzID4wLjExIChzaG93biB3aXRoIG1hZ2VudGEgbGluZSkuICANCg0KIyMjIDMuIFVuY2VydGFpbnRseSBpcyBhbHNvIGFmZmVjdGVkIGJ5IHRoZSBzYW1wbGUgc2l6ZSB0byBzb21lIGV4dGVudC4gDQpgYGB7ciwgZmlnLmhlaWdodD01fQ0KIyBjcmVhdGUgZGlmZmVyZW50IGRhdGEgZnJhbWVzIG9mIGRpZmZlcmVudCBudW1iZXIgb2YgdGVzdHMuIA0KDQpkYXRhXzFfcGVyY2VudCA8LSBkYXRhLmZyYW1lKHRlc3RlZD0gc2VxKDEwMCwgMjAwMCwgYnk9NSksDQogICAgICAgICAgICAgICAgICAgICAgcG9zaXRpdmUgPSAwLjAxKihzZXEoMTAwLCAyMDAwLCBieT01KSkpDQogICAgICAgICAgICAgICAgICAgICAgDQpkYXRhXzNfcGVyY2VudCA8LSBkYXRhLmZyYW1lKHRlc3RlZD0gc2VxKDEwMCwgMjAwMCwgYnk9NSksDQogICAgICAgICAgICAgICAgICAgICAgcG9zaXRpdmUgPSAwLjAzKihzZXEoMTAwLCAyMDAwLCBieT01KSkpDQoNCmRhdGFfNV9wZXJjZW50IDwtIGRhdGEuZnJhbWUodGVzdGVkPSBzZXEoMTAwLCAyMDAwLCBieT01KSwNCiAgICAgICAgICAgICAgICAgICAgICBwb3NpdGl2ZSA9IDAuMDUqKHNlcSgxMDAsIDIwMDAsIGJ5PTUpKSkNCg0KZGF0YV8yNV9wZXJjZW50IDwtIGRhdGEuZnJhbWUodGVzdGVkPSBzZXEoMTAwLCAyMDAwLCBieT01KSwNCiAgICAgICAgICAgICAgICAgICAgICBwb3NpdGl2ZSA9IDAuMjUqKHNlcSgxMDAsIDIwMDAsIGJ5PTUpKSkNCg0KZGF0YV81MF9wZXJjZW50IDwtIGRhdGEuZnJhbWUodGVzdGVkPSBzZXEoMTAwLCAyMDAwLCBieT01KSwNCiAgICAgICAgICAgICAgICAgICAgICBwb3NpdGl2ZSA9IDAuNSooc2VxKDEwMCwgMjAwMCwgYnk9NSkpKQ0KDQpkYXRhXzEwMF9wZXJjZW50IDwtIGRhdGEuZnJhbWUodGVzdGVkPSBzZXEoMTAwLCAyMDAwLCBieT01KSwNCiAgICAgICAgICAgICAgICAgICAgICBwb3NpdGl2ZSA9IDEqKHNlcSgxMDAsIDIwMDAsIGJ5PTUpKSkNCiAgICAgICAgICAgICAgICANCiMgUGxvdCBkYXRhIGZyb20gYWJvdmUgZGF0YSBmcmFtZXMgZm9yIHVuY2VydGFpbnR5IHZzIHNhbXBsZSBzaXplIChudW1iZXIgb2YgdGVzdHMpLiAgDQoNCnBsb3Qoc2VxKDEwMCwgMjAwMCwgYnk9NSksIChxYmV0YSgwLjk3NSwgZGF0YV8xX3BlcmNlbnQkcG9zaXRpdmUgKyAxLCBkYXRhXzFfcGVyY2VudCR0ZXN0ZWQgLSBkYXRhXzFfcGVyY2VudCRwb3NpdGl2ZSArMSktIHFiZXRhKDAuMDI1LCBkYXRhXzFfcGVyY2VudCRwb3NpdGl2ZSArIDEsIGRhdGFfMV9wZXJjZW50JHRlc3RlZCAtIGRhdGFfMV9wZXJjZW50JHBvc2l0aXZlICsxKSksIA0KICAgICB4YXh0PSJuIiwNCiAgICAgeWF4dD0gIm4iLA0KICAgICB0eXBlID0gJ2wnLCANCiAgICAgbHdkPTIsIA0KICAgICB5bGltID0gYygwLCAwLjIpLCANCiAgICAgY29sPSJncmVlbiIsIA0KICAgICB4bGFiID0gIk51bWJlciBvZiB0ZXN0cyAoc2FtcGxlIHNpemUpIiwgDQogICAgIHlsYWIgPSAiVW5jZXJ0YWludHkgKDk1JSBFVFBJKSIsDQogICAgIG1haW4gPSAiR3JhcGggMzogVW5jZXJ0YWludHkgdnMgc2FtcGxlIHNpemVzIGFuZCBwcmV2YWxlbmNlIikNCmF4aXMoMSwgYXQgPSBzZXEoMTAwLCAyMDAwLCBieT0xMDApLCBsYXM9MiApDQpheGlzKDIsIGF0ID0gc2VxKDAuMCwgMC4yLCBieT0wLjAxKSwgbGFzPTEgKQ0KbGVnZW5kKDE1MDAsMC4yLA0KICB0aXRsZSA9ICJQcmV2YWxlbmNlIiwNCiAgbGVnZW5kID0gYygiMC41IiwgIjAuMjUiLCAiMC4wNSIsICIwLjAzIiwgIjAuMDEiKSwNCiAgbHR5ID0gMSwNCiAgbHdkID0gMiwNCiAgY29sPWMoImJyb3duIiwgInJlZCIsICJvcmFuZ2UiLCAiYmx1ZSIsICJncmVlbiIpLA0KICBjZXg9IDAuOCkNCg0KIyBhZGQgbGluZSBpbiB0aGUgZ3JhcGggZm9yIHVuY2VydGFpbnR5IHZzIG51bWJlciBvZiB0ZXN0cyBmb3IgZGlmZmVyZW50IHByZXZhbGVuY2UuIFRoZSBmb2xsb3dpbmcgbGluZXMgd2VyZSBhZGRlZCBpbiB0aGUgc2ltaWxhciB3YXkuIA0KDQpsaW5lcyhkYXRhXzNfcGVyY2VudCR0ZXN0ZWQsIChxYmV0YSgwLjk3NSwgZGF0YV8zX3BlcmNlbnQkcG9zaXRpdmUgKyAxLCBkYXRhXzNfcGVyY2VudCR0ZXN0ZWQgLSBkYXRhXzNfcGVyY2VudCRwb3NpdGl2ZSArMSktIHFiZXRhKDAuMDI1LCBkYXRhXzNfcGVyY2VudCRwb3NpdGl2ZSArIDEsIGRhdGFfM19wZXJjZW50JHRlc3RlZCAtIGRhdGFfM19wZXJjZW50JHBvc2l0aXZlICsxKSksIHR5cGUgPSAnbCcsIGx3ZD0yLCB5bGltID0gYygwLCAwLjIpLCBjb2w9ImJsdWUiKSANCg0KbGluZXMoZGF0YV81X3BlcmNlbnQkdGVzdGVkLCAocWJldGEoMC45NzUsIGRhdGFfNV9wZXJjZW50JHBvc2l0aXZlICsgMSwgZGF0YV81X3BlcmNlbnQkdGVzdGVkIC0gZGF0YV81X3BlcmNlbnQkcG9zaXRpdmUgKzEpLSBxYmV0YSgwLjAyNSwgZGF0YV81X3BlcmNlbnQkcG9zaXRpdmUgKyAxLCBkYXRhXzVfcGVyY2VudCR0ZXN0ZWQgLSBkYXRhXzVfcGVyY2VudCRwb3NpdGl2ZSArMSkpLCB0eXBlID0gJ2wnLCBsd2Q9MiwgeWxpbSA9IGMoMCwgMC4yKSwgY29sPSJvcmFuZ2UiKQ0KDQpsaW5lcyhkYXRhXzI1X3BlcmNlbnQkdGVzdGVkLCAocWJldGEoMC45NzUsIGRhdGFfMjVfcGVyY2VudCRwb3NpdGl2ZSArIDEsIGRhdGFfMjVfcGVyY2VudCR0ZXN0ZWQgLSBkYXRhXzI1X3BlcmNlbnQkcG9zaXRpdmUgKzEpLSBxYmV0YSgwLjAyNSwgZGF0YV8yNV9wZXJjZW50JHBvc2l0aXZlICsgMSwgZGF0YV8yNV9wZXJjZW50JHRlc3RlZCAtIGRhdGFfMjVfcGVyY2VudCRwb3NpdGl2ZSArMSkpLCB0eXBlID0gJ2wnLCBsd2Q9MiwgeWxpbSA9IGMoMCwgMC4yKSwgY29sPSJyZWQiKQ0KDQpsaW5lcyhkYXRhXzUwX3BlcmNlbnQkdGVzdGVkLCAocWJldGEoMC45NzUsIGRhdGFfNTBfcGVyY2VudCRwb3NpdGl2ZSArIDEsIGRhdGFfNTBfcGVyY2VudCR0ZXN0ZWQgLSBkYXRhXzUwX3BlcmNlbnQkcG9zaXRpdmUgKzEpLSBxYmV0YSgwLjAyNSwgZGF0YV81MF9wZXJjZW50JHBvc2l0aXZlICsgMSwgZGF0YV81MF9wZXJjZW50JHRlc3RlZCAtIGRhdGFfNTBfcGVyY2VudCRwb3NpdGl2ZSArMSkpLCB0eXBlID0gJ2wnLCBsd2Q9MiwgeWxpbSA9IGMoMCwgMC4yKSwgY29sPSJicm93biIpDQoNCiMgYWRkIGxpbmUgc2VnbWVudHMgYW5kIHRleHRzIGZvciBhIGNlcnRhaW4gbnVtYmVyIG9mIHRlc3RzLiANCg0Kc2VnbWVudHMoMzAwLCAwLjAxLCAzMDAsIDAuMDYsIGNvbD0icHVycGxlIiwgbHdkID0gMikNCnNlZ21lbnRzKDcwMCwwLjA1LCA3MDAsIDAuMTAsIGNvbD0ibWFnZW50YSIsIGx3ZCA9IDIpDQp0ZXh0KDM2MCwgMC4wNiwgIlRlc3RzID0gMzAwIiwgc3J0PTkwLCBwb3M9MywgY2V4PTAuNTUpDQp0ZXh0KDc1NSwgMC4wOSwgIlRlc3RzID0gNzAwIiwgc3J0PTkwLCBwb3M9MywgY2V4PTAuNTUpDQpgYGANCkdyYXBoIDMgc2hvd3MgaG93IHVuY2VydGFpbnR5IGNoYW5nZXMgYWNjb3JkaW5nIHRvIGRpZmZlcmVudCBudW1iZXIgb2YgdGVzdHMgYW5kIGRpZmZlcmVudCBwcmV2YWxlbmNlLiBMZWdlbmQgaW4gdGhlIHRvcCByaWdodCBzaWRlIG9mIHRoZSBncmFwaCBpbmRpY2F0ZXMgc3BlY2lmaWMgY29sb3JzIG9mIGxpbmVzIGNvcnJlc3BvbmRpbmcgdG8gc3BlY2lmaWMgcHJldmFsZW5jZS4gUHVycGxlIGxpbmUgc2VnbWVudCBpbmRpY2F0ZXMgc2FtcGxlIHNpemUgPSAzMDAgYW5kIG1hZ2VudGEgbGluZSBzZWdtZW50IGluZGljYXRlcyBzYW1wbGUgc2l6ZT0gNzAwLiBXZSBvYnNlcnZlIHRoYXQgdGhlIGxldmVsIG9mIHVuY2VydGFpbnR5IGlzIGNsZWFybHkgZGVjcmVhc2VkIGFzIHRoZSBzYW1wbGUgc2l6ZSBpbmNyZWFzZXMgZm9yIGEgY2VydGFpbiBwcmV2YWxlbmNlLiBIb3dldmVyLCBhZnRlciBzb21lIHBvaW50LCB0aGUgY2hhbmdlcyBpbiB1bmNlcnRhaW50eSBiZWNvbWUgdmVyeSBzdWJ0bGUgYXMgdGhlIHNhbXBsZSBzaXplIGluY3JlYXNlcyBmdXJ0aGVyLkZvciBwcmV2YWxlbmNlIG9mIDElIHRvIDUlLCB0aGUgY2hhbmdlcyBpbiB1bmNlcnRhaW50eSBiZWNvbWUgc3VidGxlIGJldHdlZW4gdGhlIG51bWJlciBvZiB0ZXN0cyB+IDI1MCB0byAzNTAuIFNvLCB3ZSBjYW4gc3VnZ2VzdCB0aGF0IGlmIHRoZSBwcmV2YWxlbmNlIGlzIGxvdyAoMC4wMSAtIDAuMDUpLCBudW1iZXIgb2YgdGVzdHMgZnJvbSAyNTAgdG8gMzUwIGlzIGVub3VnaCB0byBlc3RpbWF0ZSB0aGUgcHJldmFsZW5jZSB3aXRoaW4gb3ZlcmFsbCBwb3B1bGF0aW9uIHdpdGggY29uZmlkZW5jZSAod2l0aCB2ZXJ5IGxvdyBsZXZlbCBvZiB1bmNlcnRhaW50eSkuIFNhbWUgZm9yIHRoZSBzYW1wbGUgc2l6ZSA2NTAgdG8gNzUwIGZvciB0aGUgcHJldmFsZW5jZSBiZXR3ZWVuIDI1JSB0byA1MCUuIEFzIHdlIGNhbiBzZWUgZnJvbSBncmFwaCAxLCBtb3N0IG9mIHRoZSB0aW1lIG9mIHRoZSBzZW1lc3RlciwgZXNwZWNpYWxseSBpbiB0aGUgcmVjZW50IHRpbWUsIHRoZSBwcmV2YWxlbmNlIGlzIGJldHdlZW4gMCUgdG8gPDUlLiBUaGVyZWZvcmUsIHRoZSBjdXJyZW50IGxldmVsIG9mIHNhbXBsaW5nIG9mIHRoZSBVVyBwb3B1bGF0aW9uICh+MyUsIDI1MC01MDAgcGVvcGxlKSBzaG91bGQgYmUgc3VmZmljaWVudCBlbm91Z2ggdG8gdHJhY2sgY2hhbmdlcyBpbiBkaXNlYXNlIHByZXZhbGVuY2UgYW5kIGluZm9ybSBwb2xpY3kuICAgIA0KDQojIyMgNC4gQW4gZXN0aW1hdGlvbiBvZiBhbiBvcHRpbXVtIHNhbXBsZSBzaXplIGdpdmVuIHRoZSBsZXZlbCBvZiBwcmV2YWxlbmNlLiANCmBgYHtyLCBmaWcuaGVpZ2h0PTV9DQojIENyZWF0ZSBkaWZmZXJlbnQgZGF0YSBmcmFtZXMgb2YgZGlmZmVyZW50IHNhbXBsZSBzaXplcy4gDQoNCmRhdGFfMTAwIDwtIGRhdGEuZnJhbWUodGVzdGVkPSAxMDAsDQogICAgICAgICAgICAgICAgICAgICAgcG9zaXRpdmUgPSAwOjEwMCkNCg0KZGF0YV8yNTAgPC0gZGF0YS5mcmFtZSh0ZXN0ZWQ9IDI1MCwNCiAgICAgICAgICAgICAgICAgICAgICBwb3NpdGl2ZSA9IDA6MjUwKQ0KDQpkYXRhXzM1MCA8LSBkYXRhLmZyYW1lKHRlc3RlZD0gMzUwLA0KICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aXZlID0gMDozNTApDQoNCmRhdGFfNTAwIDwtIGRhdGEuZnJhbWUodGVzdGVkPSA1MDAsDQogICAgICAgICAgICAgICAgICAgICAgcG9zaXRpdmUgPSAwOjUwMCkNCg0KZGF0YV8xMDAwIDwtIGRhdGEuZnJhbWUodGVzdGVkPSAxMDAwLA0KICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aXZlID0gMDoxMDAwKQ0KDQojIFBsb3QgZGF0YSBmcm9tIHRoZSBhYm92ZSBkYXRhIGZyYW1lIGZvciBVbmNlcnRhaW50eSB2cyBQcmV2YWxlbmNlIGZvciBzYW1wbGUgc2l6ZT0yNTAuICANCiAgICAgICAgICAgICAgICAgICAgDQpwbG90KCgwOjI1MCkvMjUwLCAocWJldGEoMC45NzUsIGRhdGFfMjUwJHBvc2l0aXZlICsgMSwgZGF0YV8yNTAkdGVzdGVkIC0gZGF0YV8yNTAkcG9zaXRpdmUgKzEpLSBxYmV0YSgwLjAyNSwgZGF0YV8yNTAkcG9zaXRpdmUgKyAxLCBkYXRhXzI1MCR0ZXN0ZWQgLSBkYXRhXzI1MCRwb3NpdGl2ZSArMSkpLCANCiAgICAgeGF4dD0ibiIsDQogICAgIHlheHQ9ICJuIiwNCiAgICAgdHlwZSA9ICdsJywgDQogICAgIGNvbD0iQmx1ZSIsDQogICAgIGx3ZD0yLA0KICAgICB5bGltID0gYygwLjAsIDAuMiksDQogICAgIHhsYWIgPSAiUHJldmFsZW5jZSIsIA0KICAgICB5bGFiID0gIlVuY2VydGFpbnR5ICg5NSUgRVRQSSkiLCANCiAgICAgbWFpbiA9ICJHcmFwaCA0OiBTYW1wbGUgc2l6ZSBhZmZlY3RzIHVuY2VydGFpbnR5IGFzIGEgZnVuY3Rpb24gb2YgcHJldmFsZW5jZXMiKQ0KDQojc3BlY2lmeSB0aGUgdGljayBsYWJlbHMgb2YgWCBhbmQgWSBheGlzIG1hbnVhbGx5Lg0KYXhpcygxLCBhdCA9IHNlcSgwLCAxLCBieT0wLjEpLCBsYXM9MiApDQpheGlzKDIsIGF0ID0gc2VxKDAsIDAuMiwgYnk9MC4wMSksIGxhcz0xICkNCg0KdGV4dCgyNTAvNTAwLCBtYXgoKHFiZXRhKDAuOTc1LCBkYXRhXzI1MCRwb3NpdGl2ZSArIDEsIGRhdGFfMjUwJHRlc3RlZCAtIGRhdGFfMjUwJHBvc2l0aXZlICsxKS0gcWJldGEoMC4wMjUsIGRhdGFfMjUwJHBvc2l0aXZlICsgMSwgZGF0YV8yNTAkdGVzdGVkIC0gZGF0YV8yNTAkcG9zaXRpdmUgKzEpKSksICJTYW1wbGVzIHRlc3RlZD0yNTAiLCBjZXggPSAwLjcsIHBvcyA9IDEsIGNvbCA9ICJibHVlIikgIyBBZGQgdGV4dCBhdCB0aGUgc3BlY2lmaWMgbG9jYXRpb24gaW4gdGhlIGdyYXBoLg0KYWJsaW5lKHY9MC4xMjQsIGNvbD0icHVycGxlIiwgbHdkPTEpICAgICAgICAgICAjIGFkZCBhIHZlcnRpY2FsIGxpbmUuDQp0ZXh0KDAuMTI0LCAwLjIsICJQcmV2YWxlbmNlPSAxMi40JSIsIGNvbCA9ICJwdXJwbGUiLCBjZXg9MC43LCBwb3M9IDIsIHNydD0gOTAsIGx3ZD0xLjUpDQphYmxpbmUodj0wLjA1LCBjb2w9ICJibGFjayIpDQp0ZXh0KDAuMDQsIDAuMTUsICJQcmV2YWxlbmNlPSA1JSIsIGNvbCA9ICJibGFjayIsIGNleD0wLjcsIHBvcz0gMiwgc3J0PSA5MCwgbHdkPTEuNSkNCg0KIyBBZGQgbGluZXMgdG8gdGhlIGdyYXBoIGZvciBVbmNlcnRhaW50eSB2cyBQcmV2YWxlbmNlIGZvciBzYW1wbGUgc2l6ZXMgMTAwLCAzNTAsIDUwMCwgMTAwMC4NCg0KbGluZXMoKDA6MTAwKS8xMDAsIChxYmV0YSgwLjk3NSwgZGF0YV8xMDAkcG9zaXRpdmUgKyAxLCBkYXRhXzEwMCR0ZXN0ZWQgLSBkYXRhXzEwMCRwb3NpdGl2ZSArMSktIHFiZXRhKDAuMDI1LCBkYXRhXzEwMCRwb3NpdGl2ZSArIDEsIGRhdGFfMTAwJHRlc3RlZCAtIGRhdGFfMTAwJHBvc2l0aXZlICsxKSksIHR5cGUgPSAnbCcsIGNvbD0ibWFnZW50YSIsIGx3ZD0yKQ0KdGV4dCgyNTAvNTAwLCBtYXgoKHFiZXRhKDAuOTc1LCBkYXRhXzEwMCRwb3NpdGl2ZSArIDEsIGRhdGFfMTAwJHRlc3RlZCAtIGRhdGFfMTAwJHBvc2l0aXZlICsxKS0gcWJldGEoMC4wMjUsIGRhdGFfMTAwJHBvc2l0aXZlICsgMSwgZGF0YV8xMDAkdGVzdGVkIC0gZGF0YV8xMDAkcG9zaXRpdmUgKzEpKSksICJTYW1wbGVzIHRlc3RlZD0xMDAiLCBjZXggPSAwLjcsIHBvcyA9IDEsIGNvbCA9ICJtYWdlbnRhIikNCg0KbGluZXMoKDA6MzUwKS8zNTAsIChxYmV0YSgwLjk3NSwgZGF0YV8zNTAkcG9zaXRpdmUgKyAxLCBkYXRhXzM1MCR0ZXN0ZWQgLSBkYXRhXzM1MCRwb3NpdGl2ZSArMSktIHFiZXRhKDAuMDI1LCBkYXRhXzM1MCRwb3NpdGl2ZSArIDEsIGRhdGFfMzUwJHRlc3RlZCAtIGRhdGFfMzUwJHBvc2l0aXZlICsxKSksIHR5cGUgPSAnbCcsIGNvbD0ib3JhbmdlIiwgbHdkPTIpDQp0ZXh0KDI1MC81MDAsIG1heCgocWJldGEoMC45NzUsIGRhdGFfMzUwJHBvc2l0aXZlICsgMSwgZGF0YV8zNTAkdGVzdGVkIC0gZGF0YV8zNTAkcG9zaXRpdmUgKzEpLSBxYmV0YSgwLjAyNSwgZGF0YV8zNTAkcG9zaXRpdmUgKyAxLCBkYXRhXzM1MCR0ZXN0ZWQgLSBkYXRhXzM1MCRwb3NpdGl2ZSArMSkpKSwgIlNhbXBsZXMgdGVzdGVkPTM1MCIsIGNleCA9IDAuNywgcG9zID0gMSwgY29sID0gIm9yYW5nZSIpDQoNCmxpbmVzKCgwOjUwMCkvNTAwLCAocWJldGEoMC45NzUsIGRhdGFfNTAwJHBvc2l0aXZlICsgMSwgZGF0YV81MDAkdGVzdGVkIC0gZGF0YV81MDAkcG9zaXRpdmUgKzEpLSBxYmV0YSgwLjAyNSwgZGF0YV81MDAkcG9zaXRpdmUgKyAxLCBkYXRhXzUwMCR0ZXN0ZWQgLSBkYXRhXzUwMCRwb3NpdGl2ZSArMSkpLCB0eXBlID0gJ2wnLCBjb2w9InJlZCIsIGx3ZD0yKQ0KdGV4dCgyNTAvNTAwLCBtYXgoKHFiZXRhKDAuOTc1LCBkYXRhXzUwMCRwb3NpdGl2ZSArIDEsIGRhdGFfNTAwJHRlc3RlZCAtIGRhdGFfNTAwJHBvc2l0aXZlICsxKS0gcWJldGEoMC4wMjUsIGRhdGFfNTAwJHBvc2l0aXZlICsgMSwgZGF0YV81MDAkdGVzdGVkIC0gZGF0YV81MDAkcG9zaXRpdmUgKzEpKSksICJTYW1wbGVzIHRlc3RlZD01MDAiLCBjZXggPSAwLjcsIHBvcyA9IDEsIGNvbCA9ICJyZWQiKQ0KDQpsaW5lcygoMDoxMDAwKS8xMDAwLCAocWJldGEoMC45NzUsIGRhdGFfMTAwMCRwb3NpdGl2ZSArIDEsIGRhdGFfMTAwMCR0ZXN0ZWQgLSBkYXRhXzEwMDAkcG9zaXRpdmUgKzEpLSBxYmV0YSgwLjAyNSwgZGF0YV8xMDAwJHBvc2l0aXZlICsgMSwgZGF0YV8xMDAwJHRlc3RlZCAtIGRhdGFfMTAwMCRwb3NpdGl2ZSArMSkpLCB0eXBlID0gJ2wnLCBjb2w9ImJyb3duIiwgbHdkPTIpDQp0ZXh0KDI1MC81MDAsIG1heCgocWJldGEoMC45NzUsIGRhdGFfMTAwMCRwb3NpdGl2ZSArIDEsIGRhdGFfMTAwMCR0ZXN0ZWQgLSBkYXRhXzEwMDAkcG9zaXRpdmUgKzEpLSBxYmV0YSgwLjAyNSwgZGF0YV8xMDAwJHBvc2l0aXZlICsgMSwgZGF0YV8xMDAwJHRlc3RlZCAtIGRhdGFfMTAwMCRwb3NpdGl2ZSArMSkpKSwgIlNhbXBsZXMgdGVzdGVkPTEwMDAiLCBjZXggPSAwLjcsIHBvcyA9IDEsIGNvbCA9ICJicm93biIpDQpgYGANCkdyYXBoIDQgc2hvd3MgaG93IHRoZSBzYW1wbGUgc2l6ZSBhZmZlY3RzIHRoZSBsZXZlbCBvZiB1bmNlcnRhaW50eSB3aGVuIGVzdGltYXRlZCBieSBhY2NvdW50aW5nIGFsbCBwcmV2YWxlbmNlLiBIZXJlIGJyb3duLCByZWQsIG9yYW5nZSwgYmx1ZSwgYW5kIG1hZ2VudGEgbGluZXMgaW5kaWNhdGUgdW5jZXJ0YWludHkgZm9yIHNhbXBsZSBzaXplcyAxMDAwLCA1MDAsIDM1MCwgMjUwLCBhbmQgMTAwIHJlc3BlY3RpdmVseS4gVGhlIHB1cnBsZSB2ZXJ0aWNhbCBsaW5lIGluZGljYXRlcyB0aGUgcHJldmFsZW5jZSBvZiAxMi40JSBhbmQgYmxhY2sgdmVydGljYWwgbGluZSBpbmRpY2F0ZXMgdGhlIHByZXZhbGVuY2Ugb2YgNSUuIE92ZXJhbGwsIGFzIHRoZSBzYW1wbGUgc2l6ZSBpcyBpbmNyZWFzZWQsIHRoZSB1bmNlcnRhaW50eSBpcyBkZWNyZWFzZWQuIElmIHdlIGNvbnNpZGVyIHRoZSBvcmlnaW5hbCBwcmV2YWxlbmNlIHRocm91Z2hvdXQgdGhlIHNlbWVzdGVyLCB0aGUgaGlnaGVzdCBwcmV2YWxlbmNlIHdhcyAxMi40JS4gQXQgdGhpcyBwb2ludCB0aGUgaGlnaGVzdCBsZXZlbCBvZiB1bmNlcnRhaW50eSBpcyB+MC4xMyBmb3IgdGhlIHNhbXBsZSBzaXplIDEwMCBhbmQgdGhlIGxvd2VzdCBpcyB+MC4wNCBmb3Igc2FtcGxlIHNpemUgMTAwMCBhcyBpbmRpY2F0ZWQgaW4gdGhlIGdyYXBoLiBTbywgd2l0aCBtb3JlIDkwMCBpbmRpdmlkdWFsIGJlaW5nIHRlc3RlZCwgdGhlIHVuY2VydGFpbnR5IGlzIHJlZHVjZWQgYnkgb25seSAwLjA5IHdoZW4gdGhlIHByZXZhbGVuY2UgaXMgMTIuNCUuIFRoZSBjdXJyZW50IHByZXZhbGVuY2UgaXMgbXVjaCBsb3dlciAob25seSA8NSUpLCB3aGljaCBpdHNlbGYgcmVkdWNlcyB0aGUgdW5jZXJ0YWludHkgc2lnbmlmaWNhbnRseSBhcyBpbmRpY2F0ZWQgaW4gZ3JhcGggMiwgeW91IHdpbGwgZmluZCBpdCBhbHNvIGluIGdyYXBoIDQuIENvbnNpZGVyaW5nIHRoZSBhYm92ZSBwaGVub21lbmEgdGhhdCA5MDAgbW9yZSB0ZXN0IHJlZHVjZXMgdGhlIHVuY2VydGFpbnR5IG9ubHkgMC4wOSBhdCB0aGUgdGltZSBvZiBoaWdoZXN0ICgxMi40JSkgcHJldmFsZW5jZSBhbmQgY3VycmVudCBzaXR1YXRpb24gb2YgbG93ZXIgcHJldmFsZW5jZSAofiBvbmx5IDUlKSwgSSB3b3VsZCBub3QgYWR2aXNlIHRvIHNhbXBsZSBtb3JlIGluZGl2aWR1YWxzIGlmIHRoZSBwcmV2YWxlbmNlIGlzIG5vdCBzaWduaWZpY2FudGx5IGhpZ2hlciB0aGFuIG5vdy4gSSB3b3VsZCBzdWdnZXN0IHRvIHRlc3RzIGV2ZW4gbGVzcyBzYW1wbGVzICh0ZXN0cyA9IH4xNTAgLSAyNTApIHRoYW4gbm93ICh0ZXN0cz0yNTAtMzUwKSBnaXZlbiB0aGUgY3VycmVudCBwcmV2YWxlbmNlLiBIb3dldmVyLCBiYXNlZCBvbiB0aGUgYWJvdmUgZ3JhcGgsIGlmIHRoZSBwcmV2YWxlbmNlIGJlY29tZSB+MTUlICh3aGljaCBuZXZlciBoYXBwZW5lZCBkdXJpbmcgdGhlIHNlbWVzdGVyLCBzbyBoaWdobHkgdW5saWtlbHkpICwgSSB3aWxsIHN1Z2dlc3QgdG8gaW5jcmVhc2UgdGhlIHNhbXBsZSBzaXplIHVwLXRvIDMwMCAtIDM1MCAofiAxMDAgLSAxNTAgbW9yZSBzYW1wbGVzKSB0byBrZWVwIHRoZSBsZXZlbCBvZiB1bmNlcnRhaW50eSB2ZXJ5IGxvdyAoPDAuMSkuIElmIHRoZSBwcmV2YWxlbmNlIGlzIGhpZ2hlciB0aGFuIHRoaXMsIHRoZSBjYW1wdXMgbWF5IGJlIGNsb3NlZCB0byBrZWVwIHRoZSBzcHJlYWRpbmcgb2YgZGlzZWFzZSB1bmRlciBjb250cm9sLg0KDQojIyMgNS4gRmluYWwgcmVjb21tZW5kYXRpb24NCkZyb20gdGhlIGRpc2N1c3Npb24gYWJvdmUgYmFzZWQgb24gb3VyIHByb2JhYmlsaXR5IG1vZGVsLCB3ZSB1bmRlcnN0YW5kIGhvdyBwcmV2YWxlbmNlIGFuZCBzYW1wbGUgc2l6ZSBtYXkgYWZmZWN0IHRoZSBsZXZlbCBvZiB1bmNlcnRhaW50eSBhbmQgdGhlaXIgY28tcmVsYXRpb25zaGlwLiBBcyBhIHJlY2FwLCBmb3IgdmVyeSBsb3cgYW5kIGhpZ2ggcHJldmFsZW5jZSwgdGhlIGxldmVsIG9mIHVuY2VydGFpbnR5IGlzIHZlcnkgbG93IGNvbXBhcmVkIHRvIGFyb3VuZCB0aGUgbWlkZGxlIHZhbHVlICg1MCUpIG9mIHRoZSBwcmV2YWxlbmNlIChncmFwaCAyIGFuZCA0KSBmb3IgYW55IGdpdmVuIG51bWJlciBvZiBzYW1wbGUgc2l6ZS4gT24gdGhlIG90aGVyIGhhbmQsIGFmdGVyIGEgY2VydGFpbiBudW1iZXIgb2Ygc2FtcGxlIHNpemUsIHRoZSBjaGFuZ2UgaW4gdW5jZXJ0YWludHkgYmVjb21lIHZlcnkgbG93IGV2ZW4gZm9yIHRoZSBtaWQtcHJldmFsZW5jZSAocHJldmFsZW5jZSA9NTAlLCB3aGVuIHVuY2VydGFpbnR5IGlzIHRoZSBoaWdoZXN0IGZvciBhIGdpdmVuIHNhbXBsZSBzaXplKShncmFwaCAzIGFuZCA0KS4gV2hpY2ggbWVhbnMgcmVnYXJkbGVzcyBvZiBob3cgbWFueSBtb3JlIHNhbXBsZXMgeW91IHRlc3RzIGZ1cnRoZXIsIHRoZSBsZXZlbCBvZiB1bmNlcnRhaW50eSB3b24ndCBjaGFuZ2Ugbm90aWNlYWJseS4gIEhvd2V2ZXIsIHRoZSBzY2FsZSAobnVtYmVycyBvZiBpbmRpdmlkdWFscyB0byBiZSB0ZXN0ZWQgZWFjaCB3ZWVrKSBkZXBlbmRzIG9uIGhvdyBwcmVjaXNlbHkgeW91IHdhbnQgdG8gZXN0aW1hdGUgdGhlIHByZXZhbGVuY2UsIE9yIGluIG90aGVyIHdvcmRzLCBob3cgbXVjaCB1bmNlcnRhaW50eSB5b3Ugd2FudCB0byB0b2xlcmF0ZSBmb3IgYSBnaXZlbiBwcmV2YWxlbmNlLiBMZXRzIHNlZSBtb3JlIHByZWNpc2VseSBpbiB0aGUgZm9sbG93aW5nIHRhYmxlIGhvdyBzY2FsZSBhcmUgcmVsYXRlZCB0byBwcmVjaXNpb24gKGhvdyBsb3cgdGhlIHVuY2VydGFpbnR5IGlzKS4NCmBgYHtyfQ0KbGlicmFyeShrYWJsZUV4dHJhKSAjIGxvYWQgbGlicmFyeSBrYWJsZUV4dHJhIGZvciBrYWJsZSgpIGZ1bmN0aW9uLg0KDQojIGNyZWF0ZSBkYXRhIGZyYW1lIGFzIGFib3ZlLg0KZGF0YV81X3BlcmNlbnQgPC0gZGF0YS5mcmFtZSh0ZXN0ZWQ9IHNlcSg1MCwgMTAwMCwgYnk9MTAwKSwNCiAgICAgICAgICAgICAgICAgICAgICBwb3NpdGl2ZSA9IDAuMDUqKHNlcSg1MCwgMTAwMCwgYnk9MTAwKSkpDQoNCmRhdGFfNV9wZXJjZW50JHVuY2VydGFpbnR5IDwtIChxYmV0YSgwLjk3NSwgZGF0YV81X3BlcmNlbnQkcG9zaXRpdmUgKyAxLCBkYXRhXzVfcGVyY2VudCR0ZXN0ZWQgLSBkYXRhXzVfcGVyY2VudCRwb3NpdGl2ZSArMSktIHFiZXRhKDAuMDI1LCBkYXRhXzVfcGVyY2VudCRwb3NpdGl2ZSArIDEsIGRhdGFfNV9wZXJjZW50JHRlc3RlZCAtIGRhdGFfNV9wZXJjZW50JHBvc2l0aXZlICsxKSkNCg0KZGF0YV8xNV9wZXJjZW50IDwtIGRhdGEuZnJhbWUodGVzdGVkPSBzZXEoNTAsIDEwMDAsIGJ5PTEwMCksDQogICAgICAgICAgICAgICAgICAgICAgcG9zaXRpdmUgPSAwLjE1KihzZXEoNTAsIDEwMDAsIGJ5PTEwMCkpKQ0KZGF0YV8xNV9wZXJjZW50JHVuY2VydGFpbnR5IDwtIChxYmV0YSgwLjk3NSwgZGF0YV8xNV9wZXJjZW50JHBvc2l0aXZlICsgMSwgZGF0YV8xNV9wZXJjZW50JHRlc3RlZCAtIGRhdGFfMTVfcGVyY2VudCRwb3NpdGl2ZSArMSktIHFiZXRhKDAuMDI1LCBkYXRhXzE1X3BlcmNlbnQkcG9zaXRpdmUgKyAxLCBkYXRhXzE1X3BlcmNlbnQkdGVzdGVkIC0gZGF0YV8xNV9wZXJjZW50JHBvc2l0aXZlICsxKSkNCg0KZGF0YV9jb21wYXJlIDwtIGRhdGEuZnJhbWUoVGVzdHM9IGRhdGFfMTVfcGVyY2VudCR0ZXN0ZWQsICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBVbmNlcnRhaW50eV9sb3dQcmV2YWwuID0gcm91bmQoZGF0YV81X3BlcmNlbnQkdW5jZXJ0YWludHksIGRpZ2l0cyA9IDIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgVW5jZXJ0YWludHlfaGlnaFByZXZhbC4gPSByb3VuZChkYXRhXzE1X3BlcmNlbnQkdW5jZXJ0YWludHksIGRpZ2l0cyA9IDIpDQogICAgICAgICAgICAgICAgICAgICAgICAgICApDQoNCnRibDE8LSBrYWJsZShkYXRhX2NvbXBhcmUsIGNhcHRpb24gPSAiVGFibGUgMTogQW4gZXhhbXBsZSBvZiBwcmVjaXNpb24gKGhvdyBsb3cgdGhlIHVuY2VydGFpbnR5IGlzKSB2cyBzYW1wbGUgc2l6ZShUZXN0cykuIGxvd1ByZXZhbC49IDUlIHByZXZhbGVuY2UsIGhpZ2hQcmV2YWwuID0gMTUlIHByZXZhbGVuY2UiKSAjIGNvbnZlcnQgdGhlIGRhdGEgZnJhbWUgaW50byBhIGN1c3RvbWl6YWJsZSB0YWJsZS4gDQpjb2x1bW5fc3BlYyh0YmwxLCAxOjMsIHdpZHRoID0gIjJpbiIpICMgY3VzdG9taXplIHRoZSB0YWJsZSB3aXRoIGEgY2FwdGlvbiBhbmQgZGVmaW5lZCB3aWR0aCBvZiBjb2x1bW5zLiANCmBgYA0KDQpJbiBnZW5lcmFsLCBhcyB3ZSBzZWUgZnJvbSB0aGUgdGFibGUgMSAoYWxzbyBmcm9tIGdyYXBoIDQpLCBoaWdoZXIgdGhlIHNhbXBsZSBzaXplLCBtb3JlIHByZWNpc2UgdGhlIGVzdGltYXRpb24gb2YgdGhlIHByZXZhbGVuY2Ugd291bGQgYmUsIGhvd2V2ZXIsIGFmdGVyIGEgY2VydGFpbiBudW1iZXIgb2YgdGVzdHMgKGZvciBleGFtcGxlLCA2NTAgdGVzdHMsIGluIHRhYmxlIDEpIHRoZSBjaGFuZ2UgaW4gdGhlIGxldmVsIG9mIHVuY2VydGFpbnR5IGRvZXMgbm90IG5vdGljZWFibGUuIFRoZXJlZm9yZSwgZXZlbiB0byBlc3RpbWF0ZSB0aGUgcHJldmFsZW5jZSB2ZXJ5IHByZWNpc2VseSB5b3UgZG9uJ3QgbmVlZCB0byBwZXJmb3JtIHVubGltaXRlZCBudW1iZXIgb2YgdGVzdHMgZm9yIGFueSBnaXZlbiBwcmV2YWxlbmNlLiBBcyB5b3Ugc2VlIGluIHRoZSBhYm92ZSB0YWJsZSwgeW91IGNhbiBjYWxjdWxhdGUgZXhhY3Qgc2NhbGVzIGJhc2VkIG9uIHByZXZhbGVuY2UgYW5kIGV4cGVjdGVkIHByZWNpc2lvbiBsZXZlbCBhbmQgdGhlbiBkZWNpZGUgYXQgd2hpY2ggc2NhbGUgeW91IHdhbnQgdG8gcGVyZm9ybSBzdXJ2ZWlsbGFuY2UgdGVzdHMuICANCg0KSW4gbXkgb3BpbmlvbiwgZm9yIHRoZSBjdXJyZW50IGxvdyBwcmV2YWxlbmNlICg8IDUlLCBzZWUgZ3JhcGggMSkgaW4gdGhlIFVXIGNhbXB1cywgdGVzdGluZyBmcm9tIH4xNTAgdG8gfiAyNTAgcGVvcGxlIGVhY2ggd2VlayBldmVuIGxlc3MgdGhhbiB0aGF0IHRvIHNvbWUgZXh0ZW50IGlzIHN1ZmZpY2llbnQgdG8gZXN0aW1hdGUgdGhlIHByZXZhbGVuY2Ugd2l0aCB1bmNlcnRhaW50eSBvbmx5IH4wLjA3IG9yIGxlc3MgKHRhYmxlMSwgYW5kIGdyYXBoIDMpLiBGaW5hbCBkZWNpc2lvbiBvbiBzY2FsZSBkZXBlbmRzIG9uIHRoZSBleHBlY3RhdGlvbiBvZiB0aGUgVVcgdGVzdGluZyBwcm9ncmFtIGFzIGRpc2N1c3NlZCBlYXJsaWVyLiAgIA0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQo=