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=