0.1 First things first

install.packages("tidyverse")
install.packages("car")
install.packages("haven")
install.packages("corrr")
install.packages("janitor")
install.packages("rstatix")

library(car) # Load the library car so we can run leveneTest, install if needed 
library(tidyverse)
library(haven) #import files produced in other statistical software
library(corrr) #Includes functions to evaluate correlations within the tidyverse
library(janitor) #To analyze cross-tabulation – chi-squared
library(rstatix) #One of many packages used for t-tests

0.2 t-statistics

0.2.1 Let’s practice importing data again

0.2.1.1 Your turn:

Import the “anes_pilot_2016.dta” file and create a dataframe NESdta. This is an Stata file so we need to use the haven package. Hint: uses read_dta()

# Using R to import an Stata filesd
NESdta<- anes_pilot_2016

View what we just imported. Did we get what we expected?

head(NESdta)
NA

Now let’s create a new dataframe NESdata_sub with a subset of variables: fttrump, pid3, birthyr, gender, ftobama. Hint: use the select function from the tidyverse. Hint: make sure you have load your tidyverse package. The variables in our subset come from the American National Election Studies, where fttrump is a Feeling thermometer for Trump in 2016 (from 1 to 100, where 1 = cold and 100 = warm), pid3 is the respondent’s party affiliation (1 = Democrat, 2 = Independent, 3 = Republican), birthyr is the respondent’s birth year, gender is the respondent’s gender (1 = male and 2 = female) and ftobama is a feeling thermometer for Obama in 2016 (from 1 to 100, where 1 = cold and 100 = warm)

Using the pipe operator [ %>%] do the following:

replace all values where fttrump>100 for NA replace all values where ftobama>998 for NA create a new variable female drop missing values on the subset data

NESdta_sub <- NESdta %>%
  dplyr::select(fttrump, pid3, birthyr, gender, ftobama) %>%
  mutate(fttrump = replace(fttrump, fttrump > 100, NA),
         ftobama = replace(ftobama, ftobama == 998, NA),
         female = ifelse(gender == 2, 1, 0)) %>%
  as.data.frame() %>%
  drop_na()

0.2.1.2 Your turn: Recoding variable

Using the NESdta_sub, create a new variable [Party] where: [Hint: use the mutate and case_when functions ] Party is equal to “Democrat” if pid3 is 1, Party is equal to “Republican” if pid3 is 2, Party is equal to “Independent” if pid3 is 3

NESdta_sub <- NESdta_sub %>% 
  mutate(Party = case_when(pid3 == 1 ~ "Democrat", 
                           pid3 == 2 ~ "Republican", pid3 == 3 ~ "Independent"))

Let’s use the glimpse function to check if the dataset looks okay

glimpse(NESdta_sub)
Rows: 1,195
Columns: 7
$ fttrump <dbl> 1, 28, 100, 0, 13, 61, 5, 85, 7…
$ pid3    <dbl> 1, 3, 2, 1, 4, 3, 1, 2, 3, 1, 2…
$ birthyr <dbl> 1960, 1957, 1963, 1980, 1974, 1…
$ gender  <dbl> 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1…
$ ftobama <dbl> 100, 39, 1, 89, 1, 0, 73, 0, 12…
$ female  <dbl> 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0…
$ Party   <chr> "Democrat", "Independent", "Rep…

t-statistics tests can be used to test difference in means between two (or more) groups using a t-distribution.

0.2.2 one-sample t-test

To compare the mean in a sample against a hypothetical population mean. For example,let’s compare the sample mean of approval for candidate Donald Trump (in the 2016 elections) against the hypothetical population mean above 50 (out of a 100 point scale, which we would interpret as the point where people view him more positively than negatively).

But first, let’s confirm what is the mean approval rating for Trump:

NESdta_sub %>%
  summarize(mean_approval = mean(fttrump, na.rm = T))
NA

Now let’s run the one sample t-test providing the population mean in the[mu] argument equal to 50. since it’s a one sample t-test and there is no other group in our comparison, we compare our sample value of 38.37845 against a null model using the [~ 1]

# t-test fit

NESdta_sub %>%
t_test(fttrump ~ 1, mu = 50, detailed = TRUE)

We conclude that the difference between the mean we find in the sample and the hypothetical mean of 50 is statistically significant. The t-statistic is -11.07 and the p-value is < 0.001, so the difference in means is larger than what typically considered “statistically significant.”

0.2.3 Chi-square Test for Contingency Tables

We use the chi-square test to test whether the differences observed in a contingency tables are statistically significant, that is, if they are not due to random sampling error.

Let’s use the function tabyl from the package [janitor] to produce a contingency table:

NESdta_sub %>%   
 tabyl(Party, female)
       Party   0   1
    Democrat 188 268
 Independent 208 171
  Republican 129 151
        <NA>  44  36

We still have some missing values in our [Party] variable, so let’s exclude them using the drop. na():

NESdta_sub<-NESdta_sub %>%  drop_na() 

Next, let’s derive a contingency table for Party and female

NESdta_sub %>%   
 tabyl(Party, female)
       Party   0   1
    Democrat 188 268
 Independent 208 171
  Republican 129 151

And then we just add the chisq.test() to test the significance

NESdta_sub %>%
tabyl(Party, female) %>%
chisq.test()

    Pearson's Chi-squared test

data:  .
X-squared = 15.64, df = 2, p-value =
0.0004017

The chi-squared value is 15.64, and the corresponding p-value is 0.0004, which is lower than our 0.05 value. The results indicate that differences in party affiliations between male and female are much higher than we would have expected as a result of random chance.

0.2.3.1 Your turn:

  1. Using the NSEdta create a subset of the dataset: NESdta_sub2, that includes the following variables: [Hint: use the select function in the tydiverse]

meet -During the past 12 months, have you attended a meeting to talk about political- sign -Worn a campaign button, put a campaign sticker on your car, or placed a sign- pidlean -Party Id - Lean- vaccine -Favor/oppose requiring children to be vaccinated in order to attend public school- marstat -marital status-

NESsta_sub2<-NESdta %>% select(meet, info, sign, pidlean, vaccine, marstat)
  1. Using the NESdta_sub2 dataframe, create a new variable plean_cat where: 1 “Closer to the Republican Party” 2 “Closer to the Democratic Party” 3 “Neither” 4 “NA”

And remember to add the %>% drop_na() at the end to exclude the missing values for the purpose of this exercise (remember that in a full research analysis, we have to first explore if the missing values in a variable might be a sign of bias/issues in the data collection, that is, it’s important to explore whether and why some groups are more likely to show missing answers for a specific variable)

NESdta_sub2<- NESsta_sub2 %>% mutate(
  plean_cat = case_when(pidlean == 1 ~ "Closer to the Republican Party",
                        pidlean == 2 ~ "Closer to the Democratic Party", 
                        pidlean == 3 ~ "Neither")) %>% drop_na()
  1. Using the NESdta_sub2 dataframe, create a new variable vac2 to recode the vaccine variable into fewer categories,where: vac2 = “Favor” if vaccine is either = 1, 2 or 3

vac2 = “Neither” if vaccine is 4

vac2 = “Oppose” if vaccine is either 5, 6 or 7

NESdta_sub2<- NESdta_sub2 %>% mutate(
  vac2 = case_when(vaccine == 1 ~ "Favor",
                   vaccine == 2 ~ "Favor",
                   vaccine == 3 ~ "Favor",
                   vaccine == 4 ~ "Neither",
                   vaccine == 5 ~ "Oppose",
                   vaccine == 6 ~ "Oppose",
                   vaccine == 7 ~ "Oppose")) %>% drop_na()
  1. Using the NESdta_sub2 dataframe, create a new variable signcat to recode the sign variable,where: signcat = “Have done this in the past 12 months” if sign = 1

signcat = “Have NOT done this in the past 12 months” if sign =2

NESdta_sub2 <- NESdta_sub2 %>% mutate(signcat = case_when(sign == "1" ~ "Have done this in the past 12 months",
                                                          sign == "2" ~ "Have NOT done this in the past 12 months"), na.rm = TRUE) %>% drop_na() 
NESdta_sub2
  1. Produce a contingency table of plean_cat and vac2. Hint: use tabyl.
tabyl(NESdta_sub2, plean_cat, vac2)
                      plean_cat Favor Neither
 Closer to the Democratic Party   101       9
 Closer to the Republican Party    88      13
                        Neither   125      57
 Oppose
      8
     26
     32
  1. Produce a contingency table of plean_cat and signcat Hint: use tabyl.
tabyl(NESdta_sub2, plean_cat, signcat)
                      plean_cat
 Closer to the Democratic Party
 Closer to the Republican Party
                        Neither
 Have done this in the past 12 months
                                   22
                                   33
                                   21
 Have NOT done this in the past 12 months
                                       96
                                       94
                                      193
  1. Run a chisq.test() to test the significance of plean_cat and vac2. [Hint: just add chisq.test() using the pipe operator]
tabyl(NESdta_sub2, plean_cat, vac2) %>% chisq.test()

    Pearson's Chi-squared test

data:  .
X-squared = 37.233, df = 4, p-value =
1.613e-07
  1. What can we conclude based on the result of the Chi-square test?

Your answer here:

p-value = 1.613e-07 means that the test hypothesis is false or should be rejected.

  1. Run a chisq.test() to test the significance of plean_cat and sign
tabyl(NESdta_sub2, plean_cat, sign) %>% chisq.test()

    Pearson's Chi-squared test

data:  .
X-squared = 15.586, df = 2, p-value =
0.0004126
  1. What can we conclude based on the result of the Chi-square test?

Your answer here: p-value = 0.000412 means that the test hypothesis is false or should be rejected.

0.2.4 Dependent t-test:

Let’s import the file w12datdep1.csv.

# Import our first data set
w12datdep1 <- read.csv(file.choose())

Notice the difference between view() and our usual head().

# View what we just imported. Did we get what we expected?
View(w12datdep1)
# Use the function for the t test
t.test(w12datdep1$Posttest, w12datdep1$Pretest, paired = TRUE, alternative = "greater")

    Paired t-test

data:  w12datdep1$Posttest and w12datdep1$Pretest
t = 2.4495, df = 24, p-value = 0.01099
alternative hypothesis: true mean difference is greater than 0
95 percent confidence interval:
 0.3618424       Inf
sample estimates:
mean difference 
            1.2 

Let’s look at a scatterplot before calculating a correlation

# Let's look at a scatterplot before calculating a correlation

ggplot(w12datdep1, aes(Pretest,Posttest)) +
  geom_point() +
  xlab("Pretest") +
  ylab("Posttest") +
  ggtitle("Pretest and Posttest Reading Achievement Scores") +
  theme_minimal() +
  scale_fill_brewer(palette="Blues") 

NA
NA
NA

Now let’s calculate the correlation:

cor(w12datdep1$Pretest, w12datdep1$Posttest)
[1] 0.05071834

Not only is the difference significant, but the size of the difference is nontrivial.

0.2.5 Let’s practice a bit more: Independent t-test:

0.2.5.1 Example 1

Let’s import the w12data1.csv file.


# Import our first data set
w12data1 <- read_csv(file.choose())
Rows: 36 Columns: 2── Column specification ─────────────────────────
Delimiter: ","
dbl (2): Qual.Marriage, Qual.PC
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# View what we just imported. Did we get what we expected?
head(w12data1)

Let’s calculate the correlation


# Calculate the correlation
cor(w12data1$Qual.Marriage, w12data1$Qual.PC)
[1] -0.09996305

# Look at a scatterplot of the data
plot(w12data1$Qual.Marriage, w12data1$Qual.PC, 
     xlab = "Marriage Quality", ylab = "Parent-Child Interaction Quality",
     main = "Scatterplot")+
theme_minimal() 
NULL

Now let’s obtain the correlation and a test of statistical significance


# Get the correlation and a test of statistical significance
cor.test(w12data1$Qual.Marriage, w12data1$Qual.PC)

    Pearson's product-moment correlation

data:  w12data1$Qual.Marriage and w12data1$Qual.PC
t = -0.58581, df = 34, p-value = 0.5619
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 -0.4148737  0.2363342
sample estimates:
        cor 
-0.09996305 

And if we were interested in getting a one-tail test:

# Ask for one-tailed test results
cor.test(w12data1$Qual.Marriage, w12data1$Qual.PC, alternative = "greater")

    Pearson's product-moment correlation

data:  w12data1$Qual.Marriage and w12data1$Qual.PC
t = -0.58581, df = 34, p-value = 0.7191
alternative hypothesis: true correlation is greater than 0
95 percent confidence interval:
 -0.3684516  1.0000000
sample estimates:
        cor 
-0.09996305 

0.2.5.2 Example 2

Let’s import the w12data2.csv file.

# Import our first data set
w12data2 <- read.csv(file.choose())
head(w12data2)
NA

When we run the t-test with the var.equal = TRUE, we are telling the t.test() function that our groups have equal variance, we will learn a test for this later.

# Run the t test

t.test(MemoryTest ~ Group, data = w12data2, var.equal = TRUE)

    Two Sample t-test

data:  MemoryTest by Group
t = -0.1371, df = 58, p-value = 0.8914
alternative hypothesis: true difference in means between group 1 and group 2 is not equal to 0
95 percent confidence interval:
 -1.560009  1.360009
sample estimates:
mean in group 1 mean in group 2 
       5.433333        5.533333 

We are using MemoryTest ~ Group:, as MemoryTest is the score we are comparing across our groups, with 1 used for the treatment group and 2 for the control group in the variable Group.

And the var.equal = TRUE tells the t.test() function that the groups have equal variance.

The results, t = –0.1371, df = 58, p = .8914, tell us the t, the degrees of freedom for our test, and the exact p.

Let’s look at the boxplot between memory test and group, and save the plot in a new object [memory], so we can access some of the summary stats used to construct it.

memory <- boxplot(MemoryTest ~ Group, data = w12data2, main = "Memory Test Scores",
        xlab = "Groups", ylab = "Scores")

Now we can use our new memory object to look at the distribution of numbers in the two groups using the stats option after running the plot. Based on what we can see from the plot, we can see the variance is different between our groups, but we don’t really know whether it is VERY different. So we will use a statistic to answer this question, the Levene’s test.

# Show the numbers used to create the boxplot
# [1] Lower whisker
# [2] 25th percentile value
# [3] 50th percentile value - median
# [4] 75th percentile value
# [5] Uppoer whisker
memory$stats
     [,1] [,2]
[1,]    1  2.0
[2,]    3  4.0
[3,]    5  5.5
[4,]    8  7.0
[5,]   15  9.0

We will now use Levene’s test from the package [car] to test the null hypothesis that the variances are equal, and the research hypothesis is that they are different. Let’s use p < .05 to signal that we should reject our null hypothesis.

# Test to see if the variances are equal in the two groups
leveneTest(MemoryTest ~ as.factor(Group), data = w12data2)
Levene's Test for Homogeneity of Variance (center = median)
      Df F value  Pr(>F)  
group  1  3.3429 0.07264 .
      58                  
---
Signif. codes:  
0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Levene’s test is F(1, 58) = 3.34, p = .07. The p for Levene’s test exceeds .05, so we fail to reject the null hypothesis of equal variance. We are going to omit var.equal statement, and what this means is that R will use a different t-test -the Welch’s t test-. This is going to change the number of degrees of freedom in the calculation to minimize Type I or Type II error. In our specific example, the p-value with the Welch’s test still leads to the same conclusion, and we fail to reject the null hypothesis of no difference in the memory test results between the treatment and control groups.

# Re-run t.test with var.equal omitted
t.test(MemoryTest ~ Group, data = w12data2)

    Welch Two Sample t-test

data:  MemoryTest by Group
t = -0.1371, df = 47.635, p-value = 0.8915
alternative hypothesis: true difference in means between group 1 and group 2 is not equal to 0
95 percent confidence interval:
 -1.566803  1.366803
sample estimates:
mean in group 1 mean in group 2 
       5.433333        5.533333 
# Look at help for t.test
?t.test

0.2.5.3 Your turn

  1. Import the data in the file named w12data3.csv: [Hint: import the data uwing read_csv.]
# Import our first data set
w12data3 <- read.csv(file.choose())
  1. Compute the correlation between motivation and GPA.
cor(w12data3$Motivation, w12data3$GPA)
[1] 0.4340226
  1. Test for the significance of the correlation coefficient at the .05 level using a two-tailed test.
cor.test(w12data3$Motivation, w12data3$GPA)

    Pearson's product-moment correlation

data:  w12data3$Motivation and w12data3$GPA
t = 2.5493, df = 28, p-value = 0.01656
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.08742338 0.68688681
sample estimates:
      cor 
0.4340226 
  1. Interpret the results:

Your answer here: significant positive correlation but not absolute.

True or false? The more highly you are motivated, the more you will study. Your answer here:

True

  1. Import the data in the file named w12data4.csv: [Hint: import the data using read.csv.]
# Import our first data set
w12data4 <- read.csv(file.choose())
  1. Compute the correlation between income and level of education.
cor(w12data4$Income, w12data4$Level.of.Education)
[1] 0.6289264
  1. Test for the significance of the correlation coefficient at the .05 level using a two-tailed test.
cor.test(w12data4$Income, w12data4$Level.of.Education)

    Pearson's product-moment correlation

data:  w12data4$Income and w12data4$Level.of.Education
t = 3.4321, df = 18, p-value = 0.002973
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.2582914 0.8381728
sample estimates:
      cor 
0.6289264 
  1. Interpret the result.

Your answer here: positive correlation between education and income

  1. Import the data in the file named w12data5.csv: [Hint: import the data using read.csv.]
# Import our first data set
w12data5 <- read.csv(file.choose())
  1. Compute the correlation between hours of studying and grade.
cor(w12data5$Hours.of.Study, w12data5$Grade)
[1] 0.6858935
  1. Test for the significance of the correlation coefficient at the .05 level using a two-tailed test between hours of studying and grade. [hint: make sure your variable names are correct]
cor.test(w12data5$Hours.of.Study, w12data5$Grade)

    Pearson's product-moment correlation

data:  w12data5$Hours.of.Study and w12data5$Grade
t = 2.6659, df = 8, p-value = 0.02854
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.09903704 0.91875110
sample estimates:
      cor 
0.6858935 
  1. Interpret this correlation

Your answer here: positive correlation among grade and study hours

  1. How much variance is shared between the two variables? [hint: remember the coefficient of determination is r2 -you can compute it directly in R, try cor^2, where cor is the value of your correlation coefficient]
0.6858935^2
[1] 0.4704499

Your answer here: 0.4704499 The shared variance equals: 47%

LS0tCnRpdGxlOiAiUFVBRCA1MTQwIgpzdWJ0aXRsZTogIlRlc3QgdGltZSIKYXV0aG9yOiAiSmVzc2UgTGV3aXMiCmRhdGU6ICJOb3ZlbWJlciAyOSwgMjAyMiIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICBoaWdobGlnaHQ6IGhhZGRvY2sKICAgIHRvY19kZXB0aDogNQogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIHRoZW1lOiBjZXJ1bGVhbgogICAgaGlnaGxpZ2h0OiBoYWRkb2NrCiAgICB0b2NfZGVwdGg6IDUKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwotLS0KCiMjIEZpcnN0IHRoaW5ncyBmaXJzdAoKYGBge3J9Cmluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpCmluc3RhbGwucGFja2FnZXMoImNhciIpCmluc3RhbGwucGFja2FnZXMoImhhdmVuIikKaW5zdGFsbC5wYWNrYWdlcygiY29ycnIiKQppbnN0YWxsLnBhY2thZ2VzKCJqYW5pdG9yIikKaW5zdGFsbC5wYWNrYWdlcygicnN0YXRpeCIpCgpgYGAKCgpgYGB7cn0KCmxpYnJhcnkoY2FyKSAjIExvYWQgdGhlIGxpYnJhcnkgY2FyIHNvIHdlIGNhbiBydW4gbGV2ZW5lVGVzdCwgaW5zdGFsbCBpZiBuZWVkZWQgCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGhhdmVuKSAjaW1wb3J0IGZpbGVzIHByb2R1Y2VkIGluIG90aGVyIHN0YXRpc3RpY2FsIHNvZnR3YXJlCmxpYnJhcnkoY29ycnIpICNJbmNsdWRlcyBmdW5jdGlvbnMgdG8gZXZhbHVhdGUgY29ycmVsYXRpb25zIHdpdGhpbiB0aGUgdGlkeXZlcnNlCmxpYnJhcnkoamFuaXRvcikgI1RvIGFuYWx5emUgY3Jvc3MtdGFidWxhdGlvbiDigJMgY2hpLXNxdWFyZWQKbGlicmFyeShyc3RhdGl4KSAjT25lIG9mIG1hbnkgcGFja2FnZXMgdXNlZCBmb3IgdC10ZXN0cwoKCmBgYAoKCiMjIHQtc3RhdGlzdGljcwoKIyMjIExldCdzIHByYWN0aWNlIGltcG9ydGluZyBkYXRhIGFnYWluIAogCiMjIyMgWW91ciB0dXJuOgpJbXBvcnQgdGhlICJhbmVzX3BpbG90XzIwMTYuZHRhIiBmaWxlIGFuZCBjcmVhdGUgYSBkYXRhZnJhbWUgTkVTZHRhLiBUaGlzIGlzIGFuIFN0YXRhIGZpbGUgc28gd2UgbmVlZCB0byB1c2UgdGhlIGhhdmVuIHBhY2thZ2UuIEhpbnQ6IHVzZXMgcmVhZF9kdGEoKQoKYGBge3J9CiMgVXNpbmcgUiB0byBpbXBvcnQgYW4gU3RhdGEgZmlsZXNkCk5FU2R0YTwtIGFuZXNfcGlsb3RfMjAxNgoKCmBgYAoKVmlldyB3aGF0IHdlIGp1c3QgaW1wb3J0ZWQuIERpZCB3ZSBnZXQgd2hhdCB3ZSBleHBlY3RlZD8KCmBgYHtyfQpoZWFkKE5FU2R0YSkKCmBgYAoKCk5vdyBsZXQncyBjcmVhdGUgYSBuZXcgZGF0YWZyYW1lIE5FU2RhdGFfc3ViIHdpdGggYSBzdWJzZXQgb2YgdmFyaWFibGVzOiBmdHRydW1wLCBwaWQzLCBiaXJ0aHlyLCBnZW5kZXIsIGZ0b2JhbWEuIEhpbnQ6IHVzZSB0aGUgc2VsZWN0IGZ1bmN0aW9uIGZyb20gdGhlIHRpZHl2ZXJzZS4gSGludDogbWFrZSBzdXJlIHlvdSBoYXZlIGxvYWQgeW91ciB0aWR5dmVyc2UgcGFja2FnZS4gVGhlIHZhcmlhYmxlcyBpbiBvdXIgc3Vic2V0IGNvbWUgZnJvbSB0aGUgQW1lcmljYW4gTmF0aW9uYWwgRWxlY3Rpb24gU3R1ZGllcywgd2hlcmUgZnR0cnVtcCBpcyBhIEZlZWxpbmcgdGhlcm1vbWV0ZXIgZm9yIFRydW1wIGluIDIwMTYgKGZyb20gMSB0byAxMDAsIHdoZXJlIDEgPSBjb2xkIGFuZCAxMDAgPSB3YXJtKSwgcGlkMyBpcyB0aGUgcmVzcG9uZGVudOKAmXMgcGFydHkgYWZmaWxpYXRpb24gKDEgPSBEZW1vY3JhdCwgMiA9IEluZGVwZW5kZW50LCAzID0gUmVwdWJsaWNhbiksICBiaXJ0aHlyIGlzIHRoZSByZXNwb25kZW504oCZcyBiaXJ0aCB5ZWFyLCBnZW5kZXIgaXMgdGhlIHJlc3BvbmRlbnTigJlzIGdlbmRlciAoMSA9IG1hbGUgYW5kIDIgPSBmZW1hbGUpIGFuZCBmdG9iYW1hIGlzIGEgIGZlZWxpbmcgdGhlcm1vbWV0ZXIgZm9yIE9iYW1hIGluIDIwMTYgKGZyb20gMSB0byAxMDAsIHdoZXJlIDEgPSBjb2xkIGFuZCAxMDAgPSB3YXJtKQoKVXNpbmcgdGhlIHBpcGUgb3BlcmF0b3IgWyAlPiVdIGRvIHRoZSBmb2xsb3dpbmc6ICAKCnJlcGxhY2UgYWxsIHZhbHVlcyB3aGVyZSBmdHRydW1wPjEwMCBmb3IgTkEKcmVwbGFjZSBhbGwgdmFsdWVzIHdoZXJlIGZ0b2JhbWE+OTk4IGZvciBOQQpjcmVhdGUgYSBuZXcgdmFyaWFibGUgZmVtYWxlIApkcm9wIG1pc3NpbmcgdmFsdWVzIG9uIHRoZSBzdWJzZXQgZGF0YQoKYGBge3J9Ck5FU2R0YV9zdWIgPC0gTkVTZHRhICU+JQogIGRwbHlyOjpzZWxlY3QoZnR0cnVtcCwgcGlkMywgYmlydGh5ciwgZ2VuZGVyLCBmdG9iYW1hKSAlPiUKICBtdXRhdGUoZnR0cnVtcCA9IHJlcGxhY2UoZnR0cnVtcCwgZnR0cnVtcCA+IDEwMCwgTkEpLAogICAgICAgICBmdG9iYW1hID0gcmVwbGFjZShmdG9iYW1hLCBmdG9iYW1hID09IDk5OCwgTkEpLAogICAgICAgICBmZW1hbGUgPSBpZmVsc2UoZ2VuZGVyID09IDIsIDEsIDApKSAlPiUKICBhcy5kYXRhLmZyYW1lKCkgJT4lCiAgZHJvcF9uYSgpCgpgYGAKCgojIyMjIFlvdXIgdHVybjogUmVjb2RpbmcgdmFyaWFibGUKClVzaW5nIHRoZSBORVNkdGFfc3ViLCBjcmVhdGUgYSBuZXcgdmFyaWFibGUgW1BhcnR5XSB3aGVyZTogW0hpbnQ6IHVzZSB0aGUgbXV0YXRlIGFuZCBjYXNlX3doZW4gZnVuY3Rpb25zIF0KUGFydHkgaXMgZXF1YWwgdG8gIkRlbW9jcmF0IiBpZiBwaWQzIGlzIDEsIApQYXJ0eSBpcyBlcXVhbCB0byAiUmVwdWJsaWNhbiIgaWYgcGlkMyBpcyAyLCAKUGFydHkgaXMgZXF1YWwgdG8gIkluZGVwZW5kZW50IiBpZiBwaWQzIGlzIDMKCgpgYGB7cn0KTkVTZHRhX3N1YiA8LSBORVNkdGFfc3ViICU+JSAKICBtdXRhdGUoUGFydHkgPSBjYXNlX3doZW4ocGlkMyA9PSAxIH4gIkRlbW9jcmF0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHBpZDMgPT0gMiB+ICJSZXB1YmxpY2FuIiwgcGlkMyA9PSAzIH4gIkluZGVwZW5kZW50IikpCmBgYAoKCkxldCdzIHVzZSB0aGUgZ2xpbXBzZSBmdW5jdGlvbiB0byBjaGVjayBpZiB0aGUgZGF0YXNldCBsb29rcyBva2F5CmBgYHtyfQpnbGltcHNlKE5FU2R0YV9zdWIpCgpgYGAKIAogCnQtc3RhdGlzdGljcyB0ZXN0cyBjYW4gYmUgdXNlZCB0byB0ZXN0IGRpZmZlcmVuY2UgaW4gbWVhbnMgYmV0d2VlbiB0d28gKG9yIG1vcmUpIGdyb3VwcyB1c2luZyBhIHQtZGlzdHJpYnV0aW9uLiAKCiMjIyBvbmUtc2FtcGxlIHQtdGVzdAoKVG8gY29tcGFyZSB0aGUgbWVhbiBpbiBhIHNhbXBsZSBhZ2FpbnN0IGEgaHlwb3RoZXRpY2FsIHBvcHVsYXRpb24gbWVhbi4gRm9yIGV4YW1wbGUsbGV0J3MgY29tcGFyZSB0aGUgc2FtcGxlIG1lYW4gb2YgYXBwcm92YWwgZm9yIGNhbmRpZGF0ZSBEb25hbGQgVHJ1bXAgKGluIHRoZSAyMDE2IGVsZWN0aW9ucykgYWdhaW5zdCB0aGUgaHlwb3RoZXRpY2FsIHBvcHVsYXRpb24gbWVhbiBhYm92ZSA1MCAob3V0IG9mIGEgMTAwIHBvaW50IHNjYWxlLCB3aGljaCB3ZSB3b3VsZCBpbnRlcnByZXQgYXMgdGhlIHBvaW50IHdoZXJlIHBlb3BsZSB2aWV3IGhpbSBtb3JlIHBvc2l0aXZlbHkgdGhhbiBuZWdhdGl2ZWx5KS4KCkJ1dCBmaXJzdCwgbGV0J3MgY29uZmlybSB3aGF0IGlzIHRoZSBtZWFuIGFwcHJvdmFsIHJhdGluZyBmb3IgVHJ1bXA6IAoKYGBge3J9Ck5FU2R0YV9zdWIgJT4lCiAgc3VtbWFyaXplKG1lYW5fYXBwcm92YWwgPSBtZWFuKGZ0dHJ1bXAsIG5hLnJtID0gVCkpCgpgYGAKTm93IGxldCdzIHJ1biB0aGUgb25lIHNhbXBsZSB0LXRlc3QgcHJvdmlkaW5nIHRoZSBwb3B1bGF0aW9uIG1lYW4gaW4gdGhlW211XSBhcmd1bWVudCBlcXVhbCB0byA1MC4gc2luY2UgaXQncyBhIG9uZSBzYW1wbGUgdC10ZXN0IGFuZCB0aGVyZSBpcyBubyBvdGhlciBncm91cCBpbiBvdXIgY29tcGFyaXNvbiwgd2UgIGNvbXBhcmUgb3VyIHNhbXBsZSB2YWx1ZSBvZiAzOC4zNzg0NSBhZ2FpbnN0IGEgbnVsbCBtb2RlbCB1c2luZyB0aGUgW34gMV0KYGBge3J9CiMgdC10ZXN0IGZpdAoKTkVTZHRhX3N1YiAlPiUKdF90ZXN0KGZ0dHJ1bXAgfiAxLCBtdSA9IDUwLCBkZXRhaWxlZCA9IFRSVUUpCmBgYApXZSBjb25jbHVkZSB0aGF0IHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIG1lYW4gd2UgZmluZCBpbiB0aGUgc2FtcGxlIGFuZCB0aGUgaHlwb3RoZXRpY2FsIG1lYW4gb2YgNTAgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4gVGhlIHQtc3RhdGlzdGljIGlzIC0xMS4wNyBhbmQgdGhlIHAtdmFsdWUgaXMgPCAwLjAwMSwgc28gdGhlIGRpZmZlcmVuY2UgaW4gbWVhbnMgaXMgbGFyZ2VyIHRoYW4gd2hhdCB0eXBpY2FsbHkgY29uc2lkZXJlZCDigJxzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LuKAnQoKCgojIyMgQ2hpLXNxdWFyZSBUZXN0IGZvciBDb250aW5nZW5jeSBUYWJsZXMKCgpXZSB1c2UgdGhlIGNoaS1zcXVhcmUgdGVzdCB0byB0ZXN0IHdoZXRoZXIgdGhlIGRpZmZlcmVuY2VzIG9ic2VydmVkIGluIGEgY29udGluZ2VuY3kgdGFibGVzIGFyZSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LCB0aGF0IGlzLCBpZiB0aGV5IGFyZSBub3QgZHVlIHRvIHJhbmRvbSBzYW1wbGluZyBlcnJvci4KCkxldCdzIHVzZSB0aGUgZnVuY3Rpb24gdGFieWwgZnJvbSB0aGUgcGFja2FnZSBbamFuaXRvcl0gdG8gcHJvZHVjZSBhIGNvbnRpbmdlbmN5IHRhYmxlOgoKYGBge3J9Ck5FU2R0YV9zdWIgJT4lICAgCiB0YWJ5bChQYXJ0eSwgZmVtYWxlKQpgYGAKCldlIHN0aWxsIGhhdmUgc29tZSBtaXNzaW5nIHZhbHVlcyBpbiBvdXIgW1BhcnR5XSB2YXJpYWJsZSwgc28gbGV0J3MgZXhjbHVkZSB0aGVtIHVzaW5nIHRoZSBkcm9wLiBuYSgpOgoKYGBge3J9Ck5FU2R0YV9zdWI8LU5FU2R0YV9zdWIgJT4lICBkcm9wX25hKCkgCmBgYAoKTmV4dCwgbGV0J3MgZGVyaXZlIGEgY29udGluZ2VuY3kgdGFibGUgZm9yIFBhcnR5IGFuZCBmZW1hbGUgCgpgYGB7cn0KTkVTZHRhX3N1YiAlPiUgICAKIHRhYnlsKFBhcnR5LCBmZW1hbGUpCmBgYAoKCkFuZCB0aGVuIHdlIGp1c3QgYWRkIHRoZSBjaGlzcS50ZXN0KCkgdG8gdGVzdCB0aGUgc2lnbmlmaWNhbmNlIApgYGB7cn0KTkVTZHRhX3N1YiAlPiUKdGFieWwoUGFydHksIGZlbWFsZSkgJT4lCmNoaXNxLnRlc3QoKQpgYGAKVGhlIGNoaS1zcXVhcmVkIHZhbHVlIGlzIDE1LjY0LCBhbmQgdGhlIGNvcnJlc3BvbmRpbmcgcC12YWx1ZSBpcyAwLjAwMDQsIHdoaWNoIGlzIGxvd2VyIHRoYW4gb3VyIDAuMDUgdmFsdWUuIFRoZSByZXN1bHRzIGluZGljYXRlIHRoYXQgZGlmZmVyZW5jZXMgaW4gcGFydHkgYWZmaWxpYXRpb25zIGJldHdlZW4gbWFsZSBhbmQgZmVtYWxlIGFyZSBtdWNoIGhpZ2hlciB0aGFuIHdlIHdvdWxkIGhhdmUgZXhwZWN0ZWQgYXMgYSByZXN1bHQgb2YgcmFuZG9tIGNoYW5jZS4gCgoKIyMjIyBZb3VyIHR1cm46CjEpIFVzaW5nIHRoZSBOU0VkdGEgY3JlYXRlIGEgc3Vic2V0IG9mIHRoZSBkYXRhc2V0OiBORVNkdGFfc3ViMiwgdGhhdCBpbmNsdWRlcyB0aGUgZm9sbG93aW5nIHZhcmlhYmxlczogW0hpbnQ6IHVzZSB0aGUgc2VsZWN0IGZ1bmN0aW9uIGluIHRoZSB0eWRpdmVyc2VdCgptZWV0IC1EdXJpbmcgdGhlIHBhc3QgMTIgbW9udGhzLCBoYXZlIHlvdSBhdHRlbmRlZCBhIG1lZXRpbmcgdG8gdGFsayBhYm91dCBwb2xpdGljYWwtCnNpZ24gLVdvcm4gYSBjYW1wYWlnbiBidXR0b24sIHB1dCBhIGNhbXBhaWduIHN0aWNrZXIgb24geW91ciBjYXIsIG9yIHBsYWNlZCBhIHNpZ24tCnBpZGxlYW4gLVBhcnR5IElkIC0gTGVhbi0KdmFjY2luZSAtRmF2b3Ivb3Bwb3NlIHJlcXVpcmluZyBjaGlsZHJlbiB0byBiZSB2YWNjaW5hdGVkIGluIG9yZGVyIHRvIGF0dGVuZCBwdWJsaWMgc2Nob29sLQptYXJzdGF0IC1tYXJpdGFsIHN0YXR1cy0KCgpgYGB7cn0KTkVTc3RhX3N1YjI8LU5FU2R0YSAlPiUgc2VsZWN0KG1lZXQsIGluZm8sIHNpZ24sIHBpZGxlYW4sIHZhY2NpbmUsIG1hcnN0YXQpCmBgYAoKCjIpIFVzaW5nIHRoZSBORVNkdGFfc3ViMiBkYXRhZnJhbWUsIGNyZWF0ZSBhIG5ldyB2YXJpYWJsZSBwbGVhbl9jYXQgd2hlcmU6CjEgIkNsb3NlciB0byB0aGUgUmVwdWJsaWNhbiBQYXJ0eSIKMiAiQ2xvc2VyIHRvIHRoZSBEZW1vY3JhdGljIFBhcnR5IgozICJOZWl0aGVyIgo0ICJOQSIKCkFuZCByZW1lbWJlciB0byBhZGQgdGhlICU+JSBkcm9wX25hKCkgYXQgdGhlIGVuZCB0byBleGNsdWRlIHRoZSBtaXNzaW5nIHZhbHVlcyBmb3IgdGhlIHB1cnBvc2Ugb2YgdGhpcyBleGVyY2lzZSAocmVtZW1iZXIgdGhhdCBpbiBhIGZ1bGwgcmVzZWFyY2ggYW5hbHlzaXMsIHdlIGhhdmUgdG8gZmlyc3QgZXhwbG9yZSBpZiB0aGUgbWlzc2luZyB2YWx1ZXMgaW4gYSB2YXJpYWJsZSBtaWdodCBiZSBhIHNpZ24gb2YgYmlhcy9pc3N1ZXMgaW4gdGhlIGRhdGEgY29sbGVjdGlvbiwgdGhhdCBpcywgaXQncyBpbXBvcnRhbnQgdG8gZXhwbG9yZSB3aGV0aGVyIGFuZCB3aHkgc29tZSBncm91cHMgYXJlIG1vcmUgbGlrZWx5IHRvIHNob3cgbWlzc2luZyBhbnN3ZXJzIGZvciBhIHNwZWNpZmljIHZhcmlhYmxlKQpgYGB7cn0KTkVTZHRhX3N1YjI8LSBORVNzdGFfc3ViMiAlPiUgbXV0YXRlKAogIHBsZWFuX2NhdCA9IGNhc2Vfd2hlbihwaWRsZWFuID09IDEgfiAiQ2xvc2VyIHRvIHRoZSBSZXB1YmxpY2FuIFBhcnR5IiwKICAgICAgICAgICAgICAgICAgICAgICAgcGlkbGVhbiA9PSAyIH4gIkNsb3NlciB0byB0aGUgRGVtb2NyYXRpYyBQYXJ0eSIsIAogICAgICAgICAgICAgICAgICAgICAgICBwaWRsZWFuID09IDMgfiAiTmVpdGhlciIpKSAlPiUgZHJvcF9uYSgpCmBgYAoKMykgVXNpbmcgdGhlIE5FU2R0YV9zdWIyIGRhdGFmcmFtZSwgY3JlYXRlIGEgbmV3IHZhcmlhYmxlIHZhYzIgdG8gcmVjb2RlIHRoZSB2YWNjaW5lIHZhcmlhYmxlIGludG8gZmV3ZXIgY2F0ZWdvcmllcyx3aGVyZToKdmFjMiA9ICJGYXZvciIgaWYgdmFjY2luZSBpcyBlaXRoZXIgPSAxLCAyIG9yIDMKCnZhYzIgPSAiTmVpdGhlciIgaWYgdmFjY2luZSBpcyA0Cgp2YWMyID0gIk9wcG9zZSIgaWYgdmFjY2luZSBpcyBlaXRoZXIgNSwgNiBvciA3CgpgYGB7cn0KTkVTZHRhX3N1YjI8LSBORVNkdGFfc3ViMiAlPiUgbXV0YXRlKAogIHZhYzIgPSBjYXNlX3doZW4odmFjY2luZSA9PSAxIH4gIkZhdm9yIiwKICAgICAgICAgICAgICAgICAgIHZhY2NpbmUgPT0gMiB+ICJGYXZvciIsCiAgICAgICAgICAgICAgICAgICB2YWNjaW5lID09IDMgfiAiRmF2b3IiLAogICAgICAgICAgICAgICAgICAgdmFjY2luZSA9PSA0IH4gIk5laXRoZXIiLAogICAgICAgICAgICAgICAgICAgdmFjY2luZSA9PSA1IH4gIk9wcG9zZSIsCiAgICAgICAgICAgICAgICAgICB2YWNjaW5lID09IDYgfiAiT3Bwb3NlIiwKICAgICAgICAgICAgICAgICAgIHZhY2NpbmUgPT0gNyB+ICJPcHBvc2UiKSkgJT4lIGRyb3BfbmEoKQpgYGAKCgo0KSBVc2luZyB0aGUgTkVTZHRhX3N1YjIgZGF0YWZyYW1lLCBjcmVhdGUgYSBuZXcgdmFyaWFibGUgc2lnbmNhdCB0byByZWNvZGUgdGhlIHNpZ24gdmFyaWFibGUsd2hlcmU6CnNpZ25jYXQgPSAiSGF2ZSBkb25lIHRoaXMgaW4gdGhlIHBhc3QgMTIgbW9udGhzIiBpZiBzaWduICA9IDEKCnNpZ25jYXQgPSAiSGF2ZSBOT1QgZG9uZSB0aGlzIGluIHRoZSBwYXN0IDEyIG1vbnRocyIgaWYgc2lnbiA9MgoKCmBgYHtyfQpORVNkdGFfc3ViMiA8LSBORVNkdGFfc3ViMiAlPiUgbXV0YXRlKHNpZ25jYXQgPSBjYXNlX3doZW4oc2lnbiA9PSAiMSIgfiAiSGF2ZSBkb25lIHRoaXMgaW4gdGhlIHBhc3QgMTIgbW9udGhzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpZ24gPT0gIjIiIH4gIkhhdmUgTk9UIGRvbmUgdGhpcyBpbiB0aGUgcGFzdCAxMiBtb250aHMiKSwgbmEucm0gPSBUUlVFKSAlPiUgZHJvcF9uYSgpIApORVNkdGFfc3ViMgpgYGAKCgo1KSBQcm9kdWNlIGEgY29udGluZ2VuY3kgdGFibGUgb2YgcGxlYW5fY2F0IGFuZCB2YWMyLiBIaW50OiB1c2UgdGFieWwuIAoKYGBge3J9CnRhYnlsKE5FU2R0YV9zdWIyLCBwbGVhbl9jYXQsIHZhYzIpCmBgYAoKCgo1KSBQcm9kdWNlIGEgY29udGluZ2VuY3kgdGFibGUgb2YgcGxlYW5fY2F0IGFuZCBzaWduY2F0IEhpbnQ6IHVzZSB0YWJ5bC4gCgpgYGB7cn0KdGFieWwoTkVTZHRhX3N1YjIsIHBsZWFuX2NhdCwgc2lnbmNhdCkKYGBgCgo2KSBSdW4gYSBjaGlzcS50ZXN0KCkgdG8gdGVzdCB0aGUgc2lnbmlmaWNhbmNlIG9mIHBsZWFuX2NhdCBhbmQgdmFjMi4gW0hpbnQ6IGp1c3QgYWRkIGNoaXNxLnRlc3QoKSB1c2luZyB0aGUgcGlwZSBvcGVyYXRvcl0KYGBge3J9CnRhYnlsKE5FU2R0YV9zdWIyLCBwbGVhbl9jYXQsIHZhYzIpICU+JSBjaGlzcS50ZXN0KCkKYGBgCjcpIFdoYXQgY2FuIHdlIGNvbmNsdWRlIGJhc2VkIG9uIHRoZSByZXN1bHQgb2YgdGhlIENoaS1zcXVhcmUgdGVzdD8KCllvdXIgYW5zd2VyIGhlcmU6CgpwLXZhbHVlID0gMS42MTNlLTA3IG1lYW5zIHRoYXQgdGhlIHRlc3QgaHlwb3RoZXNpcyBpcyBmYWxzZSBvciBzaG91bGQgYmUgcmVqZWN0ZWQuCgo4KSBSdW4gYSBjaGlzcS50ZXN0KCkgdG8gdGVzdCB0aGUgc2lnbmlmaWNhbmNlIG9mIHBsZWFuX2NhdCBhbmQgc2lnbgpgYGB7cn0KdGFieWwoTkVTZHRhX3N1YjIsIHBsZWFuX2NhdCwgc2lnbikgJT4lIGNoaXNxLnRlc3QoKQpgYGAKCjkpIFdoYXQgY2FuIHdlIGNvbmNsdWRlIGJhc2VkIG9uIHRoZSByZXN1bHQgb2YgdGhlIENoaS1zcXVhcmUgdGVzdD8KCllvdXIgYW5zd2VyIGhlcmU6CnAtdmFsdWUgPSAwLjAwMDQxMiBtZWFucyB0aGF0IHRoZSB0ZXN0IGh5cG90aGVzaXMgaXMgZmFsc2Ugb3Igc2hvdWxkIGJlIHJlamVjdGVkLgoKCiMjIyBEZXBlbmRlbnQgdC10ZXN0OgoKTGV0J3MgaW1wb3J0IHRoZSBmaWxlIHcxMmRhdGRlcDEuY3N2LgoKYGBge3J9CiMgSW1wb3J0IG91ciBmaXJzdCBkYXRhIHNldAp3MTJkYXRkZXAxIDwtIHJlYWQuY3N2KGZpbGUuY2hvb3NlKCkpCmBgYAoKTm90aWNlIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdmlldygpIGFuZCBvdXIgdXN1YWwgaGVhZCgpLgpgYGB7cn0KIyBWaWV3IHdoYXQgd2UganVzdCBpbXBvcnRlZC4gRGlkIHdlIGdldCB3aGF0IHdlIGV4cGVjdGVkPwpWaWV3KHcxMmRhdGRlcDEpCmBgYAoKCmBgYHtyfQojIFVzZSB0aGUgZnVuY3Rpb24gZm9yIHRoZSB0IHRlc3QKdC50ZXN0KHcxMmRhdGRlcDEkUG9zdHRlc3QsIHcxMmRhdGRlcDEkUHJldGVzdCwgcGFpcmVkID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAiZ3JlYXRlciIpCmBgYAoKTGV0J3MgbG9vayBhdCBhIHNjYXR0ZXJwbG90IGJlZm9yZSBjYWxjdWxhdGluZyBhIGNvcnJlbGF0aW9uCmBgYHtyfQojIExldCdzIGxvb2sgYXQgYSBzY2F0dGVycGxvdCBiZWZvcmUgY2FsY3VsYXRpbmcgYSBjb3JyZWxhdGlvbgoKZ2dwbG90KHcxMmRhdGRlcDEsIGFlcyhQcmV0ZXN0LFBvc3R0ZXN0KSkgKwogIGdlb21fcG9pbnQoKSArCiAgeGxhYigiUHJldGVzdCIpICsKICB5bGFiKCJQb3N0dGVzdCIpICsKICBnZ3RpdGxlKCJQcmV0ZXN0IGFuZCBQb3N0dGVzdCBSZWFkaW5nIEFjaGlldmVtZW50IFNjb3JlcyIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGU9IkJsdWVzIikgCgoKCmBgYAoKTm93IGxldCdzIGNhbGN1bGF0ZSB0aGUgY29ycmVsYXRpb246CmBgYHtyfQpjb3IodzEyZGF0ZGVwMSRQcmV0ZXN0LCB3MTJkYXRkZXAxJFBvc3R0ZXN0KQoKYGBgCgpOb3Qgb25seSBpcyB0aGUgZGlmZmVyZW5jZSBzaWduaWZpY2FudCwgYnV0IHRoZSBzaXplIG9mIHRoZSBkaWZmZXJlbmNlIGlzIG5vbnRyaXZpYWwuIAoKCgoKIyMjIExldCdzIHByYWN0aWNlIGEgYml0IG1vcmU6IEluZGVwZW5kZW50IHQtdGVzdDogCgojIyMjIEV4YW1wbGUgMQoKTGV0J3MgaW1wb3J0IHRoZSB3MTJkYXRhMS5jc3YgZmlsZS4gCgpgYGB7cn0KCiMgSW1wb3J0IG91ciBmaXJzdCBkYXRhIHNldAp3MTJkYXRhMSA8LSByZWFkX2NzdihmaWxlLmNob29zZSgpKQoKIyBWaWV3IHdoYXQgd2UganVzdCBpbXBvcnRlZC4gRGlkIHdlIGdldCB3aGF0IHdlIGV4cGVjdGVkPwpoZWFkKHcxMmRhdGExKQpgYGAKCkxldCdzIGNhbGN1bGF0ZSB0aGUgY29ycmVsYXRpb24KCmBgYHtyfQoKIyBDYWxjdWxhdGUgdGhlIGNvcnJlbGF0aW9uCmNvcih3MTJkYXRhMSRRdWFsLk1hcnJpYWdlLCB3MTJkYXRhMSRRdWFsLlBDKQoKYGBgCgpgYGB7cn0KCiMgTG9vayBhdCBhIHNjYXR0ZXJwbG90IG9mIHRoZSBkYXRhCnBsb3QodzEyZGF0YTEkUXVhbC5NYXJyaWFnZSwgdzEyZGF0YTEkUXVhbC5QQywgCiAgICAgeGxhYiA9ICJNYXJyaWFnZSBRdWFsaXR5IiwgeWxhYiA9ICJQYXJlbnQtQ2hpbGQgSW50ZXJhY3Rpb24gUXVhbGl0eSIsCiAgICAgbWFpbiA9ICJTY2F0dGVycGxvdCIpKwp0aGVtZV9taW5pbWFsKCkgCgpgYGAKTm93IGxldCdzIG9idGFpbiB0aGUgY29ycmVsYXRpb24gYW5kIGEgdGVzdCBvZiBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UKYGBge3J9CgojIEdldCB0aGUgY29ycmVsYXRpb24gYW5kIGEgdGVzdCBvZiBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UKY29yLnRlc3QodzEyZGF0YTEkUXVhbC5NYXJyaWFnZSwgdzEyZGF0YTEkUXVhbC5QQykKCgpgYGAKQW5kIGlmIHdlIHdlcmUgaW50ZXJlc3RlZCBpbiBnZXR0aW5nIGEgb25lLXRhaWwgdGVzdDogCgpgYGB7cn0KIyBBc2sgZm9yIG9uZS10YWlsZWQgdGVzdCByZXN1bHRzCmNvci50ZXN0KHcxMmRhdGExJFF1YWwuTWFycmlhZ2UsIHcxMmRhdGExJFF1YWwuUEMsIGFsdGVybmF0aXZlID0gImdyZWF0ZXIiKQoKYGBgCgojIyMjIEV4YW1wbGUgMgoKTGV0J3MgaW1wb3J0IHRoZSB3MTJkYXRhMi5jc3YgZmlsZS4KYGBge3J9CiMgSW1wb3J0IG91ciBmaXJzdCBkYXRhIHNldAp3MTJkYXRhMiA8LSByZWFkLmNzdihmaWxlLmNob29zZSgpKQpoZWFkKHcxMmRhdGEyKQoKYGBgCgoKV2hlbiB3ZSBydW4gdGhlIHQtdGVzdCB3aXRoIHRoZSB2YXIuZXF1YWwgPSBUUlVFLCB3ZSBhcmUgdGVsbGluZyB0aGUgdC50ZXN0KCkgZnVuY3Rpb24gdGhhdCBvdXIgZ3JvdXBzIGhhdmUgZXF1YWwgdmFyaWFuY2UsIHdlIHdpbGwgbGVhcm4gYSB0ZXN0IGZvciB0aGlzIGxhdGVyLiAKCmBgYHtyfQojIFJ1biB0aGUgdCB0ZXN0Cgp0LnRlc3QoTWVtb3J5VGVzdCB+IEdyb3VwLCBkYXRhID0gdzEyZGF0YTIsIHZhci5lcXVhbCA9IFRSVUUpCgpgYGAKCgpXZSBhcmUgdXNpbmcgTWVtb3J5VGVzdCB+IEdyb3VwOiwgYXMgTWVtb3J5VGVzdCBpcyB0aGUgc2NvcmUgd2UgYXJlIGNvbXBhcmluZyBhY3Jvc3Mgb3VyIGdyb3Vwcywgd2l0aCAxIHVzZWQgZm9yIHRoZSB0cmVhdG1lbnQgZ3JvdXAgYW5kIDIgZm9yIHRoZSBjb250cm9sIGdyb3VwIGluIHRoZSB2YXJpYWJsZSBHcm91cC4KCkFuZCB0aGUgdmFyLmVxdWFsID0gVFJVRSB0ZWxscyB0aGUgdC50ZXN0KCkgZnVuY3Rpb24gdGhhdCB0aGUgZ3JvdXBzIGhhdmUgZXF1YWwgdmFyaWFuY2UuCgpUaGUgcmVzdWx0cywgdCA9IOKAkzAuMTM3MSwgZGYgPSA1OCwgcCA9IC44OTE0LCB0ZWxsIHVzIHRoZSB0LCB0aGUgZGVncmVlcyBvZiBmcmVlZG9tIGZvciBvdXIgdGVzdCwgYW5kIHRoZSBleGFjdCBwLgoKCkxldCdzIGxvb2sgYXQgdGhlIGJveHBsb3QgYmV0d2VlbiBtZW1vcnkgdGVzdCBhbmQgZ3JvdXAsIGFuZCBzYXZlIHRoZSBwbG90IGluIGEgbmV3IG9iamVjdCBbbWVtb3J5XSwgc28gd2UgY2FuIGFjY2VzcyBzb21lIG9mIHRoZSBzdW1tYXJ5IHN0YXRzIHVzZWQgdG8gY29uc3RydWN0IGl0LiAKYGBge3J9Cm1lbW9yeSA8LSBib3hwbG90KE1lbW9yeVRlc3QgfiBHcm91cCwgZGF0YSA9IHcxMmRhdGEyLCBtYWluID0gIk1lbW9yeSBUZXN0IFNjb3JlcyIsCiAgICAgICAgeGxhYiA9ICJHcm91cHMiLCB5bGFiID0gIlNjb3JlcyIpCmBgYAoKTm93IHdlIGNhbiB1c2Ugb3VyIG5ldyBtZW1vcnkgb2JqZWN0IHRvIGxvb2sgYXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiBudW1iZXJzIGluIHRoZSB0d28gZ3JvdXBzIHVzaW5nIHRoZSBzdGF0cyBvcHRpb24gYWZ0ZXIgcnVubmluZyB0aGUgcGxvdC4gQmFzZWQgb24gd2hhdCB3ZSBjYW4gc2VlIGZyb20gdGhlIHBsb3QsIHdlIGNhbiBzZWUgdGhlIHZhcmlhbmNlIGlzIGRpZmZlcmVudCBiZXR3ZWVuIG91ciBncm91cHMsIGJ1dCB3ZSBkb24ndCByZWFsbHkga25vdyB3aGV0aGVyIGl0IGlzIFZFUlkgZGlmZmVyZW50LiBTbyB3ZSB3aWxsIHVzZSBhIHN0YXRpc3RpYyB0byBhbnN3ZXIgdGhpcyBxdWVzdGlvbiwgdGhlIExldmVuZeKAmXMgdGVzdC4gIAoKCmBgYHtyfQojIFNob3cgdGhlIG51bWJlcnMgdXNlZCB0byBjcmVhdGUgdGhlIGJveHBsb3QKIyBbMV0gTG93ZXIgd2hpc2tlcgojIFsyXSAyNXRoIHBlcmNlbnRpbGUgdmFsdWUKIyBbM10gNTB0aCBwZXJjZW50aWxlIHZhbHVlIC0gbWVkaWFuCiMgWzRdIDc1dGggcGVyY2VudGlsZSB2YWx1ZQojIFs1XSBVcHBvZXIgd2hpc2tlcgptZW1vcnkkc3RhdHMKCmBgYAoKV2Ugd2lsbCBub3cgdXNlIExldmVuZSdzIHRlc3QgZnJvbSB0aGUgcGFja2FnZSBbY2FyXSB0byB0ZXN0IHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCB0aGUgdmFyaWFuY2VzIGFyZSBlcXVhbCwgYW5kIHRoZSByZXNlYXJjaCBoeXBvdGhlc2lzIGlzIHRoYXQgdGhleSBhcmUgZGlmZmVyZW50LiBMZXQncyB1c2UgcCA8IC4wNSB0byBzaWduYWwgdGhhdCB3ZSBzaG91bGQgcmVqZWN0IG91ciBudWxsIGh5cG90aGVzaXMuCgoKYGBge3J9CiMgVGVzdCB0byBzZWUgaWYgdGhlIHZhcmlhbmNlcyBhcmUgZXF1YWwgaW4gdGhlIHR3byBncm91cHMKbGV2ZW5lVGVzdChNZW1vcnlUZXN0IH4gYXMuZmFjdG9yKEdyb3VwKSwgZGF0YSA9IHcxMmRhdGEyKQoKYGBgCgpMZXZlbmXigJlzIHRlc3QgaXMgRigxLCA1OCkgPSAzLjM0LCBwID0gLjA3LiBUaGUgcCBmb3IgTGV2ZW5l4oCZcyB0ZXN0IGV4Y2VlZHMgLjA1LCBzbyB3ZSBmYWlsIHRvIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIG9mIGVxdWFsIHZhcmlhbmNlLiBXZSBhcmUgZ29pbmcgdG8gb21pdCB2YXIuZXF1YWwgc3RhdGVtZW50LCBhbmQgd2hhdCB0aGlzIG1lYW5zIGlzIHRoYXQgUiB3aWxsIHVzZSBhIGRpZmZlcmVudCB0LXRlc3QgLXRoZSBXZWxjaCdzIHQgdGVzdC0uIFRoaXMgaXMgZ29pbmcgdG8gY2hhbmdlIHRoZSBudW1iZXIgb2YgZGVncmVlcyBvZiBmcmVlZG9tIGluIHRoZSBjYWxjdWxhdGlvbiB0byBtaW5pbWl6ZSBUeXBlIEkgb3IgVHlwZSBJSSBlcnJvci4gSW4gb3VyIHNwZWNpZmljIGV4YW1wbGUsIHRoZSBwLXZhbHVlIHdpdGggdGhlIFdlbGNoJ3MgdGVzdCBzdGlsbCBsZWFkcyB0byB0aGUgc2FtZSBjb25jbHVzaW9uLCBhbmQgd2UgZmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyBvZiBubyBkaWZmZXJlbmNlIGluIHRoZSBtZW1vcnkgdGVzdCByZXN1bHRzIGJldHdlZW4gdGhlIHRyZWF0bWVudCBhbmQgY29udHJvbCBncm91cHMuIAoKYGBge3J9CiMgUmUtcnVuIHQudGVzdCB3aXRoIHZhci5lcXVhbCBvbWl0dGVkCnQudGVzdChNZW1vcnlUZXN0IH4gR3JvdXAsIGRhdGEgPSB3MTJkYXRhMikKCmBgYAoKYGBge3J9CiMgTG9vayBhdCBoZWxwIGZvciB0LnRlc3QKP3QudGVzdApgYGAKCgoKIyMjIyBZb3VyIHR1cm4gCgoxKSAgSW1wb3J0IHRoZSBkYXRhIGluIHRoZSBmaWxlIG5hbWVkIHcxMmRhdGEzLmNzdjogW0hpbnQ6IGltcG9ydCB0aGUgZGF0YSB1d2luZyByZWFkX2Nzdi5dCgoKYGBge3J9CiMgSW1wb3J0IG91ciBmaXJzdCBkYXRhIHNldAp3MTJkYXRhMyA8LSByZWFkLmNzdihmaWxlLmNob29zZSgpKQpgYGAKCiBBKSBDb21wdXRlIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIG1vdGl2YXRpb24gYW5kIEdQQS4gCgpgYGB7cn0KY29yKHcxMmRhdGEzJE1vdGl2YXRpb24sIHcxMmRhdGEzJEdQQSkKCmBgYAoKQikgVGVzdCBmb3IgdGhlIHNpZ25pZmljYW5jZSBvZiB0aGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgYXQgdGhlIC4wNSBsZXZlbCB1c2luZyBhIHR3by10YWlsZWQgdGVzdC4KCgpgYGB7cn0KY29yLnRlc3QodzEyZGF0YTMkTW90aXZhdGlvbiwgdzEyZGF0YTMkR1BBKQpgYGAKQykgSW50ZXJwcmV0IHRoZSByZXN1bHRzOgoKWW91ciBhbnN3ZXIgaGVyZTogc2lnbmlmaWNhbnQgcG9zaXRpdmUgY29ycmVsYXRpb24gYnV0IG5vdCBhYnNvbHV0ZS4gCgoKVHJ1ZSBvciBmYWxzZT8gVGhlIG1vcmUgaGlnaGx5IHlvdSBhcmUgbW90aXZhdGVkLCB0aGUgbW9yZSB5b3Ugd2lsbCBzdHVkeS4gCllvdXIgYW5zd2VyIGhlcmU6IAoKVHJ1ZQoKMikgSW1wb3J0IHRoZSBkYXRhIGluIHRoZSBmaWxlIG5hbWVkIHcxMmRhdGE0LmNzdjogW0hpbnQ6IGltcG9ydCB0aGUgZGF0YSB1c2luZyByZWFkLmNzdi5dCgoKYGBge3J9CiMgSW1wb3J0IG91ciBmaXJzdCBkYXRhIHNldAp3MTJkYXRhNCA8LSByZWFkLmNzdihmaWxlLmNob29zZSgpKQoKYGBgCgpBKSBDb21wdXRlIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIGluY29tZSBhbmQgbGV2ZWwgb2YgZWR1Y2F0aW9uLiAKCgpgYGB7cn0KY29yKHcxMmRhdGE0JEluY29tZSwgdzEyZGF0YTQkTGV2ZWwub2YuRWR1Y2F0aW9uKQpgYGAKCkIpIFRlc3QgZm9yIHRoZSBzaWduaWZpY2FuY2Ugb2YgdGhlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IGF0IHRoZSAuMDUgbGV2ZWwgdXNpbmcgYSB0d28tdGFpbGVkIHRlc3QuCgoKYGBge3J9CmNvci50ZXN0KHcxMmRhdGE0JEluY29tZSwgdzEyZGF0YTQkTGV2ZWwub2YuRWR1Y2F0aW9uKQoKYGBgCgoKQykgSW50ZXJwcmV0IHRoZSByZXN1bHQuCgpZb3VyIGFuc3dlciBoZXJlOiBwb3NpdGl2ZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIGVkdWNhdGlvbiBhbmQgaW5jb21lCgoKCgozKSBJbXBvcnQgdGhlIGRhdGEgaW4gdGhlIGZpbGUgbmFtZWQgdzEyZGF0YTUuY3N2OiBbSGludDogaW1wb3J0IHRoZSBkYXRhIHVzaW5nIHJlYWQuY3N2Ll0KCmBgYHtyfQojIEltcG9ydCBvdXIgZmlyc3QgZGF0YSBzZXQKdzEyZGF0YTUgPC0gcmVhZC5jc3YoZmlsZS5jaG9vc2UoKSkKCmBgYAoKCkEpIENvbXB1dGUgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gaG91cnMgb2Ygc3R1ZHlpbmcgYW5kIGdyYWRlLiAKCgpgYGB7cn0KY29yKHcxMmRhdGE1JEhvdXJzLm9mLlN0dWR5LCB3MTJkYXRhNSRHcmFkZSkKYGBgCgoKQikgVGVzdCBmb3IgdGhlIHNpZ25pZmljYW5jZSBvZiB0aGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgYXQgdGhlIC4wNSBsZXZlbCB1c2luZyBhIHR3by10YWlsZWQgdGVzdCBiZXR3ZWVuIGhvdXJzIG9mIHN0dWR5aW5nIGFuZCBncmFkZS4gW2hpbnQ6IG1ha2Ugc3VyZSB5b3VyIHZhcmlhYmxlIG5hbWVzIGFyZSBjb3JyZWN0XQoKCmBgYHtyfQpjb3IudGVzdCh3MTJkYXRhNSRIb3Vycy5vZi5TdHVkeSwgdzEyZGF0YTUkR3JhZGUpCmBgYAoKCgpDKSBJbnRlcnByZXQgdGhpcyBjb3JyZWxhdGlvbgoKWW91ciBhbnN3ZXIgaGVyZTogcG9zaXRpdmUgY29ycmVsYXRpb24gYW1vbmcgZ3JhZGUgYW5kIHN0dWR5IGhvdXJzCgoKCkMpIEhvdyBtdWNoIHZhcmlhbmNlIGlzIHNoYXJlZCBiZXR3ZWVuIHRoZSB0d28gdmFyaWFibGVzPyBbaGludDogcmVtZW1iZXIgdGhlIGNvZWZmaWNpZW50IG9mIGRldGVybWluYXRpb24gaXMgcjIgLXlvdSBjYW4gY29tcHV0ZSBpdCBkaXJlY3RseSBpbiBSLCB0cnkgY29yXjIsIHdoZXJlIGNvciBpcyB0aGUgdmFsdWUgb2YgeW91ciBjb3JyZWxhdGlvbiBjb2VmZmljaWVudF0KCmBgYHtyfQowLjY4NTg5MzVeMgpgYGAKCgpZb3VyIGFuc3dlciBoZXJlOiAwLjQ3MDQ0OTkKVGhlIHNoYXJlZCB2YXJpYW5jZSBlcXVhbHM6IDQ3JQoKCgoK