The Data
Today we will be analyzing data from Fox and Guyer’s (1978) anonymity
and cooperation study again. The data is included in the
{carData}
package and you can see information about the
data set using ?Guyer
. Twenty groups of four participants
each played 30 trials of the the prisoner’s dilemma game. The number of
cooperative choices (cooperation
) made by each group were
scored out of 120 (i.e., cooperative choices made by 4 participants over
30 trials). The groups either made decisions publicly or privately
(condition
) and groups were either comprised of all women
or all men (sex
).
Run the following code to load the data into your global
environment.
# load data
data <- Guyer
# take a look at the data
head(Guyer)
## cooperation condition sex
## 1 49 public male
## 2 64 public male
## 3 37 public male
## 4 52 public male
## 5 68 public male
## 6 54 public female
# check data structure
str(Guyer)
## 'data.frame': 20 obs. of 3 variables:
## $ cooperation: num 49 64 37 52 68 54 61 79 64 29 ...
## $ condition : Factor w/ 2 levels "anonymous","public": 2 2 2 2 2 2 2 2 2 2 ...
## $ sex : Factor w/ 2 levels "female","male": 2 2 2 2 2 1 1 1 1 1 ...
Independent Samples t-test
Last time we wanted to compare the mean cooperation level to an
experimenter specified level (50% cooperation).
Now, let’s ask a new research question: does whether the decision was
made publicly or anonymously have an effect on people’s cooperation
levels? For this case, we will use an independent samples
t-test, which is used to compare the means of two independent
samples.
The null and alternative hypotheses:
The null hypothesis would be:
\[H_{0}: \mu_1 = \mu_2\]
The alternative hypothesis would be:
\[H_{1}: \mu_1 \neq \mu_2\]
Assumptions
The assumptions include…
- Normality: Assume that both population distributions are
normally distributed.
- Independence: Assume that the observations within and
between groups are independent of each other.
- Homogeneity of variance: Assume that the population
standard deviations of both populations are equal. If you violate this
assumption, use Welch’s t-test (which is actually the default
in R).
Sampling Distribution of Differences Between Means
Another way of stating the null hypothesis is that, if the two
population means are equal, than the difference between the two
population means (population mean 1 minus population mean 2) is zero, as
shown below:
\[H_{0}: \mu_1 - \mu_2 = 0\]
Remember the sampling distribution of means is used to represent the
results we would expect to obtain if the null hypothesis is
true.
For an independent samples t-test, the sampling distribution is a
t distribution that represents all the possible sample mean
differences we could expect to obtain if we randomly obtained
samples from two populations with equal population means and
calculated the difference between each pair of sample means and plotted
those sample mean differences in a distribution.
Standard Error for Student’s t-test
We’ll first talk about how to calculate standard error of the
sampling distribution if performing a student’s t-test, which
assumes that the population standard deviations are equal.
The standard error of the difference, aka the standard
deviation of the sampling distribution of differences between means, is
calculated as:
\[\sigma_{d} = \hat{\sigma_{p}}
\sqrt{(\frac{1}{N_{1}} + \frac{1}{N_{2}})}\] For student’s t-test
(which assumes the standard deviations of the two populations are
equal), \(\hat{\sigma_{p}}\) is the
pooled estimate of the population standard deviation and is
calculated as:
\[\hat{\sigma_{p}} = \sqrt{\frac{{{(N_{1}
- 1)\hat{\sigma_{1}^{2}} + (N_{2} - 1)\hat{\sigma_{2}^{2}}}}} {N_{1} +
N_{2} - 2}}\]
For an independent samples t-test, the null hypothesis states that
the means of the two populations being compared are equal. Another
assumption that student’s version of the independent samples
t-test makes is that the standard deviation of the two populations
are equal. The pooled estimate of the population standard deviation
is a weighted average of the two samples’ estimates of their
population standard deviations.
The degrees of freedom for student’s t-test are N1 + N2
- 2.
Standard Error for Welch’s t-test
If you have reason to think that the homogeneity of variances
assumption has been violated, you should instead perform welch’s
t-test, which does not make this assumption. The main difference
between welch’s t-test and student’s t-test is in how the standard
error of the difference is calculated. For welch’s t-test, you
calculate it as:
\[\sigma_{d} =
\sqrt{(\frac{\hat{\sigma_{1}^{2}}}{N_{1}} +
\frac{\hat{\sigma_{2}^{2}}}{N_{2}})}\] This measure of standard
error will be slightly larger than the measure of
standard error using student’s t-test, and thus this is a more
conservative test (because it will produce a smaller t-test).
The degrees of freedom for welch’s t-test are:
The Independent Samples t-Statistic
The t-statistic for the independent samples t-test is the
difference between our two sample means divided by the
standard error of the difference.
\[t = \frac{\bar X_{1} - \bar
X_{2}}{\sigma_{d}}\]
Which will express, in standard error units, how far away our
actually obtained sample mean difference is from the mean of our
sampling distribution of differences between means (that represents all
the sample mean differences we would expect if the null were
true), which lets us see how unlikely our results
would be if the null hypothesis is true.
Descriptive Statistics
First, let’s get descriptive statistics for each condition to see
what’s going on. We can get the descriptive statistics separately for
the two conditions being compared by using the group_by()
function.
descriptives <- data %>%
group_by(condition) %>%
summarise(n = n(),
mean = mean(cooperation, na.rm = TRUE),
sd = sd(cooperation, na.rm = TRUE))
descriptives
## # A tibble: 2 × 4
## condition n mean sd
## <fct> <int> <dbl> <dbl>
## 1 anonymous 10 40.9 9.42
## 2 public 10 55.7 14.8
Conducting Independent Samples t-Test in R
Option 1: t.test()
Student’s t-test
As with the one-sample and paired t-tests, we can use the
t.test()
function from the the built-in
{stats}
package to conduct an independent samples
t-test.
stats::t.test(cooperation ~ condition, data = data, var.equal = TRUE) # Student's t-test
##
## Two Sample t-test
##
## data: cooperation by condition
## t = -2.6615, df = 18, p-value = 0.0159
## alternative hypothesis: true difference in means between group anonymous and group public is not equal to 0
## 95 percent confidence interval:
## -26.482755 -3.117245
## sample estimates:
## mean in group anonymous mean in group public
## 40.9 55.7
The syntax being used here is similar to how you will perform
regression models in R. Whatever comes on the left of the tilde
(~
) is the dependent variable (in this case,
cooperation
) and whatever comes on the right of the tilde
is the independent variable (in this case, condition
).
Since we specified var.equal = TRUE
in the
t.test()
function, it calculated a Student’s
t-test. If we had specified var.equal = FALSE
(the
default for both t.test()
and
independentSamplesTTest()
) we would have calculated a
Welch’s t-test. Unlike Student’s t-test, Welch’s
t-test does not assume equal variances between groups. To test
whether you have violated the homogeneity of variances assumption, you
can use Levene’s test, as shown below.
Welch’s t-test
Let’s first perform Levene’s test to see if we have violated
the homogeneity of variances assumption. A significant Levene’s
test indicates a violation.
leveneTest(cooperation ~ condition, data = data, center = "mean")
## Levene's Test for Homogeneity of Variance (center = "mean")
## Df F value Pr(>F)
## group 1 1.9346 0.1812
## 18
Have we violated the homogeneity of variances assumption?
Now, let’s perform Welch’s t-test by setting
var.equal = FALSE
.
t.test(cooperation ~ condition, data = data, var.equal = FALSE) # Welch's t-test
##
## Welch Two Sample t-test
##
## data: cooperation by condition
## t = -2.6615, df = 15.237, p-value = 0.0176
## alternative hypothesis: true difference in means between group anonymous and group public is not equal to 0
## 95 percent confidence interval:
## -26.636502 -2.963498
## sample estimates:
## mean in group anonymous mean in group public
## 40.9 55.7
In this case, the t-test was the same for both tests because the
homogeneity of variances assumption was not violated.
Option 2: independentSamplesTTest()
We can also use the independentSamplesTTest
function in
the {lsr}
package to get the output with Cohen’s d
included.
Student’s t-test can be used by setting
var.equal = TRUE
.
independentSamplesTTest(formula = cooperation ~ condition,
data = data,
var.equal = TRUE) # Student
##
## Student's independent samples t-test
##
## Outcome variable: cooperation
## Grouping variable: condition
##
## Descriptive statistics:
## anonymous public
## mean 40.900 55.700
## std dev. 9.422 14.848
##
## Hypotheses:
## null: population means equal for both groups
## alternative: different population means in each group
##
## Test results:
## t-statistic: -2.661
## degrees of freedom: 18
## p-value: 0.016
##
## Other information:
## two-sided 95% confidence interval: [-26.483, -3.117]
## estimated effect size (Cohen's d): 1.19
Welch’s t-test can be used by setting
var.equal = FALSE
.
independentSamplesTTest(formula = cooperation ~ condition,
data = data,
var.equal = FALSE) # Welch
##
## Welch's independent samples t-test
##
## Outcome variable: cooperation
## Grouping variable: condition
##
## Descriptive statistics:
## anonymous public
## mean 40.900 55.700
## std dev. 9.422 14.848
##
## Hypotheses:
## null: population means equal for both groups
## alternative: different population means in each group
##
## Test results:
## t-statistic: -2.661
## degrees of freedom: 15.237
## p-value: 0.018
##
## Other information:
## two-sided 95% confidence interval: [-26.637, -2.963]
## estimated effect size (Cohen's d): 1.19
Practice
Your turn! What if the research question was ‘do cooperation levels
vary by sex?’
t.test(cooperation ~ sex, data = data, var.equal = TRUE)
##
## Two Sample t-test
##
## data: cooperation by sex
## t = 0.15244, df = 18, p-value = 0.8805
## alternative hypothesis: true difference in means between group female and group male is not equal to 0
## 95 percent confidence interval:
## -12.78236 14.78236
## sample estimates:
## mean in group female mean in group male
## 48.8 47.8
Interpretation and Write-Up
Let’s assign the output of the independent samples t-test to an
object so we can get APA-style formatted output from it.
Unfortunately, the apa_print()
function only works with
the t.test()
output, and not with the
independentSamplesTTest()
output. Thus, there will be a few
things missing from the output (i.e., M and SD for each condition,
measure of effect size).
ist_results <- t.test(cooperation ~ condition, data = data, var.equal = TRUE) # Student's t-test
apa_print(ist_results)
## $estimate
## [1] "$\\Delta M = -14.80$, 95\\% CI $[-26.48, -3.12]$"
##
## $statistic
## [1] "$t(18) = -2.66$, $p = .016$"
##
## $full_result
## [1] "$\\Delta M = -14.80$, 95\\% CI $[-26.48, -3.12]$, $t(18) = -2.66$, $p = .016$"
##
## $table
## A data.frame with 5 labelled columns:
##
## estimate conf.int statistic df p.value
## 1 -14.80 [-26.48, -3.12] -2.66 18 .016
##
## estimate : $\\Delta M$
## conf.int : 95\\% CI
## statistic: $t$
## df : $\\mathit{df}$
## p.value : $p$
## attr(,"class")
## [1] "apa_results" "list"
A proper write-up for our Independent Sample t-test would
be:
Cooperation in the public condition (M = 55.70, SD
= 14.84) was much greater than cooperation in the anonymous condition
(M = 40.90, SD = 9.42), t(18) = 2.66,
p = .018, 95% CI [-26.64,-3.12], d = 1.19.
Or, if you want to use the apa_print() output:
Cooperation in the public condition (M = 55.70, SD
= 14.84) was much greater than cooperation in the anonymous condition
(M = 40.90, SD = 9.42), \(t(18) = -2.66\), \(p = .016\), 95% CI [-26.48, -3.12],
d = 1.19.
Plotting an Independent Samples t-test
We can quickly plot our means and 95% confidence interval using the
ggerrorplot()
function in the {ggpubr}
package.
# create plot
ggerrorplot(data,
x = "condition",
y = "cooperation",
desc_stat = "mean_ci",
color = "condition",
ylab = "Cooperation") +
# add results of the t.test
stat_compare_means(method = "t.test")
Change the ‘desc_stat’ parameter if you want to plot a different type
of error bar. Make sure to add a caption, so it is clear what you are
plotting.
# create plot
ggerrorplot(data,
x = "condition",
y = "cooperation",
desc_stat = "mean_se", #change to standard error
color = "condition",
ylab = "Cooperation") +
# add results of the t.test
stat_compare_means(method = "t.test") +
#add caption
labs(caption = 'Error bars indicate the SEM.')
Plotting in ggplot using a stats layer
Before when we used ggplot, we provided the data and canvas we wanted
to plot and then added layers of geoms:
ggplot(data, aes(x=condition, y=cooperation)) + #create canvas
geom_point() #add geom
Sometimes you also want to plot some sort of transformation of your
data. One way to do that is with stats layers. Here we want to plot
summary statistics (mean and CI), so we’ll use ‘stat_summary’:
ggplot(data, aes(x = condition, y = cooperation)) + #create canvas
stat_summary(aes(color = condition), fun = mean, #specify a function to run on your data
geom="point") + #here is where you specify what geom to use
stat_summary(aes(color = condition),
fun.data = mean_ci, #specify a function to run on your data
geom="errorbar", #here is where you specify what geom to use
width = .2) + #here is where you make the error bars a normal width
papaja::theme_apa(
base_family = "Times New Roman") # Makes it APA themed :)
Power Calculations
In order to calculate power, one way is to use the ‘pwr’ package.
This package has several similar functions for different statistical
tests that follow the same general logic. Today we’ll be using
‘pwr.t.test’. This function takes a sample size (n), an effect size
estimate (d), an alpha level (sig.level), and a power (power). The key
thing is to fill in a value for 1 of those 4 things and then leave the
4th one out to calculate it. You can then specify the type of t-test
(type), and whether it is a two-sided or directional test
(alternative).
Cool power visualization here
Here I will make a post-hoc power calculation.
Equal sample sizes
pwr.t.test(n = 10, #sample size (per group)
d = 1.19, #Cohen's d
sig.level = .05, # alpha level
power = NULL, # Set what you want to calculate to NULL or leave out entirely
type = 'two.sample', #independent sample t-test
alternative = 'two.sided' #two-tailed test
)
##
## Two-sample t test power calculation
##
## n = 10
## d = 1.19
## sig.level = 0.05
## power = 0.7112416
## alternative = two.sided
##
## NOTE: n is number in *each* group
If that is a good estimate of effect size, then our power was .711,
even with such a small sample size.
Unequal sample sizes
In cases where your Ns are unequal, use ‘pwr.t2n.test’
pwr.t2n.test(n1=10, #n of group 1
n2=10, #n of group 2
d = 1.19, #Cohen's d
sig.level = .05, # alpha level
power = NULL, # Set what you want to calculate to NULL or leave out entirely
alternative = 'two.sided' #two-tailed test
)
##
## t test power calculation
##
## n1 = 10
## n2 = 10
## d = 1.19
## sig.level = 0.05
## power = 0.7112416
## alternative = two.sided
Practice
Your turn! What sample size do we need to replicate this same effect
size with a power of .95?
pwr.t.test(n = NULL, #sample size (per group)
d = 1.19, #Cohen's d
sig.level = .05, # alpha level
power = 0.95, # Set what you want to calculate to NULL or leave out entirely
type = 'two.sample', #independent sample t-test
alternative = 'two.sided' #two-tailed test
)
##
## Two-sample t test power calculation
##
## n = 19.36879
## d = 1.19
## sig.level = 0.05
## power = 0.95
## alternative = two.sided
##
## NOTE: n is number in *each* group
One more! What effect size do we need to achieve a power of .9, with
30 participants per group, and an alpha level of .01?
pwr.t.test(n = 30, #sample size (per group)
d = NULL, #Cohen's d
sig.level = .01, # alpha level
power = 0.9 , # Set what you want to calculate to NULL or leave out entirely
type = 'two.sample', #independent sample t-test
alternative = 'two.sided' #two-tailed test
)
##
## Two-sample t test power calculation
##
## n = 30
## d = 1.025559
## sig.level = 0.01
## power = 0.9
## alternative = two.sided
##
## NOTE: n is number in *each* group
Minihacks
Minihack 1 Independent Samples t-test:
An intrepid researcher submits a paper on the difference in coding
abilities between Mac and PC users. They argue that PC users are better
at coding than Mac users. Coding ability was operationalized with a
continuous ‘ability’ metric. Despite a growing fear that you are
becoming Reviewer 2, you acquire their data through GitHub to check
their analyses.
Run the following lines of code to load the data:
# set seed for reproducability
set.seed(42)
# load data
data_os <- data.frame("id" = 1:1e5,
"os" = c(rep("pc", 2e4),
rep("mac", 8e4)),
"ability" = c(rnorm(2e4, 15, 90),
rnorm(8e4, 13.9, 1)))
- Perform an student’s independent samples t-test on the data
(using a built in function).
#Your code here
- After running the code, you think that maybe you should have run a
Welch’s t-test instead of a Student’s t-test.
Investigate your chosen function to figure out how to perform a Welch’s
t-test on the data. Do you find a different result? Why or why
not?
#Your code here
- Let’s give the researchers the benefit of the doubt and assume the
variances of both groups are equal. Is there a
meaningful difference between Mac and PC users? Use a
statistic to provide support for your answer.
#Your code here
Please report the results of the t-test in APA style (Please use
as much inline r code as possible).
Plot the data using ggerrorplot()
. Does this support
your answer to question 3?
#Your code here
- Recreate this plot using ggplot. Change the y-axis to a range that
makes sense.
#Your code here
7 Use the Cohen’s d to calculate the percentage of overlap between
the groups. (See lecture 17)
#Your code here
- Your colleague doesn’t care about the comparison between PC and Mac
users. They are only interested in PC users and whether they differ from
an ability level of 14. What should you tell him? What statistical test
supports you?
#Your code here
Minihack 2: POWER
- Find a GIF that represents power and display it using
RMarkdown.
- You are planning on running a fourth version of a study comparing
how tall plants grow after listening to the Beatles or Mozart when they
were seedlings. Previous versions of the study found a Cohen’s d of .1,
.6, and .2. You want to replicate this study with a pea plant, but don’t
expect pea plants to differ from other plants. How many plants should I
plan on including if I want a power of at least .8?
#Your code here
- Whoops! I forgot to mention that this a design where pairs of
genetically identical plants are sorted into the two conditions. How
many pairs of plants do I need?
#Your code here
- Write code to extract the sample size needed (round up) and display
it embedded in an explanation.
#Your code here
Minihack 3: Trouble Shooting
My advisor told me that I had multiple errors in my code. She told me
the line numbers where the errors are, but she thought it would be a
good learning experience for me to try to solve the errors myself. I
need your help. Fix the errors in the following chunks of code.
Error 1:
I am trying to calculate post-hoc power, but it keeps giving me a
strange error message???
pwr.t2n.test(n1=30, #n of group 1
n2=20, #n of group 2
d = .5, #Cohen's d
sig.level = .05, # alpha level
power = NULL, # Set what you want to calculate to NULL or leave out entirely
type = 'two.sample', #independent sample t-test
alternative = 'two.sided' #two-tailed test
)
Error 2:
I prefer t.test()
over
independentSamplesTTest()
because I’m an R purist, and I
wanted to calculate a Cohen’s d value using the
t2d()
function in the {psych}
package. I don’t
think it is working properly. I have a t-statistic of
5.12
and the sample sizes for my two groups are
15
and 22
.
# load psych
library(psych)
# calculate cohen's d
t2d(t = 5.12, n = 15, n1 = 22)
Error 3
I was trying to plot my data from the first minihack, but I can only
see part of my error bars, I want to see all of it.
ggplot(data_os, aes(x=os, y=ability)) + #create canvas
stat_summary(fun.data = mean_ci, #specify a function to run on your data
geom="errorbar") + #here is where you specify what geom to use
stat_summary(fun = mean, #specify a function to run on your data
geom="bar", #here is where you specify what geom to use
fill='blue') +
# add results of t.test
stat_compare_means(method = "t.test") +
coord_cartesian(ylim=c(12,17))
LS0tCnRpdGxlOiAiTGFiIDk6IEluZGVwZW5kZW50IFNhbXBsZXMgKnQqLXRlc3RzIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6IAogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAzCiAgICB0b2NfZmxvYXQ6IFRSVUUKICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUKZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlCi0tLQoKWW91IGNhbiBkb3dubG9hZCB0aGUgcm1kIGZpbGUgW2hlcmVdKGxhYi05X2lzdC5SbWQpLgoKYGBge3Igc2V0dXAsIGluY2x1ZGUgPSBGQUxTRX0KIyBzZXQgY2h1bmsgb3B0aW9ucwprbml0cjo6b3B0c19jaHVuayRzZXQobWVzc2FnZSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFKQoKIyBzdXBwcmVzcyBzY2llbnRpZmljIG5vdGF0aW9uCm9wdGlvbnMoc2NpcGVuID0gOTk5KQoKI2xvYWQgcmVxdWlyZWQgcGFja2FnZXMKbGlicmFyeSh0aWR5dmVyc2UpICMgaW5jbHVkZXMgZHBseXIgYW5kIGdncGxvdDIgZnVuY3Rpb25zCmxpYnJhcnkobHNyKSAjIGluY2x1ZGVzIHQtdGVzdCBmdW5jdGlvbnMKbGlicmFyeShjYXJEYXRhKSAjIGluY2x1ZGVzIHRoZSBHdXllciBkYXRhIHNldApsaWJyYXJ5KGhlcmUpICMgZm9yIGZpbmRpbmcgY29ycmVjdCBwYXRoCmxpYnJhcnkoZ2dwdWJyKSAjIGZvciBtYWtpbmcgYW4gZXJyb3IgbGluZSBwbG90CmxpYnJhcnkocHdyKSAjIGZvciBwb3dlciBjYWxjdWxhdGlvbnMKbGlicmFyeShwYXBhamEpICMgZm9yIHJlcG9ydGluZyByZXN1bHRzCmxpYnJhcnkoY2FyKSAjIHRvIHBlcmZvcm0gTGV2ZW5lJ3MgdGVzdApgYGAKClRvIHF1aWNrbHkgbmF2aWdhdGUgdG8gdGhlIGRlc2lyZWQgc2VjdGlvbiwgY2xpY2sgb25lIG9mIHRoZSBmb2xsb3dpbmcgbGlua3M6CgoxLiAgW0RhdGEgRGVzY3JpcHRpb25dKCNkYXRhKQoyLiAgW0luZGVwZW5kZW50IFNhbXBsZXMgKnQqLXRlc3RdKCNpbmRlcGVuZGVudCkKMy4gIFtNaW5paGFja3NdKCNtaW5paGFja3MpCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMgVGhlIERhdGEgeyNkYXRhfQoKVG9kYXkgd2Ugd2lsbCBiZSBhbmFseXppbmcgZGF0YSBmcm9tIEZveCBhbmQgR3V5ZXIncyAoMTk3OCkgYW5vbnltaXR5IGFuZCBjb29wZXJhdGlvbiBzdHVkeSBhZ2Fpbi4gVGhlIGRhdGEgaXMgaW5jbHVkZWQgaW4gdGhlIGB7Y2FyRGF0YX1gIHBhY2thZ2UgYW5kIHlvdSBjYW4gc2VlIGluZm9ybWF0aW9uIGFib3V0IHRoZSBkYXRhIHNldCB1c2luZyBgP0d1eWVyYC4gVHdlbnR5IGdyb3VwcyBvZiBmb3VyIHBhcnRpY2lwYW50cyBlYWNoIHBsYXllZCAzMCB0cmlhbHMgb2YgdGhlIHRoZSBwcmlzb25lcidzIGRpbGVtbWEgZ2FtZS4gVGhlIG51bWJlciBvZiBjb29wZXJhdGl2ZSBjaG9pY2VzIChgY29vcGVyYXRpb25gKSBtYWRlIGJ5IGVhY2ggZ3JvdXAgd2VyZSBzY29yZWQgb3V0IG9mIDEyMCAoaS5lLiwgY29vcGVyYXRpdmUgY2hvaWNlcyBtYWRlIGJ5IDQgcGFydGljaXBhbnRzIG92ZXIgMzAgdHJpYWxzKS4gVGhlIGdyb3VwcyBlaXRoZXIgbWFkZSBkZWNpc2lvbnMgcHVibGljbHkgb3IgcHJpdmF0ZWx5IChgY29uZGl0aW9uYCkgYW5kIGdyb3VwcyB3ZXJlIGVpdGhlciBjb21wcmlzZWQgb2YgYWxsIHdvbWVuIG9yIGFsbCBtZW4gKGBzZXhgKS4KClJ1biB0aGUgZm9sbG93aW5nIGNvZGUgdG8gbG9hZCB0aGUgZGF0YSBpbnRvIHlvdXIgZ2xvYmFsIGVudmlyb25tZW50LgoKYGBge3J9CiMgbG9hZCBkYXRhIApkYXRhIDwtIEd1eWVyCgojIHRha2UgYSBsb29rIGF0IHRoZSBkYXRhCmhlYWQoR3V5ZXIpCgojIGNoZWNrIGRhdGEgc3RydWN0dXJlCnN0cihHdXllcikKYGBgCgojIEluZGVwZW5kZW50IFNhbXBsZXMgKnQqLXRlc3QgeyNpbmRlcGVuZGVudH0KCkxhc3QgdGltZSB3ZSB3YW50ZWQgdG8gY29tcGFyZSB0aGUgbWVhbiBjb29wZXJhdGlvbiBsZXZlbCB0byBhbiBleHBlcmltZW50ZXIgc3BlY2lmaWVkIGxldmVsICg1MCUgY29vcGVyYXRpb24pLgoKTm93LCBsZXQncyBhc2sgYSBuZXcgcmVzZWFyY2ggcXVlc3Rpb246IGRvZXMgd2hldGhlciB0aGUgZGVjaXNpb24gd2FzIG1hZGUgcHVibGljbHkgb3IgYW5vbnltb3VzbHkgaGF2ZSBhbiBlZmZlY3Qgb24gcGVvcGxlJ3MgY29vcGVyYXRpb24gbGV2ZWxzPyBGb3IgdGhpcyBjYXNlLCB3ZSB3aWxsIHVzZSBhbiBpbmRlcGVuZGVudCBzYW1wbGVzICp0Ki10ZXN0LCB3aGljaCBpcyB1c2VkIHRvIGNvbXBhcmUgdGhlIG1lYW5zIG9mIHR3byBpbmRlcGVuZGVudCBzYW1wbGVzLgoKIyMgVGhlIG51bGwgYW5kIGFsdGVybmF0aXZlIGh5cG90aGVzZXM6CgpUaGUgbnVsbCBoeXBvdGhlc2lzIHdvdWxkIGJlOgoKJCRIX3swfTogXG11XzEgPSBcbXVfMiQkCgpUaGUgYWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyB3b3VsZCBiZToKCiQkSF97MX06IFxtdV8xIFxuZXEgXG11XzIkJAoKIyMjIEFzc3VtcHRpb25zCgpUaGUgYXNzdW1wdGlvbnMgaW5jbHVkZS4uLgoKMS4gICpOb3JtYWxpdHkqOiBBc3N1bWUgdGhhdCBib3RoIHBvcHVsYXRpb24gZGlzdHJpYnV0aW9ucyBhcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuCjIuICAqSW5kZXBlbmRlbmNlKjogQXNzdW1lIHRoYXQgdGhlIG9ic2VydmF0aW9ucyB3aXRoaW4gYW5kIGJldHdlZW4gZ3JvdXBzIGFyZSBpbmRlcGVuZGVudCBvZiBlYWNoIG90aGVyLgozLiAgKkhvbW9nZW5laXR5IG9mIHZhcmlhbmNlKjogQXNzdW1lIHRoYXQgdGhlIHBvcHVsYXRpb24gc3RhbmRhcmQgZGV2aWF0aW9ucyBvZiBib3RoIHBvcHVsYXRpb25zIGFyZSBlcXVhbC4gSWYgeW91IHZpb2xhdGUgdGhpcyBhc3N1bXB0aW9uLCB1c2UgKldlbGNoJ3MgdC10ZXN0KiAod2hpY2ggaXMgYWN0dWFsbHkgdGhlIGRlZmF1bHQgaW4gUikuCgojIyMgU2FtcGxpbmcgRGlzdHJpYnV0aW9uIG9mIERpZmZlcmVuY2VzIEJldHdlZW4gTWVhbnMKCkFub3RoZXIgd2F5IG9mIHN0YXRpbmcgdGhlIG51bGwgaHlwb3RoZXNpcyBpcyB0aGF0LCBpZiB0aGUgdHdvIHBvcHVsYXRpb24gbWVhbnMgYXJlIGVxdWFsLCB0aGFuIHRoZSAqZGlmZmVyZW5jZSogYmV0d2VlbiB0aGUgdHdvIHBvcHVsYXRpb24gbWVhbnMgKHBvcHVsYXRpb24gbWVhbiAxIG1pbnVzIHBvcHVsYXRpb24gbWVhbiAyKSBpcyB6ZXJvLCBhcyBzaG93biBiZWxvdzoKCiQkSF97MH06IFxtdV8xIC0gXG11XzIgPSAwJCQKClJlbWVtYmVyIHRoZSBzYW1wbGluZyBkaXN0cmlidXRpb24gb2YgbWVhbnMgaXMgdXNlZCB0byByZXByZXNlbnQgdGhlIHJlc3VsdHMgd2Ugd291bGQgZXhwZWN0IHRvIG9idGFpbiAqaWYgdGhlIG51bGwgaHlwb3RoZXNpcyBpcyB0cnVlKi4KCkZvciBhbiBpbmRlcGVuZGVudCBzYW1wbGVzIHQtdGVzdCwgdGhlIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBpcyBhICp0KiBkaXN0cmlidXRpb24gdGhhdCByZXByZXNlbnRzIGFsbCB0aGUgcG9zc2libGUgKnNhbXBsZSBtZWFuIGRpZmZlcmVuY2VzKiB3ZSBjb3VsZCBleHBlY3QgdG8gb2J0YWluIGlmIHdlIHJhbmRvbWx5IG9idGFpbmVkIHNhbXBsZXMgZnJvbSB0d28gcG9wdWxhdGlvbnMgd2l0aCAqZXF1YWwgcG9wdWxhdGlvbiBtZWFucyogYW5kIGNhbGN1bGF0ZWQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBlYWNoIHBhaXIgb2Ygc2FtcGxlIG1lYW5zIGFuZCBwbG90dGVkIHRob3NlIHNhbXBsZSBtZWFuIGRpZmZlcmVuY2VzIGluIGEgZGlzdHJpYnV0aW9uLgoKIyMjIyBTdGFuZGFyZCBFcnJvciBmb3IgU3R1ZGVudCdzIHQtdGVzdAoKV2UnbGwgZmlyc3QgdGFsayBhYm91dCBob3cgdG8gY2FsY3VsYXRlIHN0YW5kYXJkIGVycm9yIG9mIHRoZSBzYW1wbGluZyBkaXN0cmlidXRpb24gaWYgcGVyZm9ybWluZyBhICpzdHVkZW50J3MgdC10ZXN0Kiwgd2hpY2ggYXNzdW1lcyB0aGF0IHRoZSBwb3B1bGF0aW9uIHN0YW5kYXJkIGRldmlhdGlvbnMgYXJlICplcXVhbCouCgpUaGUgKnN0YW5kYXJkIGVycm9yIG9mIHRoZSBkaWZmZXJlbmNlKiwgYWthIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBvZiBkaWZmZXJlbmNlcyBiZXR3ZWVuIG1lYW5zLCBpcyBjYWxjdWxhdGVkIGFzOgoKJCRcc2lnbWFfe2R9ID0gXGhhdHtcc2lnbWFfe3B9fSBcc3FydHsoXGZyYWN7MX17Tl97MX19ICsgXGZyYWN7MX17Tl97Mn19KX0kJCBGb3Igc3R1ZGVudCdzIHQtdGVzdCAod2hpY2ggYXNzdW1lcyB0aGUgc3RhbmRhcmQgZGV2aWF0aW9ucyBvZiB0aGUgdHdvIHBvcHVsYXRpb25zIGFyZSBlcXVhbCksICRcaGF0e1xzaWdtYV97cH19JCBpcyB0aGUgKnBvb2xlZCBlc3RpbWF0ZSBvZiB0aGUgcG9wdWxhdGlvbiBzdGFuZGFyZCBkZXZpYXRpb24qIGFuZCBpcyBjYWxjdWxhdGVkIGFzOgoKJCRcaGF0e1xzaWdtYV97cH19ID0gXHNxcnR7XGZyYWN7e3soTl97MX0gLSAxKVxoYXR7XHNpZ21hX3sxfV57Mn19ICsgKE5fezJ9IC0gMSlcaGF0e1xzaWdtYV97Mn1eezJ9fX19fSB7Tl97MX0gKyBOX3syfSAtIDJ9fSQkCgpGb3IgYW4gaW5kZXBlbmRlbnQgc2FtcGxlcyB0LXRlc3QsIHRoZSBudWxsIGh5cG90aGVzaXMgc3RhdGVzIHRoYXQgdGhlIG1lYW5zIG9mIHRoZSB0d28gcG9wdWxhdGlvbnMgYmVpbmcgY29tcGFyZWQgYXJlIGVxdWFsLiBBbm90aGVyIGFzc3VtcHRpb24gdGhhdCAqc3R1ZGVudCdzKiB2ZXJzaW9uIG9mIHRoZSBpbmRlcGVuZGVudCBzYW1wbGVzIHQtdGVzdCBtYWtlcyBpcyB0aGF0IHRoZSAqc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoZSB0d28gcG9wdWxhdGlvbnMgYXJlIGVxdWFsKi4gVGhlIHBvb2xlZCBlc3RpbWF0ZSBvZiB0aGUgcG9wdWxhdGlvbiBzdGFuZGFyZCBkZXZpYXRpb24gaXMgYSAqd2VpZ2h0ZWQgYXZlcmFnZSogb2YgdGhlIHR3byBzYW1wbGVzJyBlc3RpbWF0ZXMgb2YgdGhlaXIgcG9wdWxhdGlvbiBzdGFuZGFyZCBkZXZpYXRpb25zLgoKVGhlICpkZWdyZWVzIG9mIGZyZWVkb20qIGZvciBzdHVkZW50J3MgdC10ZXN0IGFyZSAqTjEgKyBOMiAtIDIqLgoKIyMjIyBTdGFuZGFyZCBFcnJvciBmb3IgV2VsY2gncyB0LXRlc3QKCklmIHlvdSBoYXZlIHJlYXNvbiB0byB0aGluayB0aGF0IHRoZSBob21vZ2VuZWl0eSBvZiB2YXJpYW5jZXMgYXNzdW1wdGlvbiBoYXMgYmVlbiB2aW9sYXRlZCwgeW91IHNob3VsZCBpbnN0ZWFkIHBlcmZvcm0gKndlbGNoJ3MgdC10ZXN0Kiwgd2hpY2ggZG9lcyBub3QgbWFrZSB0aGlzIGFzc3VtcHRpb24uIFRoZSBtYWluIGRpZmZlcmVuY2UgYmV0d2VlbiB3ZWxjaCdzIHQtdGVzdCBhbmQgc3R1ZGVudCdzIHQtdGVzdCBpcyBpbiBob3cgdGhlICpzdGFuZGFyZCBlcnJvciBvZiB0aGUgZGlmZmVyZW5jZSogaXMgY2FsY3VsYXRlZC4gRm9yIHdlbGNoJ3MgdC10ZXN0LCB5b3UgY2FsY3VsYXRlIGl0IGFzOgoKJCRcc2lnbWFfe2R9ID0gXHNxcnR7KFxmcmFje1xoYXR7XHNpZ21hX3sxfV57Mn19fXtOX3sxfX0gKyBcZnJhY3tcaGF0e1xzaWdtYV97Mn1eezJ9fX17Tl97Mn19KX0kJCBUaGlzIG1lYXN1cmUgb2Ygc3RhbmRhcmQgZXJyb3Igd2lsbCBiZSAqKnNsaWdodGx5IGxhcmdlcioqIHRoYW4gdGhlIG1lYXN1cmUgb2Ygc3RhbmRhcmQgZXJyb3IgdXNpbmcgc3R1ZGVudCdzIHQtdGVzdCwgYW5kIHRodXMgdGhpcyBpcyBhIG1vcmUgY29uc2VydmF0aXZlIHRlc3QgKGJlY2F1c2UgaXQgd2lsbCBwcm9kdWNlIGEgc21hbGxlciB0LXRlc3QpLgoKVGhlICpkZWdyZWVzIG9mIGZyZWVkb20qIGZvciB3ZWxjaCdzIHQtdGVzdCBhcmU6CgohW10ocmVzb3VyY2VzXGxhYjlcZGZfd2VsY2hfdHRlc3QuSlBHKQoKIyMjIFRoZSBJbmRlcGVuZGVudCBTYW1wbGVzIHQtU3RhdGlzdGljCgpUaGUgdC1zdGF0aXN0aWMgZm9yIHRoZSBpbmRlcGVuZGVudCBzYW1wbGVzIHQtdGVzdCBpcyB0aGUgKmRpZmZlcmVuY2UgYmV0d2VlbiBvdXIgdHdvIHNhbXBsZSBtZWFucyogZGl2aWRlZCBieSB0aGUgKnN0YW5kYXJkIGVycm9yIG9mIHRoZSBkaWZmZXJlbmNlKi4KCiQkdCA9IFxmcmFje1xiYXIgWF97MX0gLSBcYmFyIFhfezJ9fXtcc2lnbWFfe2R9fSQkCgpXaGljaCB3aWxsIGV4cHJlc3MsIGluIHN0YW5kYXJkIGVycm9yIHVuaXRzLCBob3cgZmFyIGF3YXkgb3VyIGFjdHVhbGx5IG9idGFpbmVkIHNhbXBsZSBtZWFuIGRpZmZlcmVuY2UgaXMgZnJvbSB0aGUgbWVhbiBvZiBvdXIgc2FtcGxpbmcgZGlzdHJpYnV0aW9uIG9mIGRpZmZlcmVuY2VzIGJldHdlZW4gbWVhbnMgKHRoYXQgcmVwcmVzZW50cyBhbGwgdGhlIHNhbXBsZSBtZWFuIGRpZmZlcmVuY2VzIHdlIHdvdWxkIGV4cGVjdCBpZiB0aGUgbnVsbCB3ZXJlICp0cnVlKiksIHdoaWNoIGxldHMgdXMgc2VlIGhvdyAqdW5saWtlbHkqIG91ciByZXN1bHRzIHdvdWxkIGJlICppZiB0aGUgbnVsbCBoeXBvdGhlc2lzIGlzIHRydWUqLgoKIyMgRGVzY3JpcHRpdmUgU3RhdGlzdGljcwoKRmlyc3QsIGxldCdzIGdldCBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIGZvciBlYWNoIGNvbmRpdGlvbiB0byBzZWUgd2hhdCdzIGdvaW5nIG9uLiBXZSBjYW4gZ2V0IHRoZSBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIHNlcGFyYXRlbHkgZm9yIHRoZSB0d28gY29uZGl0aW9ucyBiZWluZyBjb21wYXJlZCBieSB1c2luZyB0aGUgYGdyb3VwX2J5KClgIGZ1bmN0aW9uLgoKYGBge3J9CmRlc2NyaXB0aXZlcyA8LSBkYXRhICU+JQogIGdyb3VwX2J5KGNvbmRpdGlvbikgJT4lCiAgc3VtbWFyaXNlKG4gPSBuKCksCiAgICAgICAgICAgIG1lYW4gPSBtZWFuKGNvb3BlcmF0aW9uLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBzZCA9IHNkKGNvb3BlcmF0aW9uLCBuYS5ybSA9IFRSVUUpKQoKZGVzY3JpcHRpdmVzCmBgYAoKIyMgQ29uZHVjdGluZyBJbmRlcGVuZGVudCBTYW1wbGVzIHQtVGVzdCBpbiBSCgojIyMgT3B0aW9uIDE6IHQudGVzdCgpCgojIyMjIFN0dWRlbnQncyB0LXRlc3QKCkFzIHdpdGggdGhlIG9uZS1zYW1wbGUgYW5kIHBhaXJlZCAqdCotdGVzdHMsIHdlIGNhbiB1c2UgdGhlIGB0LnRlc3QoKWAgZnVuY3Rpb24gZnJvbSB0aGUgdGhlIGJ1aWx0LWluIGB7c3RhdHN9YCBwYWNrYWdlIHRvIGNvbmR1Y3QgYW4gaW5kZXBlbmRlbnQgc2FtcGxlcyAqdCotdGVzdC4KCmBgYHtyfQpzdGF0czo6dC50ZXN0KGNvb3BlcmF0aW9uIH4gY29uZGl0aW9uLCBkYXRhID0gZGF0YSwgdmFyLmVxdWFsID0gVFJVRSkgIyBTdHVkZW50J3MgdC10ZXN0CmBgYAoKVGhlIHN5bnRheCBiZWluZyB1c2VkIGhlcmUgaXMgc2ltaWxhciB0byBob3cgeW91IHdpbGwgcGVyZm9ybSByZWdyZXNzaW9uIG1vZGVscyBpbiBSLiBXaGF0ZXZlciBjb21lcyBvbiB0aGUgbGVmdCBvZiB0aGUgdGlsZGUgKGB+YCkgaXMgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSAoaW4gdGhpcyBjYXNlLCBgY29vcGVyYXRpb25gKSBhbmQgd2hhdGV2ZXIgY29tZXMgb24gdGhlIHJpZ2h0IG9mIHRoZSB0aWxkZSBpcyB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGUgKGluIHRoaXMgY2FzZSwgYGNvbmRpdGlvbmApLgoKU2luY2Ugd2Ugc3BlY2lmaWVkIGB2YXIuZXF1YWwgPSBUUlVFYCBpbiB0aGUgYHQudGVzdCgpYCBmdW5jdGlvbiwgaXQgY2FsY3VsYXRlZCBhIFN0dWRlbnQncyAqdCotdGVzdC4gSWYgd2UgaGFkIHNwZWNpZmllZCBgdmFyLmVxdWFsID0gRkFMU0VgICh0aGUgZGVmYXVsdCBmb3IgYm90aCBgdC50ZXN0KClgIGFuZCBgaW5kZXBlbmRlbnRTYW1wbGVzVFRlc3QoKWApIHdlIHdvdWxkIGhhdmUgY2FsY3VsYXRlZCBhIFdlbGNoJ3MgKnQqLXRlc3QuIFVubGlrZSBTdHVkZW50J3MgKnQqLXRlc3QsIFdlbGNoJ3MgKnQqLXRlc3QgZG9lcyBub3QgYXNzdW1lIGVxdWFsIHZhcmlhbmNlcyBiZXR3ZWVuIGdyb3Vwcy4gVG8gdGVzdCB3aGV0aGVyIHlvdSBoYXZlIHZpb2xhdGVkIHRoZSBob21vZ2VuZWl0eSBvZiB2YXJpYW5jZXMgYXNzdW1wdGlvbiwgeW91IGNhbiB1c2UgKkxldmVuZSdzIHRlc3QqLCBhcyBzaG93biBiZWxvdy4KCiMjIyMgV2VsY2gncyB0LXRlc3QKCkxldCdzIGZpcnN0IHBlcmZvcm0gTGV2ZW5lJ3MgdGVzdCB0byBzZWUgaWYgd2UgaGF2ZSAqdmlvbGF0ZWQqIHRoZSBob21vZ2VuZWl0eSBvZiB2YXJpYW5jZXMgYXNzdW1wdGlvbi4gQSAqc2lnbmlmaWNhbnQqIExldmVuZSdzIHRlc3QgaW5kaWNhdGVzIGEgdmlvbGF0aW9uLgoKYGBge3J9CmxldmVuZVRlc3QoY29vcGVyYXRpb24gfiBjb25kaXRpb24sIGRhdGEgPSBkYXRhLCBjZW50ZXIgPSAibWVhbiIpIApgYGAKCkhhdmUgd2UgdmlvbGF0ZWQgdGhlIGhvbW9nZW5laXR5IG9mIHZhcmlhbmNlcyBhc3N1bXB0aW9uPwoKTm93LCBsZXQncyBwZXJmb3JtIFdlbGNoJ3MgdC10ZXN0IGJ5IHNldHRpbmcgYHZhci5lcXVhbCA9IEZBTFNFYC4KCmBgYHtyfQp0LnRlc3QoY29vcGVyYXRpb24gfiBjb25kaXRpb24sIGRhdGEgPSBkYXRhLCB2YXIuZXF1YWwgPSBGQUxTRSkgIyBXZWxjaCdzIHQtdGVzdApgYGAKCkluIHRoaXMgY2FzZSwgdGhlIHQtdGVzdCB3YXMgdGhlIHNhbWUgZm9yIGJvdGggdGVzdHMgYmVjYXVzZSB0aGUgaG9tb2dlbmVpdHkgb2YgdmFyaWFuY2VzIGFzc3VtcHRpb24gd2FzIG5vdCB2aW9sYXRlZC4KCiMjIyBPcHRpb24gMjogaW5kZXBlbmRlbnRTYW1wbGVzVFRlc3QoKQoKV2UgY2FuIGFsc28gdXNlIHRoZSBgaW5kZXBlbmRlbnRTYW1wbGVzVFRlc3RgIGZ1bmN0aW9uIGluIHRoZSBge2xzcn1gIHBhY2thZ2UgdG8gZ2V0IHRoZSBvdXRwdXQgd2l0aCBDb2hlbidzICpkKiBpbmNsdWRlZC4KCipTdHVkZW50J3MgdC10ZXN0KiBjYW4gYmUgdXNlZCBieSBzZXR0aW5nIGB2YXIuZXF1YWwgPSBUUlVFYC4KCmBgYHtyfQppbmRlcGVuZGVudFNhbXBsZXNUVGVzdChmb3JtdWxhICAgPSBjb29wZXJhdGlvbiB+IGNvbmRpdGlvbiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgICAgICA9IGRhdGEsIAogICAgICAgICAgICAgICAgICAgICAgICB2YXIuZXF1YWwgPSBUUlVFKSAjIFN0dWRlbnQKYGBgCgoqV2VsY2gncyB0LXRlc3QqIGNhbiBiZSB1c2VkIGJ5IHNldHRpbmcgYHZhci5lcXVhbCA9IEZBTFNFYC4KCmBgYHtyfQppbmRlcGVuZGVudFNhbXBsZXNUVGVzdChmb3JtdWxhICAgPSBjb29wZXJhdGlvbiB+IGNvbmRpdGlvbiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgICAgICA9IGRhdGEsIAogICAgICAgICAgICAgICAgICAgICAgICB2YXIuZXF1YWwgPSBGQUxTRSkgIyBXZWxjaApgYGAKCiMjIyBQcmFjdGljZQoKWW91ciB0dXJuISBXaGF0IGlmIHRoZSByZXNlYXJjaCBxdWVzdGlvbiB3YXMgJ2RvIGNvb3BlcmF0aW9uIGxldmVscyB2YXJ5IGJ5IHNleD8nCgpgYGB7cn0KdC50ZXN0KGNvb3BlcmF0aW9uIH4gc2V4LCBkYXRhID0gZGF0YSwgdmFyLmVxdWFsID0gVFJVRSkKYGBgCgojIyBJbnRlcnByZXRhdGlvbiBhbmQgV3JpdGUtVXAKCkxldCdzIGFzc2lnbiB0aGUgb3V0cHV0IG9mIHRoZSBpbmRlcGVuZGVudCBzYW1wbGVzIHQtdGVzdCB0byBhbiBvYmplY3Qgc28gd2UgY2FuIGdldCBBUEEtc3R5bGUgZm9ybWF0dGVkIG91dHB1dCBmcm9tIGl0LgoKVW5mb3J0dW5hdGVseSwgdGhlIGBhcGFfcHJpbnQoKWAgZnVuY3Rpb24gb25seSB3b3JrcyB3aXRoIHRoZSBgdC50ZXN0KClgIG91dHB1dCwgYW5kIG5vdCB3aXRoIHRoZSBgaW5kZXBlbmRlbnRTYW1wbGVzVFRlc3QoKWAgb3V0cHV0LiBUaHVzLCB0aGVyZSB3aWxsIGJlIGEgZmV3IHRoaW5ncyBtaXNzaW5nIGZyb20gdGhlIG91dHB1dCAoaS5lLiwgTSBhbmQgU0QgZm9yIGVhY2ggY29uZGl0aW9uLCBtZWFzdXJlIG9mIGVmZmVjdCBzaXplKS4KCmBgYHtyfQppc3RfcmVzdWx0cyA8LSB0LnRlc3QoY29vcGVyYXRpb24gfiBjb25kaXRpb24sIGRhdGEgPSBkYXRhLCB2YXIuZXF1YWwgPSBUUlVFKSAjIFN0dWRlbnQncyB0LXRlc3QKCmFwYV9wcmludChpc3RfcmVzdWx0cykKYGBgCgpBIHByb3BlciB3cml0ZS11cCBmb3Igb3VyIEluZGVwZW5kZW50IFNhbXBsZSAqdCotdGVzdCB3b3VsZCBiZToKCkNvb3BlcmF0aW9uIGluIHRoZSBwdWJsaWMgY29uZGl0aW9uICgqTSogPSA1NS43MCwgKlNEKiA9IDE0Ljg0KSB3YXMgbXVjaCBncmVhdGVyIHRoYW4gY29vcGVyYXRpb24gaW4gdGhlIGFub255bW91cyBjb25kaXRpb24gKCpNKiA9IDQwLjkwLCAqU0QqID0gOS40MiksICp0KigxOCkgPSAyLjY2LCAqcCogPSAuMDE4LCA5NSUgQ0kgWy0yNi42NCwtMy4xMl0sICpkKiA9IDEuMTkuCgpPciwgaWYgeW91IHdhbnQgdG8gdXNlIHRoZSBhcGFfcHJpbnQoKSBvdXRwdXQ6CgpDb29wZXJhdGlvbiBpbiB0aGUgcHVibGljIGNvbmRpdGlvbiAoKk0qID0gNTUuNzAsICpTRCogPSAxNC44NCkgd2FzIG11Y2ggZ3JlYXRlciB0aGFuIGNvb3BlcmF0aW9uIGluIHRoZSBhbm9ueW1vdXMgY29uZGl0aW9uICgqTSogPSA0MC45MCwgKlNEKiA9IDkuNDIpLCBgciBhcGFfcHJpbnQoaXN0X3Jlc3VsdHMpJHN0YXRpc3RpY2AsIDk1JSBDSSBbYHIgcm91bmQoaXN0X3Jlc3VsdHMkY29uZi5pbnRbMV0sIDIpYCwgYHIgcm91bmQoaXN0X3Jlc3VsdHMkY29uZi5pbnRbMl0sIDIpYF0sICpkKiA9IDEuMTkuCgojIyBQbG90dGluZyBhbiBJbmRlcGVuZGVudCBTYW1wbGVzICp0Ki10ZXN0CgpXZSBjYW4gcXVpY2tseSBwbG90IG91ciBtZWFucyBhbmQgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgdXNpbmcgdGhlIGBnZ2Vycm9ycGxvdCgpYCBmdW5jdGlvbiBpbiB0aGUgYHtnZ3B1YnJ9YCBwYWNrYWdlLgoKYGBge3J9CiMgY3JlYXRlIHBsb3QKZ2dlcnJvcnBsb3QoZGF0YSwgCiAgICAgICAgICAgIHggICAgICAgICA9ICJjb25kaXRpb24iLCAKICAgICAgICAgICAgeSAgICAgICAgID0gImNvb3BlcmF0aW9uIiwgCiAgICAgICAgICAgIGRlc2Nfc3RhdCA9ICJtZWFuX2NpIiwgCiAgICAgICAgICAgIGNvbG9yICAgICA9ICJjb25kaXRpb24iLCAKICAgICAgICAgICAgeWxhYiAgICAgID0gIkNvb3BlcmF0aW9uIikgKwogICMgYWRkIHJlc3VsdHMgb2YgdGhlIHQudGVzdAogIHN0YXRfY29tcGFyZV9tZWFucyhtZXRob2QgPSAidC50ZXN0IikKYGBgCgpDaGFuZ2UgdGhlICdkZXNjX3N0YXQnIHBhcmFtZXRlciBpZiB5b3Ugd2FudCB0byBwbG90IGEgZGlmZmVyZW50IHR5cGUgb2YgZXJyb3IgYmFyLiBNYWtlIHN1cmUgdG8gYWRkIGEgY2FwdGlvbiwgc28gaXQgaXMgY2xlYXIgd2hhdCB5b3UgYXJlIHBsb3R0aW5nLgoKYGBge3J9CiMgY3JlYXRlIHBsb3QKZ2dlcnJvcnBsb3QoZGF0YSwgCiAgICAgICAgICAgIHggICAgICAgICA9ICJjb25kaXRpb24iLCAKICAgICAgICAgICAgeSAgICAgICAgID0gImNvb3BlcmF0aW9uIiwgCiAgICAgICAgICAgIGRlc2Nfc3RhdCA9ICJtZWFuX3NlIiwgI2NoYW5nZSB0byBzdGFuZGFyZCBlcnJvcgogICAgICAgICAgICBjb2xvciAgICAgPSAiY29uZGl0aW9uIiwgCiAgICAgICAgICAgIHlsYWIgICAgICA9ICJDb29wZXJhdGlvbiIpICsKICAjIGFkZCByZXN1bHRzIG9mIHRoZSB0LnRlc3QKICBzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gInQudGVzdCIpICsKICAjYWRkIGNhcHRpb24KICBsYWJzKGNhcHRpb24gPSAnRXJyb3IgYmFycyBpbmRpY2F0ZSB0aGUgU0VNLicpCmBgYAoKIyMjIFBsb3R0aW5nIGluIGdncGxvdCB1c2luZyBhIHN0YXRzIGxheWVyCgpCZWZvcmUgd2hlbiB3ZSB1c2VkIGdncGxvdCwgd2UgcHJvdmlkZWQgdGhlIGRhdGEgYW5kIGNhbnZhcyB3ZSB3YW50ZWQgdG8gcGxvdCBhbmQgdGhlbiBhZGRlZCBsYXllcnMgb2YgZ2VvbXM6CgpgYGB7cn0KZ2dwbG90KGRhdGEsIGFlcyh4PWNvbmRpdGlvbiwgeT1jb29wZXJhdGlvbikpICsgI2NyZWF0ZSBjYW52YXMKICBnZW9tX3BvaW50KCkgI2FkZCBnZW9tCmBgYAoKU29tZXRpbWVzIHlvdSBhbHNvIHdhbnQgdG8gcGxvdCBzb21lIHNvcnQgb2YgdHJhbnNmb3JtYXRpb24gb2YgeW91ciBkYXRhLiBPbmUgd2F5IHRvIGRvIHRoYXQgaXMgd2l0aCBzdGF0cyBsYXllcnMuIEhlcmUgd2Ugd2FudCB0byBwbG90IHN1bW1hcnkgc3RhdGlzdGljcyAobWVhbiBhbmQgQ0kpLCBzbyB3ZSdsbCB1c2UgJ3N0YXRfc3VtbWFyeSc6CgpgYGB7cn0KZ2dwbG90KGRhdGEsIGFlcyh4ID0gY29uZGl0aW9uLCB5ID0gY29vcGVyYXRpb24pKSArICNjcmVhdGUgY2FudmFzCiAgc3RhdF9zdW1tYXJ5KGFlcyhjb2xvciA9IGNvbmRpdGlvbiksIGZ1biA9IG1lYW4sICNzcGVjaWZ5IGEgZnVuY3Rpb24gdG8gcnVuIG9uIHlvdXIgZGF0YQogICAgICAgIGdlb209InBvaW50IikgKyAjaGVyZSBpcyB3aGVyZSB5b3Ugc3BlY2lmeSB3aGF0IGdlb20gdG8gdXNlCiAgc3RhdF9zdW1tYXJ5KGFlcyhjb2xvciA9IGNvbmRpdGlvbiksIAogICAgICAgICAgICAgICBmdW4uZGF0YSA9IG1lYW5fY2ksICNzcGVjaWZ5IGEgZnVuY3Rpb24gdG8gcnVuIG9uIHlvdXIgZGF0YQogICAgICAgIGdlb209ImVycm9yYmFyIiwgICNoZXJlIGlzIHdoZXJlIHlvdSBzcGVjaWZ5IHdoYXQgZ2VvbSB0byB1c2UKICAgICAgICB3aWR0aCA9IC4yKSArICNoZXJlIGlzIHdoZXJlIHlvdSBtYWtlIHRoZSBlcnJvciBiYXJzIGEgbm9ybWFsIHdpZHRoCiAgcGFwYWphOjp0aGVtZV9hcGEoCiAgICBiYXNlX2ZhbWlseSA9ICJUaW1lcyBOZXcgUm9tYW4iKSAjIE1ha2VzIGl0IEFQQSB0aGVtZWQgOikKYGBgCgojIyBQb3dlciBDYWxjdWxhdGlvbnMKCkluIG9yZGVyIHRvIGNhbGN1bGF0ZSBwb3dlciwgb25lIHdheSBpcyB0byB1c2UgdGhlICdwd3InIHBhY2thZ2UuIFRoaXMgcGFja2FnZSBoYXMgc2V2ZXJhbCBzaW1pbGFyIGZ1bmN0aW9ucyBmb3IgZGlmZmVyZW50IHN0YXRpc3RpY2FsIHRlc3RzIHRoYXQgZm9sbG93IHRoZSBzYW1lIGdlbmVyYWwgbG9naWMuIFRvZGF5IHdlJ2xsIGJlIHVzaW5nICdwd3IudC50ZXN0Jy4gVGhpcyBmdW5jdGlvbiB0YWtlcyBhIHNhbXBsZSBzaXplIChuKSwgYW4gZWZmZWN0IHNpemUgZXN0aW1hdGUgKGQpLCBhbiBhbHBoYSBsZXZlbCAoc2lnLmxldmVsKSwgYW5kIGEgcG93ZXIgKHBvd2VyKS4gVGhlIGtleSB0aGluZyBpcyB0byBmaWxsIGluIGEgdmFsdWUgZm9yIDEgb2YgdGhvc2UgNCB0aGluZ3MgYW5kIHRoZW4gbGVhdmUgdGhlIDR0aCBvbmUgb3V0IHRvIGNhbGN1bGF0ZSBpdC4gWW91IGNhbiB0aGVuIHNwZWNpZnkgdGhlIHR5cGUgb2YgdC10ZXN0ICh0eXBlKSwgYW5kIHdoZXRoZXIgaXQgaXMgYSB0d28tc2lkZWQgb3IgZGlyZWN0aW9uYWwgdGVzdCAoYWx0ZXJuYXRpdmUpLgoKQ29vbCBwb3dlciB2aXN1YWxpemF0aW9uIFtoZXJlXShodHRwczovL3Jwc3ljaG9sb2dpc3QuY29tL2QzL25oc3QvKQoKSGVyZSBJIHdpbGwgbWFrZSBhIHBvc3QtaG9jIHBvd2VyIGNhbGN1bGF0aW9uLgoKIyMjIEVxdWFsIHNhbXBsZSBzaXplcwoKYGBge3J9CnB3ci50LnRlc3QobiA9IDEwLCAjc2FtcGxlIHNpemUgKHBlciBncm91cCkKICAgICAgICAgICBkID0gMS4xOSwgI0NvaGVuJ3MgZAogICAgICAgICAgIHNpZy5sZXZlbCA9IC4wNSwgIyBhbHBoYSBsZXZlbAogICAgICAgICAgIHBvd2VyID0gTlVMTCwgIyBTZXQgd2hhdCB5b3Ugd2FudCB0byBjYWxjdWxhdGUgdG8gTlVMTCBvciBsZWF2ZSBvdXQgZW50aXJlbHkKICAgICAgICAgICB0eXBlID0gJ3R3by5zYW1wbGUnLCAjaW5kZXBlbmRlbnQgc2FtcGxlIHQtdGVzdAogICAgICAgICAgIGFsdGVybmF0aXZlID0gJ3R3by5zaWRlZCcgICN0d28tdGFpbGVkIHRlc3QKICAgICApCmBgYAoKSWYgdGhhdCBpcyBhIGdvb2QgZXN0aW1hdGUgb2YgZWZmZWN0IHNpemUsIHRoZW4gb3VyIHBvd2VyIHdhcyAuNzExLCBldmVuIHdpdGggc3VjaCBhIHNtYWxsIHNhbXBsZSBzaXplLgoKIyMjIFVuZXF1YWwgc2FtcGxlIHNpemVzCgpJbiBjYXNlcyB3aGVyZSB5b3VyIE5zIGFyZSB1bmVxdWFsLCB1c2UgJ3B3ci50Mm4udGVzdCcKCmBgYHtyfQpwd3IudDJuLnRlc3QobjE9MTAsICNuIG9mIGdyb3VwIDEKICAgICAgICAgICAgIG4yPTEwLCAjbiBvZiBncm91cCAyCiAgICAgICAgICAgICAgZCA9IDEuMTksICNDb2hlbidzIGQKICAgICAgICAgICBzaWcubGV2ZWwgPSAuMDUsICMgYWxwaGEgbGV2ZWwKICAgICAgICAgICBwb3dlciA9IE5VTEwsICMgU2V0IHdoYXQgeW91IHdhbnQgdG8gY2FsY3VsYXRlIHRvIE5VTEwgb3IgbGVhdmUgb3V0IGVudGlyZWx5CiAgICAgICAgICAgYWx0ZXJuYXRpdmUgPSAndHdvLnNpZGVkJyAgI3R3by10YWlsZWQgdGVzdAogICAgICAgICkKYGBgCgojIyMgUHJhY3RpY2UKCllvdXIgdHVybiEgV2hhdCBzYW1wbGUgc2l6ZSBkbyB3ZSBuZWVkIHRvIHJlcGxpY2F0ZSB0aGlzIHNhbWUgZWZmZWN0IHNpemUgd2l0aCBhIHBvd2VyIG9mIC45NT8KCmBgYHtyfQpwd3IudC50ZXN0KG4gPSBOVUxMLCAjc2FtcGxlIHNpemUgKHBlciBncm91cCkKICAgICAgICAgICBkID0gMS4xOSwgI0NvaGVuJ3MgZAogICAgICAgICAgIHNpZy5sZXZlbCA9IC4wNSwgIyBhbHBoYSBsZXZlbAogICAgICAgICAgIHBvd2VyID0gMC45NSwgIyBTZXQgd2hhdCB5b3Ugd2FudCB0byBjYWxjdWxhdGUgdG8gTlVMTCBvciBsZWF2ZSBvdXQgZW50aXJlbHkKICAgICAgICAgICB0eXBlID0gJ3R3by5zYW1wbGUnLCAjaW5kZXBlbmRlbnQgc2FtcGxlIHQtdGVzdAogICAgICAgICAgIGFsdGVybmF0aXZlID0gJ3R3by5zaWRlZCcgICN0d28tdGFpbGVkIHRlc3QKICAgICApCmBgYAoKT25lIG1vcmUhIFdoYXQgZWZmZWN0IHNpemUgZG8gd2UgbmVlZCB0byBhY2hpZXZlIGEgcG93ZXIgb2YgLjksIHdpdGggMzAgcGFydGljaXBhbnRzIHBlciBncm91cCwgYW5kIGFuIGFscGhhIGxldmVsIG9mIC4wMT8KCmBgYHtyfQpwd3IudC50ZXN0KG4gPSAzMCwgI3NhbXBsZSBzaXplIChwZXIgZ3JvdXApCiAgICAgICAgICAgZCA9IE5VTEwsICNDb2hlbidzIGQKICAgICAgICAgICBzaWcubGV2ZWwgPSAuMDEsICMgYWxwaGEgbGV2ZWwKICAgICAgICAgICBwb3dlciA9IDAuOSAsICMgU2V0IHdoYXQgeW91IHdhbnQgdG8gY2FsY3VsYXRlIHRvIE5VTEwgb3IgbGVhdmUgb3V0IGVudGlyZWx5CiAgICAgICAgICAgdHlwZSA9ICd0d28uc2FtcGxlJywgI2luZGVwZW5kZW50IHNhbXBsZSB0LXRlc3QKICAgICAgICAgICBhbHRlcm5hdGl2ZSA9ICd0d28uc2lkZWQnICAjdHdvLXRhaWxlZCB0ZXN0CiAgICAgKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyBNaW5paGFja3MgeyNtaW5paGFja3N9CgojIyBNaW5paGFjayAxIEluZGVwZW5kZW50IFNhbXBsZXMgdC10ZXN0OgoKQW4gaW50cmVwaWQgcmVzZWFyY2hlciBzdWJtaXRzIGEgcGFwZXIgb24gdGhlIGRpZmZlcmVuY2UgaW4gY29kaW5nIGFiaWxpdGllcyBiZXR3ZWVuIE1hYyBhbmQgUEMgdXNlcnMuIFRoZXkgYXJndWUgdGhhdCBQQyB1c2VycyBhcmUgYmV0dGVyIGF0IGNvZGluZyB0aGFuIE1hYyB1c2Vycy4gQ29kaW5nIGFiaWxpdHkgd2FzIG9wZXJhdGlvbmFsaXplZCB3aXRoIGEgY29udGludW91cyAnYWJpbGl0eScgbWV0cmljLiBEZXNwaXRlIGEgZ3Jvd2luZyBmZWFyIHRoYXQgeW91IGFyZSBiZWNvbWluZyBSZXZpZXdlciAyLCB5b3UgYWNxdWlyZSB0aGVpciBkYXRhIHRocm91Z2ggR2l0SHViIHRvIGNoZWNrIHRoZWlyIGFuYWx5c2VzLgoKUnVuIHRoZSBmb2xsb3dpbmcgbGluZXMgb2YgY29kZSB0byBsb2FkIHRoZSBkYXRhOgoKYGBge3J9CiMgc2V0IHNlZWQgZm9yIHJlcHJvZHVjYWJpbGl0eQpzZXQuc2VlZCg0MikKCiMgbG9hZCBkYXRhCmRhdGFfb3MgPC0gZGF0YS5mcmFtZSgiaWQiICAgICAgPSAxOjFlNSwKICAgICAgICAgICAgICAgICAgICAgICJvcyIgICAgICA9IGMocmVwKCJwYyIsIDJlNCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXAoIm1hYyIsIDhlNCkpLAogICAgICAgICAgICAgICAgICAgICAgImFiaWxpdHkiID0gYyhybm9ybSgyZTQsIDE1LCA5MCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJub3JtKDhlNCwgMTMuOSwgMSkpKQpgYGAKCjEuICBQZXJmb3JtIGFuICpzdHVkZW50J3MgaW5kZXBlbmRlbnQgc2FtcGxlcyB0LXRlc3QqIG9uIHRoZSBkYXRhICh1c2luZyBhIGJ1aWx0IGluIGZ1bmN0aW9uKS4KCmBgYHtyfQojWW91ciBjb2RlIGhlcmUKYGBgCgoyLiAgQWZ0ZXIgcnVubmluZyB0aGUgY29kZSwgeW91IHRoaW5rIHRoYXQgbWF5YmUgeW91IHNob3VsZCBoYXZlIHJ1biBhIFdlbGNoJ3MgKnQqLXRlc3QgaW5zdGVhZCBvZiBhIFN0dWRlbnQncyAqdCotdGVzdC4gSW52ZXN0aWdhdGUgeW91ciBjaG9zZW4gZnVuY3Rpb24gdG8gZmlndXJlIG91dCBob3cgdG8gcGVyZm9ybSBhIFdlbGNoJ3MgKnQqLXRlc3Qgb24gdGhlIGRhdGEuIERvIHlvdSBmaW5kIGEgZGlmZmVyZW50IHJlc3VsdD8gV2h5IG9yIHdoeSBub3Q/CgpgYGB7cn0KI1lvdXIgY29kZSBoZXJlCmBgYAoKMy4gIExldCdzIGdpdmUgdGhlIHJlc2VhcmNoZXJzIHRoZSBiZW5lZml0IG9mIHRoZSBkb3VidCBhbmQgYXNzdW1lIHRoZSB2YXJpYW5jZXMgb2YgYm90aCBncm91cHMgYXJlIGVxdWFsLiBJcyB0aGVyZSBhICoqbWVhbmluZ2Z1bCoqIGRpZmZlcmVuY2UgYmV0d2VlbiBNYWMgYW5kIFBDIHVzZXJzPyBVc2UgYSBzdGF0aXN0aWMgdG8gcHJvdmlkZSBzdXBwb3J0IGZvciB5b3VyIGFuc3dlci4KCmBgYHtyfQojWW91ciBjb2RlIGhlcmUKYGBgCgo0LiAgUGxlYXNlIHJlcG9ydCB0aGUgcmVzdWx0cyBvZiB0aGUgdC10ZXN0IGluIEFQQSBzdHlsZSAoUGxlYXNlIHVzZSBhcyBtdWNoIGlubGluZSByIGNvZGUgYXMgcG9zc2libGUpLgoKNS4gIFBsb3QgdGhlIGRhdGEgdXNpbmcgYGdnZXJyb3JwbG90KClgLiBEb2VzIHRoaXMgc3VwcG9ydCB5b3VyIGFuc3dlciB0byBxdWVzdGlvbiAzPwoKYGBge3J9CiNZb3VyIGNvZGUgaGVyZQpgYGAKCjYuICBSZWNyZWF0ZSB0aGlzIHBsb3QgdXNpbmcgZ2dwbG90LiBDaGFuZ2UgdGhlIHktYXhpcyB0byBhIHJhbmdlIHRoYXQgbWFrZXMgc2Vuc2UuCgpgYGB7cn0KI1lvdXIgY29kZSBoZXJlCmBgYAoKNyBVc2UgdGhlIENvaGVuJ3MgZCB0byBjYWxjdWxhdGUgdGhlIHBlcmNlbnRhZ2Ugb2Ygb3ZlcmxhcCBiZXR3ZWVuIHRoZSBncm91cHMuIChTZWUgbGVjdHVyZSAxNykKCmBgYHtyfQojWW91ciBjb2RlIGhlcmUKYGBgCgo4LiAgWW91ciBjb2xsZWFndWUgZG9lc24ndCBjYXJlIGFib3V0IHRoZSBjb21wYXJpc29uIGJldHdlZW4gUEMgYW5kIE1hYyB1c2Vycy4gVGhleSBhcmUgb25seSBpbnRlcmVzdGVkIGluIFBDIHVzZXJzIGFuZCB3aGV0aGVyIHRoZXkgZGlmZmVyIGZyb20gYW4gYWJpbGl0eSBsZXZlbCBvZiAxNC4gV2hhdCBzaG91bGQgeW91IHRlbGwgaGltPyBXaGF0IHN0YXRpc3RpY2FsIHRlc3Qgc3VwcG9ydHMgeW91PwoKYGBge3J9CiNZb3VyIGNvZGUgaGVyZQpgYGAKCiMjIE1pbmloYWNrIDI6IFBPV0VSCgoxLiAgRmluZCBhIEdJRiB0aGF0IHJlcHJlc2VudHMgcG93ZXIgYW5kIGRpc3BsYXkgaXQgdXNpbmcgUk1hcmtkb3duLgoKIVtdKGh0dHBzOi8vbWVkaWEuZ2lwaHkuY29tL21lZGlhLzNvODRzcTIxVHhESDZQeVltcy9naXBoeS5naWYpCgoyLiAgWW91IGFyZSBwbGFubmluZyBvbiBydW5uaW5nIGEgZm91cnRoIHZlcnNpb24gb2YgYSBzdHVkeSBjb21wYXJpbmcgaG93IHRhbGwgcGxhbnRzIGdyb3cgYWZ0ZXIgbGlzdGVuaW5nIHRvIHRoZSBCZWF0bGVzIG9yIE1vemFydCB3aGVuIHRoZXkgd2VyZSBzZWVkbGluZ3MuIFByZXZpb3VzIHZlcnNpb25zIG9mIHRoZSBzdHVkeSBmb3VuZCBhIENvaGVuJ3MgZCBvZiAuMSwgLjYsIGFuZCAuMi4gWW91IHdhbnQgdG8gcmVwbGljYXRlIHRoaXMgc3R1ZHkgd2l0aCBhIHBlYSBwbGFudCwgYnV0IGRvbid0IGV4cGVjdCBwZWEgcGxhbnRzIHRvIGRpZmZlciBmcm9tIG90aGVyIHBsYW50cy4gSG93IG1hbnkgcGxhbnRzIHNob3VsZCBJIHBsYW4gb24gaW5jbHVkaW5nIGlmIEkgd2FudCBhIHBvd2VyIG9mIGF0IGxlYXN0IC44PwoKYGBge3J9CiNZb3VyIGNvZGUgaGVyZQoKYGBgCgozLiAgV2hvb3BzISBJIGZvcmdvdCB0byBtZW50aW9uIHRoYXQgdGhpcyBhIGRlc2lnbiB3aGVyZSBwYWlycyBvZiBnZW5ldGljYWxseSBpZGVudGljYWwgcGxhbnRzIGFyZSBzb3J0ZWQgaW50byB0aGUgdHdvIGNvbmRpdGlvbnMuIEhvdyBtYW55IHBhaXJzIG9mIHBsYW50cyBkbyBJIG5lZWQ/CgpgYGB7cn0KI1lvdXIgY29kZSBoZXJlCgpgYGAKCjQuICBXcml0ZSBjb2RlIHRvIGV4dHJhY3QgdGhlIHNhbXBsZSBzaXplIG5lZWRlZCAocm91bmQgdXApIGFuZCBkaXNwbGF5IGl0IGVtYmVkZGVkIGluIGFuIGV4cGxhbmF0aW9uLgoKYGBge3J9CiNZb3VyIGNvZGUgaGVyZQpgYGAKCiMjIE1pbmloYWNrIDM6IFRyb3VibGUgU2hvb3RpbmcKCk15IGFkdmlzb3IgdG9sZCBtZSB0aGF0IEkgaGFkIG11bHRpcGxlIGVycm9ycyBpbiBteSBjb2RlLiBTaGUgdG9sZCBtZSB0aGUgbGluZSBudW1iZXJzIHdoZXJlIHRoZSBlcnJvcnMgYXJlLCBidXQgc2hlIHRob3VnaHQgaXQgd291bGQgYmUgYSBnb29kIGxlYXJuaW5nIGV4cGVyaWVuY2UgZm9yIG1lIHRvIHRyeSB0byBzb2x2ZSB0aGUgZXJyb3JzIG15c2VsZi4gSSBuZWVkIHlvdXIgaGVscC4gRml4IHRoZSBlcnJvcnMgaW4gdGhlIGZvbGxvd2luZyBjaHVua3Mgb2YgY29kZS4KCioqRXJyb3IgMToqKgoKSSBhbSB0cnlpbmcgdG8gY2FsY3VsYXRlIHBvc3QtaG9jIHBvd2VyLCBidXQgaXQga2VlcHMgZ2l2aW5nIG1lIGEgc3RyYW5nZSBlcnJvciBtZXNzYWdlPz8/CgpgYGB7ciwgZXZhbD1GQUxTRX0KcHdyLnQybi50ZXN0KG4xPTMwLCAjbiBvZiBncm91cCAxCiAgICAgICAgICAgICBuMj0yMCwgI24gb2YgZ3JvdXAgMgogICAgICAgICAgICAgIGQgPSAuNSwgI0NvaGVuJ3MgZAogICAgICAgICAgIHNpZy5sZXZlbCA9IC4wNSwgIyBhbHBoYSBsZXZlbAogICAgICAgICAgIHBvd2VyID0gTlVMTCwgIyBTZXQgd2hhdCB5b3Ugd2FudCB0byBjYWxjdWxhdGUgdG8gTlVMTCBvciBsZWF2ZSBvdXQgZW50aXJlbHkKICAgICAgICAgICB0eXBlID0gJ3R3by5zYW1wbGUnLCAjaW5kZXBlbmRlbnQgc2FtcGxlIHQtdGVzdAogICAgICAgICAgIGFsdGVybmF0aXZlID0gJ3R3by5zaWRlZCcgICN0d28tdGFpbGVkIHRlc3QKICAgICAgICAgICAgICkKYGBgCgoqKkVycm9yIDI6KioKCkkgcHJlZmVyIGB0LnRlc3QoKWAgb3ZlciBgaW5kZXBlbmRlbnRTYW1wbGVzVFRlc3QoKWAgYmVjYXVzZSBJJ20gYW4gUiBwdXJpc3QsIGFuZCBJIHdhbnRlZCB0byBjYWxjdWxhdGUgYSBDb2hlbidzICpkKiB2YWx1ZSB1c2luZyB0aGUgYHQyZCgpYCBmdW5jdGlvbiBpbiB0aGUgYHtwc3ljaH1gIHBhY2thZ2UuIEkgZG9uJ3QgdGhpbmsgaXQgaXMgd29ya2luZyBwcm9wZXJseS4gSSBoYXZlIGEgKnQqLXN0YXRpc3RpYyBvZiBgNS4xMmBhbmQgdGhlIHNhbXBsZSBzaXplcyBmb3IgbXkgdHdvIGdyb3VwcyBhcmUgYDE1YCBhbmQgYDIyYC4KCmBgYHtyLCBldmFsID0gRkFMU0V9CiMgbG9hZCBwc3ljaApsaWJyYXJ5KHBzeWNoKQoKIyBjYWxjdWxhdGUgY29oZW4ncyBkCnQyZCh0ID0gNS4xMiwgbiA9IDE1LCBuMSA9IDIyKQpgYGAKCioqRXJyb3IgMyoqCgpJIHdhcyB0cnlpbmcgdG8gcGxvdCBteSBkYXRhIGZyb20gdGhlIGZpcnN0IG1pbmloYWNrLCBidXQgSSBjYW4gb25seSBzZWUgcGFydCBvZiBteSBlcnJvciBiYXJzLCBJIHdhbnQgdG8gc2VlIGFsbCBvZiBpdC4KCmBgYHtyfQpnZ3Bsb3QoZGF0YV9vcywgYWVzKHg9b3MsIHk9YWJpbGl0eSkpICsgI2NyZWF0ZSBjYW52YXMKICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBtZWFuX2NpLCAjc3BlY2lmeSBhIGZ1bmN0aW9uIHRvIHJ1biBvbiB5b3VyIGRhdGEKICAgICAgICBnZW9tPSJlcnJvcmJhciIpICsgI2hlcmUgaXMgd2hlcmUgeW91IHNwZWNpZnkgd2hhdCBnZW9tIHRvIHVzZSAKICBzdGF0X3N1bW1hcnkoZnVuID0gbWVhbiwgI3NwZWNpZnkgYSBmdW5jdGlvbiB0byBydW4gb24geW91ciBkYXRhCiAgICAgICAgZ2VvbT0iYmFyIiwgICNoZXJlIGlzIHdoZXJlIHlvdSBzcGVjaWZ5IHdoYXQgZ2VvbSB0byB1c2UKICAgICAgICBmaWxsPSdibHVlJykgKwogICMgYWRkIHJlc3VsdHMgb2YgdC50ZXN0CiAgc3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJ0LnRlc3QiKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW09YygxMiwxNykpCmBgYAo=