US Democrat presidents dataset
Here’s a dataset of US presidential elections. Each row represents a
presidential election at the county level. The variables in the dataset
are the US state, the county within that state, and the percentage of
votes that went to the Democrat candidate in 2008, 2012, and in
2016.
# Load libraries
library(tidyr)
library(dplyr)
library(ggplot2)
library(fst)
library(tibble)
library(readr)
dem_votes_potus_08_16 <- read_fst(uselect_path)
dem_votes_potus_08_16
colnames(dem_votes_potus_08_16)
[1] "state" "county" "FIPS" "dem_cand_votes_08" "dem_percent_08" "dem_cand_votes_12" "dem_percent_12"
[8] "dem_cand_votes_16" "dem_percent_16"
Hypotheses
One question is whether the percentage of votes given to the
Republican candidate was lower in 2008 compared to
2012. To test this, we form the hypotheses. As before,
the null hypothesis is that our hunch is wrong, and
that the population parameters are the same in each year group.
The alternative hypothesis is that the parameter in 2008 was
lower than in 2012. I’m setting a significance level of
0.05.
One feature of this dataset is that the 2008 votes and the
2012 votes are paired, since they both refer to the same
county. That is, the 2008 and 2012 values aren’t independent from each
other. Some voting patterns may occur due to county-level demographics
and local politics. We want to capture this pairing in our model.
\[
H_{0}: \mu_{2008} \ - \mu_{2012} = 0
\\ H_{A}: \mu_{2008} \ - \mu_{2012} < 0
\]
\[
Set\ \alpha = 0.05: \ Significance \ level
\]
From two samples to one
For paired analyses, rather than considering the two variables
separately, we consider a single variable of the difference. In this
histogram of the difference most values are between minus ten and ten,
with a few outliers.
sample_data <- dem_votes_potus_08_16 %>%
mutate(diff = dem_percent_08 - dem_percent_12)
ggplot(sample_data, aes(x = diff)) +
geom_histogram(binwidth = 1)

NA
head(sample_data$diff, 30)
[1] -2.23387788 1.20418692 -0.86343547 1.94779306 -1.56068097 2.19284462 0.46573839 -1.95303233 -0.15685772 1.09746821 -1.23219534 -0.65191061 1.07898478
[14] 2.90689306 -1.40145860 5.98220437 2.10897226 1.89697848 3.26170252 0.98114752 -0.35486217 3.46370218 3.06243598 1.50691738 4.39727218 2.72474816
[27] -0.09605252 2.30883794 2.32793299 3.61597762
Calculate sample statistics of the difference
The sample mean, x-bar
, is calculated on this
difference. It is \(3.059\)
xbar_diff <- sample_data %>%
summarise(xbar_diff = mean(diff)) %>%
pull(xbar_diff)
xbar_diff
[1] 3.059585
Revised hypotheses
We can restate the hypotheses in terms of the single population mean,
\(\mu_{diff}\) , being equal to
or less than zero. The test statistic, \(t\), has a slightly simpler equation
compared to the two sample case. We have one statistic, so the number of
degrees of freedom is the number of rows in the sample minus one.
Old hypotheses
\[
H_{0}: \mu_{2008} \ - \mu_{2012} = 0
\\ H_{A}: \mu_{2008} \ - \mu_{2012} < 0
\]
New hypothesis
\[
H_{0}: \mu_{diff} = 0 \\
H_{A}: \mu_{diff} < 0
\]
Calculating the p-value
To calculate the test statistic, we need the number of rows in the
dataset, 500. And we need the standard deviation of the differences. We
already know \(\bar{x}\) , the mean of
the differences. Assuming the null hypothesis is true means \(\mu_{diff}\) is zero.
\[
\ t = \frac{x_{diff} \ - \mu_{diff}}{\sqrt{\frac{s^2_{diff}}{n_{diff}}}}
\]
n_diff <- nrow(sample_data)
n_diff
[1] 500
s_diff <- sample_data %>%
summarise(sd_diff = sd(diff)) %>%
pull(sd_diff)
s_diff
[1] 3.388767
t_stat <- (xbar_diff - 0) / sqrt(s_diff ^ 2 / n_diff)
t_stat
[1] 20.18859
degrees_of_freedom <- n_diff - 1
p_value <- pt(t_stat, df = degrees_of_freedom)
p_value
[1] 1
We now have everything we need to plug into the equation to calculate
\(t\). It’s \(20.18\). The degrees of freedom are one
less than \(n_{diff}\) at \(499\). Finally, we transform t with the
t-distribution CDF. The p-value is \(1\). That means we accept the null
hypothesis and reject the alternative hypothesis that the Democrat
candidate got a smaller percentage of the vote in 2008 compared to
2012.
Testing differences between two means using
t.test()
That was a lot of calculating. Fortunately, there’s an easier way
using t.test()
. It works with vectors, so the first
argument is the vector of differences. The type of alternative
hypothesis can be two-sided, less or greater. Finally, you
specify the value of \(\mu_{diff}\)
from the null hypothesis. Zero is the default, so strictly-speaking we
didn’t need to specify it. Here’s the output. You should recognize the
value of the test statistic and the degrees of freedom, as well as \(\bar{x}\) on the last line. The
p-value is written as “less
1”. p-values smaller than this are less
reliable due to computational accuracy constraints, but it’s the same
number we calculated before.
t.test(
# Vector of differences
sample_data$diff,
# Choose between "two sided", "less", "greater"
alternative = "less",
# Null hypothesis population parameter
mu = 0
)
One Sample t-test
data: sample_data$diff
t = 20.189, df = 499, p-value = 1
alternative hypothesis: true mean is less than 0
95 percent confidence interval:
-Inf 3.309327
sample estimates:
mean of x
3.059585
t-test()
with paired = TRUE
There’s a variation of t.test()
for paired data that
requires even less work. Rather than calculating the difference between
the two paired variables, you can just pass them both directly to
t.test()
and set paired to TRUE. Notice that all the
numbers are the same.
t.test(sample_data$dem_percent_08, sample_data$dem_percent_12,
alternative = "less", mu = 0, paired = TRUE)
Paired t-test
data: sample_data$dem_percent_08 and sample_data$dem_percent_12
t = 20.189, df = 499, p-value = 1
alternative hypothesis: true mean difference is less than 0
95 percent confidence interval:
-Inf 3.309327
sample estimates:
mean difference
3.059585
Unpaired t.test()
If we don’t set paired = TRUE
and instead performed an
unpaired t-test, then the numbers change. The test statistic is closer
to one, there are more degrees of freedom, and the p-value is much
larger. Performing an unpaired t-test increases the chance of a
false negative error.
t.test(x = sample_data$dem_percent_08, y = sample_data$dem_percent_12,
alternative = "less", mu = 0)
Welch Two Sample t-test
data: sample_data$dem_percent_08 and sample_data$dem_percent_12
t = 3.3584, df = 994.6, p-value = 0.9996
alternative hypothesis: true difference in means is less than 0
95 percent confidence interval:
-Inf 4.559485
sample estimates:
mean of x mean of y
41.84253 38.78294
Visualizing the difference
Before you start running hypothesis tests, it’s a great idea to
perform some exploratory data analysis. That is, calculating summary
statistics and visualizing distributions.
Here, we’ll look at the proportion of county-level votes for the
Democratic candidate in 2012 and 2016,
dem_votes_potus_12_16
. Since the counties are the same in
both years, these samples are paired. The columns containing the samples
are dem_percent_12
and dem_percent_16
.
# Calculate the differences from 2012 to 2016
sample_dem_data <- dem_votes_potus_08_16 %>%
select(state, county, dem_percent_12, dem_percent_16) %>%
mutate(diff = dem_percent_12 - dem_percent_16)
sample_dem_data
# Find mean & standard deviations of differences
diff_stats <- sample_dem_data %>%
summarise(xbar_diff = mean(diff), s_diff = sd(diff))
# See the results
diff_stats
# Using sample_dem_data, plot diff as a histogram
ggplot(sample_dem_data, aes(diff)) +
geom_histogram(binwidth = 1)

Using t.test()
Manually calculating test statistics and transforming them with a CDF
to get a p-value is a lot of effort to do every time we
need to compare two sample means. The comparison of two sample means is
called a t-test, and R has a t.test()
function to
accomplish it. This function provides some flexibility in how you
perform the test.
Now, we’ll explore the difference between the proportion of
county-level votes for the Democratic candidate in 2012 and 2016.
# Conduct a t-test on diff
test_results <- t.test(sample_dem_data$diff, alternative = "greater", mu = 0)
# See the results
test_results
One Sample t-test
data: sample_dem_data$diff
t = 30.298, df = 499, p-value < 2.2e-16
alternative hypothesis: true mean is greater than 0
95 percent confidence interval:
6.45787 Inf
sample estimates:
mean of x
6.829313
# Conduct a paired t-test on dem_percent_12 and dem_percent_16
test_results <- t.test(sample_dem_data$dem_percent_12, sample_dem_data$dem_percent_16, alternative = "greater", mu = 0, paired = TRUE)
# See the results
test_results
Paired t-test
data: sample_dem_data$dem_percent_12 and sample_dem_data$dem_percent_16
t = 30.298, df = 499, p-value < 2.2e-16
alternative hypothesis: true mean difference is greater than 0
95 percent confidence interval:
6.45787 Inf
sample estimates:
mean difference
6.829313
What is the correct decision from the t-test
assuming \(\alpha \ = 0.001\)
?
Reject the null hypothesis
Compare the paired t-test to an (inappropriate) unpaired test on the
same data.
How does the p-value change?
# Conduct a t-test on diff
test_results <- t.test(x=sample_dem_data$dem_percent_12, y=sample_dem_data$dem_percent_16, alternative = "greater", mu = 0)
test_results
Welch Two Sample t-test
data: sample_dem_data$dem_percent_12 and sample_dem_data$dem_percent_16
t = 7.1816, df = 997.19, p-value = 6.732e-13
alternative hypothesis: true difference in means is greater than 0
95 percent confidence interval:
5.263684 Inf
sample estimates:
mean of x mean of y
38.78294 31.95363
The p-value from de unpaired test is greater than the p-value
from the paired test
END
LS0tDQp0aXRsZTogIlBhaXJlZCB0LXRlc3RzIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQpkYXRlOiAyMDI0LTAzLTE4DQphdXRob3I6IEp1YW4gRmVybmFuZG8gTW9zcXVlcmEgQXJhdWpvDQotLS0NCg0KIyMjICoqVVMgRGVtb2NyYXQgcHJlc2lkZW50cyBkYXRhc2V0KioNCg0KSGVyZSdzIGEgZGF0YXNldCBvZiBVUyBwcmVzaWRlbnRpYWwgZWxlY3Rpb25zLiBFYWNoIHJvdyByZXByZXNlbnRzIGEgcHJlc2lkZW50aWFsIGVsZWN0aW9uIGF0IHRoZSBjb3VudHkgbGV2ZWwuIFRoZSB2YXJpYWJsZXMgaW4gdGhlIGRhdGFzZXQgYXJlIHRoZSBVUyBzdGF0ZSwgdGhlIGNvdW50eSB3aXRoaW4gdGhhdCBzdGF0ZSwgYW5kIHRoZSBwZXJjZW50YWdlIG9mIHZvdGVzIHRoYXQgd2VudCB0byB0aGUgRGVtb2NyYXQgY2FuZGlkYXRlIGluIDIwMDgsIDIwMTIsIGFuZCBpbiAyMDE2Lg0KDQpgYGB7cn0NCiMgTG9hZCBsaWJyYXJpZXMNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShmc3QpDQpsaWJyYXJ5KHRpYmJsZSkNCmxpYnJhcnkocmVhZHIpDQpgYGANCg0KYGBge3IgZWNobz1GQUxTRX0NCnVzZWxlY3RfcGF0aCA8LSAiQzovVXNlcnMvSnVhbkZlciBNb3NxdWVyYS9Eb2N1bWVudHMvZGF0YXNldHMvZGVtX2NvdW50eV9wcmVzX2pvaW5lZC5mc3QiDQpgYGANCg0KYGBge3J9DQpkZW1fdm90ZXNfcG90dXNfMDhfMTYgPC0gcmVhZF9mc3QodXNlbGVjdF9wYXRoKQ0KZGVtX3ZvdGVzX3BvdHVzXzA4XzE2DQpjb2xuYW1lcyhkZW1fdm90ZXNfcG90dXNfMDhfMTYpDQpgYGANCg0KIyMjICoqSHlwb3RoZXNlcyoqDQoNCk9uZSBxdWVzdGlvbiBpcyB3aGV0aGVyIHRoZSBwZXJjZW50YWdlIG9mIHZvdGVzIGdpdmVuIHRvIHRoZSBSZXB1YmxpY2FuIGNhbmRpZGF0ZSAqKndhcyBsb3dlciBpbiAyMDA4IGNvbXBhcmVkIHRvIDIwMTIqKi4gVG8gdGVzdCB0aGlzLCB3ZSBmb3JtIHRoZSBoeXBvdGhlc2VzLiBBcyBiZWZvcmUsICoqdGhlIG51bGwgaHlwb3RoZXNpcyBpcyB0aGF0IG91ciBodW5jaCBpcyB3cm9uZyoqLCBhbmQgdGhhdCB0aGUgcG9wdWxhdGlvbiBwYXJhbWV0ZXJzIGFyZSB0aGUgc2FtZSBpbiBlYWNoIHllYXIgZ3JvdXAuIFQqKmhlIGFsdGVybmF0aXZlIGh5cG90aGVzaXMgaXMgdGhhdCB0aGUgcGFyYW1ldGVyIGluIDIwMDggd2FzIGxvd2VyIHRoYW4gaW4gMjAxMioqLiBJJ20gc2V0dGluZyBhIHNpZ25pZmljYW5jZSBsZXZlbCBvZiAqKjAuMDUqKi4NCg0KT25lIGZlYXR1cmUgb2YgdGhpcyBkYXRhc2V0IGlzIHRoYXQgKip0aGUgMjAwOCB2b3RlcyBhbmQgdGhlIDIwMTIgdm90ZXMgYXJlIHBhaXJlZCoqLCBzaW5jZSB0aGV5IGJvdGggcmVmZXIgdG8gdGhlIHNhbWUgY291bnR5LiBUaGF0IGlzLCB0aGUgMjAwOCBhbmQgMjAxMiB2YWx1ZXMgYXJlbid0IGluZGVwZW5kZW50IGZyb20gZWFjaCBvdGhlci4gU29tZSB2b3RpbmcgcGF0dGVybnMgbWF5IG9jY3VyIGR1ZSB0byBjb3VudHktbGV2ZWwgZGVtb2dyYXBoaWNzIGFuZCBsb2NhbCBwb2xpdGljcy4gV2Ugd2FudCB0byBjYXB0dXJlIHRoaXMgcGFpcmluZyBpbiBvdXIgbW9kZWwuDQoNCiQkDQpIX3swfTogXG11X3syMDA4fSBcIC0gXG11X3syMDEyfSA9IDANClxcIEhfe0F9OiBcbXVfezIwMDh9IFwgLSBcbXVfezIwMTJ9IDwgMA0KJCQNCg0KJCQNClNldFwgXGFscGhhID0gMC4wNTogXCBTaWduaWZpY2FuY2UgXCBsZXZlbA0KJCQNCg0KIyMjICoqRnJvbSB0d28gc2FtcGxlcyB0byBvbmUqKg0KDQpGb3IgcGFpcmVkIGFuYWx5c2VzLCByYXRoZXIgdGhhbiBjb25zaWRlcmluZyB0aGUgdHdvIHZhcmlhYmxlcyBzZXBhcmF0ZWx5LCB3ZSBjb25zaWRlciBhIHNpbmdsZSB2YXJpYWJsZSBvZiB0aGUgZGlmZmVyZW5jZS4gSW4gdGhpcyBoaXN0b2dyYW0gb2YgdGhlIGRpZmZlcmVuY2UgbW9zdCB2YWx1ZXMgYXJlIGJldHdlZW4gbWludXMgdGVuIGFuZCB0ZW4sIHdpdGggYSBmZXcgb3V0bGllcnMuDQoNCmBgYHtyfQ0Kc2FtcGxlX2RhdGEgPC0gZGVtX3ZvdGVzX3BvdHVzXzA4XzE2ICU+JQ0KICBtdXRhdGUoZGlmZiA9IGRlbV9wZXJjZW50XzA4IC0gZGVtX3BlcmNlbnRfMTIpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3Qoc2FtcGxlX2RhdGEsIGFlcyh4ID0gZGlmZikpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKQ0KICANCmBgYA0KDQpgYGB7cn0NCmhlYWQoc2FtcGxlX2RhdGEkZGlmZiwgMzApDQpgYGANCg0KIyMjICoqQ2FsY3VsYXRlIHNhbXBsZSBzdGF0aXN0aWNzIG9mIHRoZSBkaWZmZXJlbmNlKioNCg0KVGhlIHNhbXBsZSBtZWFuLCBgeC1iYXJgLCBpcyBjYWxjdWxhdGVkIG9uIHRoaXMgZGlmZmVyZW5jZS4gSXQgaXMgJDMuMDU5JA0KDQpgYGB7cn0NCnhiYXJfZGlmZiA8LSBzYW1wbGVfZGF0YSAlPiUNCiAgc3VtbWFyaXNlKHhiYXJfZGlmZiA9IG1lYW4oZGlmZikpICU+JQ0KICBwdWxsKHhiYXJfZGlmZikNCg0KeGJhcl9kaWZmDQpgYGANCg0KIyMjICoqUmV2aXNlZCBoeXBvdGhlc2VzKioNCg0KV2UgY2FuIHJlc3RhdGUgdGhlIGh5cG90aGVzZXMgaW4gdGVybXMgb2YgdGhlIHNpbmdsZSBwb3B1bGF0aW9uIG1lYW4sICRcbXVfe2RpZmZ9JCAsIGJlaW5nICoqZXF1YWwgdG8gb3IgbGVzcyB0aGFuIHplcm8qKi4gVGhlIHRlc3Qgc3RhdGlzdGljLCAkdCQsIGhhcyBhIHNsaWdodGx5IHNpbXBsZXIgZXF1YXRpb24gY29tcGFyZWQgdG8gdGhlIHR3byBzYW1wbGUgY2FzZS4gV2UgaGF2ZSBvbmUgc3RhdGlzdGljLCBzbyB0aGUgbnVtYmVyIG9mIGRlZ3JlZXMgb2YgZnJlZWRvbSBpcyB0aGUgbnVtYmVyIG9mIHJvd3MgaW4gdGhlIHNhbXBsZSBtaW51cyBvbmUuDQoNCiMjIyMgKipPbGQgaHlwb3RoZXNlcyoqDQoNCiQkDQpIX3swfTogXG11X3syMDA4fSBcIC0gXG11X3syMDEyfSA9IDANClxcIEhfe0F9OiBcbXVfezIwMDh9IFwgLSBcbXVfezIwMTJ9IDwgMA0KJCQNCg0KIyMjIyAqKk5ldyBoeXBvdGhlc2lzKioNCg0KJCQNCkhfezB9OiBcbXVfe2RpZmZ9ID0gMCBcXA0KSF97QX06IFxtdV97ZGlmZn0gPCAwDQokJA0KDQojIyMgKipDYWxjdWxhdGluZyB0aGUgcC12YWx1ZSoqDQoNClRvIGNhbGN1bGF0ZSB0aGUgdGVzdCBzdGF0aXN0aWMsIHdlIG5lZWQgdGhlIG51bWJlciBvZiByb3dzIGluIHRoZSBkYXRhc2V0LCA1MDAuIEFuZCB3ZSBuZWVkIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIGRpZmZlcmVuY2VzLiBXZSBhbHJlYWR5IGtub3cgJFxiYXJ7eH0kICwgdGhlIG1lYW4gb2YgdGhlIGRpZmZlcmVuY2VzLiBBc3N1bWluZyB0aGUgbnVsbCBoeXBvdGhlc2lzIGlzIHRydWUgbWVhbnMgJFxtdV97ZGlmZn0kIGlzIHplcm8uDQoNCiQkDQpcIHQgPSBcZnJhY3t4X3tkaWZmfSBcIC0gXG11X3tkaWZmfX17XHNxcnR7XGZyYWN7c14yX3tkaWZmfX17bl97ZGlmZn19fX0NCiQkDQoNCmBgYHtyfQ0Kbl9kaWZmIDwtIG5yb3coc2FtcGxlX2RhdGEpDQpuX2RpZmYNCmBgYA0KDQpgYGB7cn0NCnNfZGlmZiA8LSBzYW1wbGVfZGF0YSAlPiUNCiAgc3VtbWFyaXNlKHNkX2RpZmYgPSBzZChkaWZmKSkgJT4lDQogIHB1bGwoc2RfZGlmZikNCg0Kc19kaWZmDQpgYGANCg0KYGBge3J9DQp0X3N0YXQgPC0gKHhiYXJfZGlmZiAtIDApIC8gc3FydChzX2RpZmYgXiAyIC8gbl9kaWZmKQ0KdF9zdGF0DQpgYGANCg0KYGBge3J9DQpkZWdyZWVzX29mX2ZyZWVkb20gPC0gbl9kaWZmIC0gMQ0KDQpwX3ZhbHVlIDwtIHB0KHRfc3RhdCwgZGYgPSBkZWdyZWVzX29mX2ZyZWVkb20pDQpwX3ZhbHVlDQpgYGANCg0KV2Ugbm93IGhhdmUgZXZlcnl0aGluZyB3ZSBuZWVkIHRvIHBsdWcgaW50byB0aGUgZXF1YXRpb24gdG8gY2FsY3VsYXRlICR0JC4gSXQncyAkMjAuMTgkLiBUaGUgZGVncmVlcyBvZiBmcmVlZG9tIGFyZSBvbmUgbGVzcyB0aGFuICRuX3tkaWZmfSQgYXQgJDQ5OSQuIEZpbmFsbHksIHdlIHRyYW5zZm9ybSB0IHdpdGggdGhlIHQtZGlzdHJpYnV0aW9uIENERi4gVGhlIHAtdmFsdWUgaXMgJDEkLiBUaGF0IG1lYW5zIHdlIGFjY2VwdCB0aGUgbnVsbCBoeXBvdGhlc2lzIGFuZCByZWplY3QgdGhlIGFsdGVybmF0aXZlIGh5cG90aGVzaXMgdGhhdCB0aGUgRGVtb2NyYXQgY2FuZGlkYXRlIGdvdCBhIHNtYWxsZXIgcGVyY2VudGFnZSBvZiB0aGUgdm90ZSBpbiAyMDA4IGNvbXBhcmVkIHRvIDIwMTIuDQoNCiMjIyAqKlRlc3RpbmcgZGlmZmVyZW5jZXMgYmV0d2VlbiB0d28gbWVhbnMgdXNpbmcgdC50ZXN0KCkqKg0KDQpUaGF0IHdhcyBhIGxvdCBvZiBjYWxjdWxhdGluZy4gRm9ydHVuYXRlbHksIHRoZXJlJ3MgYW4gZWFzaWVyIHdheSB1c2luZyBgdC50ZXN0KClgLiBJdCB3b3JrcyB3aXRoIHZlY3RvcnMsIHNvIHRoZSBmaXJzdCBhcmd1bWVudCBpcyB0aGUgdmVjdG9yIG9mIGRpZmZlcmVuY2VzLiBUaGUgKip0eXBlIG9mIGFsdGVybmF0aXZlIGh5cG90aGVzaXMgY2FuIGJlIHR3by1zaWRlZCwgbGVzcyBvciBncmVhdGVyKiouIEZpbmFsbHksIHlvdSBzcGVjaWZ5IHRoZSB2YWx1ZSBvZiAkXG11X3tkaWZmfSQgZnJvbSB0aGUgbnVsbCBoeXBvdGhlc2lzLiBaZXJvIGlzIHRoZSBkZWZhdWx0LCBzbyBzdHJpY3RseS1zcGVha2luZyB3ZSBkaWRuJ3QgbmVlZCB0byBzcGVjaWZ5IGl0LiBIZXJlJ3MgdGhlIG91dHB1dC4gWW91IHNob3VsZCByZWNvZ25pemUgdGhlIHZhbHVlIG9mIHRoZSB0ZXN0IHN0YXRpc3RpYyBhbmQgdGhlIGRlZ3JlZXMgb2YgZnJlZWRvbSwgYXMgd2VsbCBhcyAkXGJhcnt4fSQgb24gdGhlIGxhc3QgbGluZS4gVGhlICoqcC12YWx1ZSoqIGlzIHdyaXR0ZW4gYXMgIioqKmxlc3MgMSoqKiIuICoqcC12YWx1ZXMqKiBzbWFsbGVyIHRoYW4gdGhpcyBhcmUgbGVzcyByZWxpYWJsZSBkdWUgdG8gY29tcHV0YXRpb25hbCBhY2N1cmFjeSBjb25zdHJhaW50cywgYnV0IGl0J3MgdGhlIHNhbWUgbnVtYmVyIHdlIGNhbGN1bGF0ZWQgYmVmb3JlLg0KDQpgYGB7cn0NCnQudGVzdCgNCiAgIyBWZWN0b3Igb2YgZGlmZmVyZW5jZXMNCiAgc2FtcGxlX2RhdGEkZGlmZiwNCiAgIyBDaG9vc2UgYmV0d2VlbiAidHdvIHNpZGVkIiwgImxlc3MiLCAiZ3JlYXRlciINCiAgYWx0ZXJuYXRpdmUgPSAibGVzcyIsDQogICMgTnVsbCBoeXBvdGhlc2lzIHBvcHVsYXRpb24gcGFyYW1ldGVyDQogIG11ID0gMA0KICApDQpgYGANCg0KIyMjICoqYHQtdGVzdCgpYCB3aXRoIHBhaXJlZCA9IFRSVUUqKg0KDQpUaGVyZSdzIGEgdmFyaWF0aW9uIG9mIGB0LnRlc3QoKWAgZm9yIHBhaXJlZCBkYXRhIHRoYXQgcmVxdWlyZXMgZXZlbiBsZXNzIHdvcmsuIFJhdGhlciB0aGFuIGNhbGN1bGF0aW5nIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHR3byBwYWlyZWQgdmFyaWFibGVzLCB5b3UgY2FuIGp1c3QgcGFzcyB0aGVtIGJvdGggZGlyZWN0bHkgdG8gYHQudGVzdCgpYCBhbmQgc2V0IHBhaXJlZCB0byBUUlVFLiBOb3RpY2UgdGhhdCBhbGwgdGhlIG51bWJlcnMgYXJlIHRoZSBzYW1lLg0KDQpgYGB7cn0NCnQudGVzdChzYW1wbGVfZGF0YSRkZW1fcGVyY2VudF8wOCwgc2FtcGxlX2RhdGEkZGVtX3BlcmNlbnRfMTIsIA0KICAgICAgIGFsdGVybmF0aXZlID0gImxlc3MiLCBtdSA9IDAsIHBhaXJlZCA9IFRSVUUpDQpgYGANCg0KIyMjICoqVW5wYWlyZWQgYHQudGVzdCgpYCoqDQoNCklmIHdlIGRvbid0IHNldCBgcGFpcmVkID0gVFJVRWAgYW5kIGluc3RlYWQgcGVyZm9ybWVkIGFuIHVucGFpcmVkIHQtdGVzdCwgdGhlbiB0aGUgbnVtYmVycyBjaGFuZ2UuIFRoZSB0ZXN0IHN0YXRpc3RpYyBpcyBjbG9zZXIgdG8gb25lLCB0aGVyZSBhcmUgbW9yZSBkZWdyZWVzIG9mIGZyZWVkb20sIGFuZCB0aGUgcC12YWx1ZSBpcyBtdWNoIGxhcmdlci4gKipQZXJmb3JtaW5nIGFuIHVucGFpcmVkIHQtdGVzdCBpbmNyZWFzZXMgdGhlIGNoYW5jZSBvZiBhIGZhbHNlIG5lZ2F0aXZlIGVycm9yKiouDQoNCmBgYHtyfQ0KdC50ZXN0KHggPSBzYW1wbGVfZGF0YSRkZW1fcGVyY2VudF8wOCwgeSA9IHNhbXBsZV9kYXRhJGRlbV9wZXJjZW50XzEyLA0KICAgICAgIGFsdGVybmF0aXZlID0gImxlc3MiLCBtdSA9IDApDQpgYGANCg0KIyMjICoqVmlzdWFsaXppbmcgdGhlIGRpZmZlcmVuY2UqKg0KDQpCZWZvcmUgeW91IHN0YXJ0IHJ1bm5pbmcgaHlwb3RoZXNpcyB0ZXN0cywgaXQncyBhIGdyZWF0IGlkZWEgdG8gcGVyZm9ybSBzb21lIGV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMuIFRoYXQgaXMsIGNhbGN1bGF0aW5nIHN1bW1hcnkgc3RhdGlzdGljcyBhbmQgdmlzdWFsaXppbmcgZGlzdHJpYnV0aW9ucy4NCg0KSGVyZSwgd2UnbGwgbG9vayBhdCB0aGUgcHJvcG9ydGlvbiBvZiBjb3VudHktbGV2ZWwgdm90ZXMgZm9yIHRoZSBEZW1vY3JhdGljIGNhbmRpZGF0ZSBpbiAyMDEyIGFuZCAyMDE2LCBgZGVtX3ZvdGVzX3BvdHVzXzEyXzE2YC4gU2luY2UgdGhlIGNvdW50aWVzIGFyZSB0aGUgc2FtZSBpbiBib3RoIHllYXJzLCB0aGVzZSBzYW1wbGVzIGFyZSBwYWlyZWQuIFRoZSBjb2x1bW5zIGNvbnRhaW5pbmcgdGhlIHNhbXBsZXMgYXJlIGBkZW1fcGVyY2VudF8xMmAgYW5kIGBkZW1fcGVyY2VudF8xNmAuDQoNCmBgYHtyfQ0KIyBDYWxjdWxhdGUgdGhlIGRpZmZlcmVuY2VzIGZyb20gMjAxMiB0byAyMDE2DQpzYW1wbGVfZGVtX2RhdGEgPC0gZGVtX3ZvdGVzX3BvdHVzXzA4XzE2ICU+JQ0KICBzZWxlY3Qoc3RhdGUsIGNvdW50eSwgZGVtX3BlcmNlbnRfMTIsIGRlbV9wZXJjZW50XzE2KSAlPiUNCiAgbXV0YXRlKGRpZmYgPSBkZW1fcGVyY2VudF8xMiAtIGRlbV9wZXJjZW50XzE2KQ0KDQpzYW1wbGVfZGVtX2RhdGENCmBgYA0KDQpgYGB7cn0NCiMgRmluZCBtZWFuICYgc3RhbmRhcmQgZGV2aWF0aW9ucyBvZiBkaWZmZXJlbmNlcw0KZGlmZl9zdGF0cyA8LSBzYW1wbGVfZGVtX2RhdGEgJT4lDQogIHN1bW1hcmlzZSh4YmFyX2RpZmYgPSBtZWFuKGRpZmYpLCBzX2RpZmYgPSBzZChkaWZmKSkNCg0KIyBTZWUgdGhlIHJlc3VsdHMNCmRpZmZfc3RhdHMNCmBgYA0KDQpgYGB7cn0NCiMgVXNpbmcgc2FtcGxlX2RlbV9kYXRhLCBwbG90IGRpZmYgYXMgYSBoaXN0b2dyYW0NCiAgZ2dwbG90KHNhbXBsZV9kZW1fZGF0YSwgYWVzKGRpZmYpKSArIA0KICAgIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkNCmBgYA0KDQojIyMgKipVc2luZyB0LnRlc3QoKSoqDQoNCk1hbnVhbGx5IGNhbGN1bGF0aW5nIHRlc3Qgc3RhdGlzdGljcyBhbmQgdHJhbnNmb3JtaW5nIHRoZW0gd2l0aCBhIENERiB0byBnZXQgYSAqKnAtdmFsdWUqKiBpcyBhIGxvdCBvZiBlZmZvcnQgdG8gZG8gZXZlcnkgdGltZSB3ZSBuZWVkIHRvIGNvbXBhcmUgdHdvIHNhbXBsZSBtZWFucy4gVGhlIGNvbXBhcmlzb24gb2YgdHdvIHNhbXBsZSBtZWFucyBpcyBjYWxsZWQgYSB0LXRlc3QsIGFuZCBSIGhhcyBhIGB0LnRlc3QoKWAgZnVuY3Rpb24gdG8gYWNjb21wbGlzaCBpdC4gVGhpcyBmdW5jdGlvbiBwcm92aWRlcyBzb21lIGZsZXhpYmlsaXR5IGluIGhvdyB5b3UgcGVyZm9ybSB0aGUgdGVzdC4NCg0KTm93LCB3ZSdsbCBleHBsb3JlIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHByb3BvcnRpb24gb2YgY291bnR5LWxldmVsIHZvdGVzIGZvciB0aGUgRGVtb2NyYXRpYyBjYW5kaWRhdGUgaW4gMjAxMiBhbmQgMjAxNi4NCg0KYGBge3J9DQojIENvbmR1Y3QgYSB0LXRlc3Qgb24gZGlmZg0KdGVzdF9yZXN1bHRzIDwtIHQudGVzdChzYW1wbGVfZGVtX2RhdGEkZGlmZiwgYWx0ZXJuYXRpdmUgPSAiZ3JlYXRlciIsIG11ID0gMCkNCg0KIyBTZWUgdGhlIHJlc3VsdHMNCnRlc3RfcmVzdWx0cw0KYGBgDQoNCmBgYHtyfQ0KIyBDb25kdWN0IGEgcGFpcmVkIHQtdGVzdCBvbiBkZW1fcGVyY2VudF8xMiBhbmQgZGVtX3BlcmNlbnRfMTYNCnRlc3RfcmVzdWx0cyA8LSB0LnRlc3Qoc2FtcGxlX2RlbV9kYXRhJGRlbV9wZXJjZW50XzEyLCBzYW1wbGVfZGVtX2RhdGEkZGVtX3BlcmNlbnRfMTYsIGFsdGVybmF0aXZlID0gImdyZWF0ZXIiLCBtdSA9IDAsIHBhaXJlZCA9IFRSVUUpDQoNCiMgU2VlIHRoZSByZXN1bHRzDQp0ZXN0X3Jlc3VsdHMNCmBgYA0KDQojIyMgKipXaGF0IGlzIHRoZSBjb3JyZWN0IGRlY2lzaW9uIGZyb20gdGhlIHQtdGVzdCBhc3N1bWluZyoqICRcYWxwaGEgXCA9IDAuMDAxJCA/DQoNCioqUmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMqKg0KDQojIyMgQ29tcGFyZSB0aGUgcGFpcmVkIHQtdGVzdCB0byBhbiAoaW5hcHByb3ByaWF0ZSkgdW5wYWlyZWQgdGVzdCBvbiB0aGUgc2FtZSBkYXRhLg0KDQoqKkhvdyBkb2VzIHRoZSBwLXZhbHVlIGNoYW5nZT8qKg0KDQpgYGB7cn0NCiMgQ29uZHVjdCBhIHQtdGVzdCBvbiBkaWZmDQp0ZXN0X3Jlc3VsdHMgPC0gdC50ZXN0KHg9c2FtcGxlX2RlbV9kYXRhJGRlbV9wZXJjZW50XzEyLCB5PXNhbXBsZV9kZW1fZGF0YSRkZW1fcGVyY2VudF8xNiwgYWx0ZXJuYXRpdmUgPSAiZ3JlYXRlciIsIG11ID0gMCkNCnRlc3RfcmVzdWx0cw0KYGBgDQoNCioqVGhlIHAtdmFsdWUgZnJvbSBkZSB1bnBhaXJlZCB0ZXN0IGlzIGdyZWF0ZXIgdGhhbiB0aGUgcC12YWx1ZSBmcm9tIHRoZSBwYWlyZWQgdGVzdCoqDQoNCiMjIyBFTkQNCg==