Background

Problem Statement:

This document is the report from the final course project for the Inferential Statistics course, as part of the Duke University Statistics with R course in partnership with Coursera. The project consisted of exploring a real-world dataset (a subset of the General Social Survey) and create a report that included statistical inference on a question of interest (ended using three quesitons).

Summary:

  • Although small, there were significant differences between genders on whether sexual education should be taught in schools. This is especially important for single parents, or parents of the same sex, where one’s stance and actions cannot overcompensate for the other’s
  • We could not prove significant differences in the representation of each gender amongst the various social classes
  • There were significant differences in total family income based on the respondent’s family income when 16 years old. This is important as the earned income should be independent of someone’s family background. Further measures should be put into place for helping out those in unfavourable groups

Note: all of the research questions are focusing on the survey data in the year 2012 to account for year-on-year variances and display the most recent view that our data could provide.

Next steps/recommendations:

  • analyse changes between years (ie. 1980 vs 2012)
  • some variables (ie. social class) were subjective and registered based on the respondent’s opinion (more objective methods should be considered)
  • further expand on the analysis by looking at other related factors (ie. if there was a difference between total family income based on the respondent’s family income when 16 years old, can we find any further variables that can provide a more in-depth view as to why?)

Dataset

Since 1972, the General Social Survey (GSS) has been monitoring societal change and studying the growing complexity of American society. The GSS aims to gather data on contemporary American society in order to monitor and explain trends and constants in attitudes, behaviors, and attributes; to examine the structure and functioning of society in general as well as the role played by relevant subgroups; to compare the United States to other societies in order to place American society in comparative perspective and develop cross-national models of human society; and to make high-quality data easily accessible to scholars, students, policy makers, and others, with minimal cost and waiting.

Source: GSS project description https://www.norc.org/Research/Projects/Pages/general-social-survey.aspx


Part 1: Data

generabizability

According to the below link, each survey from 1972 to 2004 was an independently drawn sample of English-speaking persons 18 years of age or over, living in non-institutional arrangements within the United States through probability sampling (page 8). http://gss.norc.org/documents/codebook/GSS_Codebook_intro.pdf

However, there is a major difference between the individuals prior to 2006 and after, as explained below

  • 1972-2004, data includes English speaking individuals older than 18 years from non-institutional arrangements in the US
  • 2006 and beyond, data includes English and Spanish-speaking individuals

Furthermore, the selection process was ran through systematic selection and controlled selection. Therefore, it can be assumed that the data is representative of the populations mentioned above, based on the year in focus.

causality

Due to the observational nature of the study, no random assignment was used (test/control group), and hence causality cannot be inferred.


Part 2: Research questions

1 - Is there a difference in the opinion on sexual education in schools based on gender?

It would be helpful to know if this perception is dependent on gender, since sex is an important topic and can lead to serious family and health consequences, amongst others. This is especially important for single parents, or parents of the same sex, where one’s stance and actions cannot overcompensate for the other’s.

2 - Are there significant differences in the representation of each gender amongst the various social classes?

Ideally, we would have an equal distribution of each gender across classes. This is important as we shouldn’t have a significant difference based on someone’s gender.

3 - Does the total family income depend on the respondent’s family income when 16 years old?

This is important as the earned income should be independent of someone’s family background. If there are differences, further measures should be put into place for helping out those in unfavourable groups.

Note: all of the research questions are focusing on the survey data in the year 2012 to account for year-on-year variances and display the most recent view that our data could provide.


Part 3: Exploratory data analysis

1 - Is there a difference in the opinion on sexual education in schools based on gender?

We can see that there is a higher proportion of men that oppose sexual education in schools (11%) than women (8%). The absolute numbers can be seen in the table below.

question_1_SexEduc <- gss%>%
  filter(year == 2012)%>%
  filter(sexeduc != "Depends" & !is.na(sexeduc))%>%
  group_by(sex, sexeduc)%>%
  summarise(count = n())%>%
  mutate(prop = round(count/sum(count),2)*100)

ggplot(question_1_SexEduc, aes(sex, prop, fill = sexeduc))+
  geom_col(col = "black")+
  theme_few()+
  theme(legend.position = "top")+
  geom_text(aes(label = paste(prop, "%", sep = "")), nudge_y = -3)+
  labs(y="Proportion",
       x = NULL,
       fill = "Perception on Sexual Education in schools")

question_1_SexEduc%>%
  kbl(caption = "Summary statistics")%>%
  kable_paper("hover", full_width = F)
Summary statistics
sex sexeduc count prop
Male Favor 519 89
Male Oppose 64 11
Female Favor 638 92
Female Oppose 53 8

2 - Are there significant differences in the representation of each gender amongst the various social classes?

We cannot see any significant discrepencies between women and men as it regards their social class in either the graph or summary table.

#create summary table
question_2_gender <- gss%>%
  filter(year == "2012")%>%
  group_by(sex, class)%>%
  summarise(count = n())%>%
  mutate(prop = round(count/sum(count),2)*100)

#create plot table
question_2 <- gss%>%
  filter(year == "2012")%>%
  filter(!is.na(class))%>%
  droplevels()

ggplot(question_2) +
  geom_mosaic(aes(x=product(sex), fill = class), col = "black")+
  theme_few()+
  theme(legend.position = "none")+
  labs(x = "",
       y = "Social class")

question_2_gender%>%
  kbl(caption = "Summary data")%>%
  kable_paper("hover", full_width = F)
Summary data
sex class count prop
Male Lower Class 86 10
Male Working Class 385 43
Male Middle Class 372 42
Male Upper Class 34 4
Male NA 9 1
Female Lower Class 114 10
Female Working Class 468 43
Female Middle Class 467 43
Female Upper Class 31 3
Female NA 8 1

3 - Does the total family income depend on the respondent’s family income when 16 years old?

We can notice large differences both in median salary and variances across the different classes.

question_3_detail <- gss%>%
  filter(year == "2012")%>%
  filter(!is.na(incom16))%>%
  filter(!is.na(coninc))%>%
  select(incom16, coninc)%>%
  droplevels()

ggplot(question_3_detail, aes(incom16, coninc, fill = incom16))+
  geom_boxplot(col = "black", varwidth = TRUE)+
  labs(x = NULL,
       y = "Total family income (yearly)")+
  scale_y_continuous(labels=scales::dollar_format())+
  coord_flip()+
  theme_few()+
  theme(legend.position = "none")

question_3_year <- gss%>%
  filter(year == "2012")%>%
  group_by(incom16)%>%
  summarise(count = n(),
            median_income = round(median(coninc, na.rm = TRUE),1))%>%
  mutate(prop = round(count/sum(count)*100,2))

question_3_year%>%
  kbl(caption = "Summary statistics")%>%
  kable_paper("hover", full_width = F)
Summary statistics
incom16 count median_income prop
Far Below Average 181 24895 9.17
Below Average 523 34470 26.49
Average 875 34470 44.33
Above Average 304 51705 15.40
Far Above Average 47 34470 2.38
NA 44 21065 2.23

Part 4: Inference

1 - Is there a difference in the opinion on sexual education in schools based on gender?

Hypothesis

  • null hypothesis (Ho) - there is no difference in the proportions of men and women that oppose sex education
  • alternative hypothesis (Ha) - there is a significant difference in proportions of men and women that oppose sex education

Conditions

1) Independence
  • sampled observations must be independent of each other
    • random sample / assignment - true, due to the study design
    • sample size should be less than 10% of the respective population - true, since the sample size shown below is smaller than 10% of the population of the USA
question_1 <- gss%>%
  filter(year == "2012")%>%
  select(sex,sexeduc)%>%
  droplevels()

table(question_1$sex, question_1$sexeduc)%>%
  kbl(caption = "Contingency table")%>%
  kable_paper("hover", full_width = F)
Contingency table
Favor Oppose
Male 519 64
Female 638 53
2) Sample size
  • success-failure condition: at-least 10 succeses and 10 failures in our sample - true, as seen from the above table

Methods

In this analysis, we’re working with two categorical variables and thus, we will be using an inference based on two proportions. This means that we will be able to report both a p value and a confidence interval. Given that we met all of the conditions, we can use a theoretical based method rather than a simulation based inference.

p value

Interpretation:

We observed a p-value lower than 5%, so for this question, we reject the null hypothesis. Thus, there is sufficient evidence to conclude that a larger proportion of males, compared to females, oppose sex education. In the context of our data, a p value of 0.02 means that given a true null hypothesis, (ie. if there were no differences between the groups), there’s only a chance of 2% for this difference between males and females to have simply happened by chance.

Hypothesis testing is used to assess the plausibility of a hypothesis by using sample data. The test provides evidence concerning the plausibility of the hypothesis, given the data. Statistical analysts test a hypothesis by measuring and examining a random sample of the population being analyzed

sexeduc_2012 <- gss%>% 
  filter(year == 2012)%>%
  filter(sexeduc %in% c("Favor", "Oppose"))%>%
  select(sex,sexeduc)%>%
  droplevels()
  
inference(x = sex,
          y = sexeduc,
          data = sexeduc_2012, 
          statistic = "proportion", 
          type = "ht", 
          method = "theoretical", 
          alternative = "greater", 
          success = "Oppose", 
          null = 0)
## Response variable: categorical (2 levels, success: Oppose)
## Explanatory variable: categorical (2 levels) 
## n_Male = 583, p_hat_Male = 0.1098
## n_Female = 691, p_hat_Female = 0.0767
## H0: p_Male =  p_Female
## HA: p_Male > p_Female
## z = 2.0367
## p_value = 0.0208

confidence interval

Interpretation:

The 95% confidence interval for the difference between proportions of males and females that oppose sex education is between 0.0009 to 0.0653 (it excludes 0). Though the difference is really small, it still exists. Hence the results for both tests agree, and we can say that a greater proportion of men, than females, oppose sex education, and steps can be taken to better educate the men on the issue.

inference(x = sex,
          y = sexeduc,
          data = sexeduc_2012, 
          statistic = "proportion", 
          type = "ci", 
          method = "theoretical",
          #null = 0,
          #alternative = "greater", 
          success = "Oppose")
## Response variable: categorical (2 levels, success: Oppose)
## Explanatory variable: categorical (2 levels) 
## n_Male = 583, p_hat_Male = 0.1098
## n_Female = 691, p_hat_Female = 0.0767
## 95% CI (Male - Female): (9e-04 , 0.0653)

2 - Are there significant differences in the representation of each gender amongst the various social classes?

Hypothesis

  • null hypothesis (Ho) - the respondent’s gender and social class are independent variables
  • alternative hypothesis (Ha) - the respondent’s social class and gender are dependent variables

Conditions

1) Independence
  • sampled observations must be independent of each other
    • random sample / assignment - true, due to the study design
    • sample size should be less than 10% of the population - true, since the sample size shown below is smaller than 10% of the population of the USA
    • each case only contributes to one cell in the table - true
table(question_2$premarsx, question_2$sex)%>%
  kbl(caption = "Contingency table")%>%
  kable_paper("hover", full_width = F)
Contingency table
Male Female
Always Wrong 104 163
Almst Always Wrg 26 46
Sometimes Wrong 98 107
Not Wrong At All 342 359
2) Sample size
  • each particular scenario must have at least 5 expected cases - true, as seen in the above table

Methods

Since the dataset consists of two categorical variables (gender and social class), the adequate test to be used is the chi-square test of independence. This test is to be used when comparing 2 categorical variables where one of the variables has more than 2 levels(social class). This means that we will be using reporting a p value but not a confidence interval, since the latter isn’t defined by a chi-square test of independence.

The Chi-square test of independence works by comparing the distribution that you observe to the distribution that you expect if there is no relationship between the categorical variables. In the Chi-square context, the word “expected” is equivalent to what you’d expect if the null hypothesis is true.

p value

Interpretation:

The low X-squared statistic (1.85) with 3 degrees of freedom leads to a high p-value (0.60). Since the p-value is above alpha (0.05), we can conclude that there is sufficient evidence to fail to reject the null hypothesis (Ho).

In the context of the research question, this result provides evidence that there isn’t a significant difference between males and females, as of the data recorded in 2012. In other words, given a true null hypothesis (ie. no differences between the groups), there’s a 60% chance that any differences seen have happened by chance.

tidy(chisq.test(question_2$sex,question_2$class))%>%
  kbl(caption = "Chi-square test of independence")%>%
  kable_paper("hover", full_width = F)
Chi-square test of independence
statistic p.value parameter method
1.854238 0.6032039 3 Pearson’s Chi-squared test

No other methods were applicable and hence there’s nothing to compare the result to.

3 - Does the total family income depend on the respondent’s family income when 16 years old?

Hypothesis

  • null hypothesis (Ho) - there are no significant differences between the total family incomes based on their family income when 16 years old
  • alternative hypothesis (Ha) - at least one of the groups (as defined by family income when 16 years old) is significantly different in their total family income to the others

Conditions

1) Independence
  • within groups: sampled observations must be independent of each other
    • random sample / assignment - true, due to the study design
    • each group’s sample size should be less than 10% of the respective population - true, as seen in the below table
  • between groups: groups must be independent of each other - true, we can assume that the groups are independent to each other due to the study design
question_3_year%>%
  filter(!is.na(incom16))%>%
  kbl(caption = "Summary statistics")%>%
  kable_paper("hover", full_width = F)
Summary statistics
incom16 count median_income prop
Far Below Average 181 24895 9.17
Below Average 523 34470 26.49
Average 875 34470 44.33
Above Average 304 51705 15.40
Far Above Average 47 34470 2.38
2) Skewness
  • distribution of response variable within each group should be approximately normal (especially important when sample sizes are small) - we can check this using normal probability plots (QQ plots) or the Shapiro-Wilk normality test
    • the QQ plot does not show a normal distribution of our data
    • given the extremely low p-value, the Shapiro-Wilk normality test implies that the distribution of the data is significantly different from a normal distribution and that we cannot assume the normality

However, the sample size is relatively large for each class thus, unlike the independence of data, this assumption is not crucial.

ggplot(question_3_detail, aes(sample=coninc, col = incom16))+
  stat_qq()+
  stat_qq_line()+
  facet_wrap(.~incom16)+
  labs(title = "QQ plot")+
  theme_few()+
  theme(legend.position = "none")

question_3_detail %>% 
  select(incom16, coninc) %>% 
  group_by(group = as.character(incom16)) %>%
  do(tidy(shapiro.test(.$coninc)))%>%
  #put this into a aesthetically pleasing dataframe
  kbl(caption = "Shapiro-Wilk normality test")%>%
  kable_paper("hover", full_width = F)
Shapiro-Wilk normality test
group statistic p.value method
Above Average 0.8291873 0.0e+00 Shapiro-Wilk normality test
Average 0.7930347 0.0e+00 Shapiro-Wilk normality test
Below Average 0.7740452 0.0e+00 Shapiro-Wilk normality test
Far Above Average 0.7785680 1.3e-06 Shapiro-Wilk normality test
Far Below Average 0.6971207 0.0e+00 Shapiro-Wilk normality test
3) Variance
  • variability should be consistent across groups (homoscedastic groups). This is especially important when sample sizes differ between groups, as it is in our case and we can check this using:
    • side by side box plots (previously shown in the Exploratory Data Analysis)not met as the variability within the lower class group is much higher than in the other groups
    • Residual vs. Fitted plots - not true, given the shape of the data and extreme outliers across all groups
    • Levene’s test - from the output below we can see that the p-value is less than the significance level of 0.05. Therefore, we can not assume the homogeneity of variances in the different treatment groups.

When the homogeneity assumption is violated, as seen above, we could use the Welch one-way test, which does not require for the assumption of equal variances to be met.

res.aov <- aov(coninc ~ incom16, data = question_3_detail)

tidy(leveneTest(question_3_detail$coninc~question_3_detail$incom16))%>%
  kbl(caption = "Levene's test")%>%
  kable_paper("hover", full_width = F)
Levene’s test
statistic p.value df df.residual
12.3667 0 4 1723
ggplot(res.aov, aes(.fitted, .resid, col = incom16))+
  geom_point()+
  stat_smooth(method="loess", show.legend = FALSE)+
  geom_hline(yintercept=0, col="red", linetype="dashed")+
  labs(x = "Fitted values",
       y = "Residuals",
       title = "Residual vs Fitted Plot",
       col = "Class")+
  theme_few()+
  theme(legend.position = "top")

Methods

Given that we have one categorical variable with multiple levels (class) and one numerical variable (tv hours per day), the appropriate method for analysis is ANOVA. At the same time, we violated the homogeneity assumption and a one way test is more appropriate in this case. Furthermore, we will account for the increased risk of type I error with the Tukey test(due to multple comparisons), as well as understand which groups are significant (or not). Lastly, this means that we will be using reporting a p value but not a confidence interval, since this type of statistical analysis does not support the latter.

ANOVA is used to compare differences of means among more than 2 groups. It does this by looking at variation in the data and where that variation is found (hence its name). Specifically, ANOVA compares the amount of variation between groups with the amount of variation within groups. It can be used for both observational and experimental studies.

p value

Interpretation:

We can start by conducting a ANOVA test, despite the homogeneity assumption being violated, as a point of comparison with the one way test (below). We can see that the p value is almost 0, which means we can reject the null hypothesis and that there are significant differences between at least two of our groups.

tidy(res.aov)%>%
  kbl(caption = c("ANOVA table - without intercept"), )%>%
  kable_paper("hover", full_width = F)
ANOVA table - without intercept
term df sumsq meansq statistic p.value
incom16 4 1.248804e+11 31220101666 14.61664 0
Residuals 1723 3.680206e+12 2135929026 NA NA
# tidy(Anova(res.aov, type =3))%>%
#   kbl(caption = c("ANOVA table - with intercept"))%>%
#   kable_paper("hover", full_width = F)

variance_explained <- round(
  summary.lm(res.aov)$r.squared*100, 1
  )

In the context of the research question, the ANOVA output also shows us that only around 3.3% of the variance in total family income is explained by the respondent’s income when 16 years old. However, this only tells us that some groups are significantly different to others, not which ones. We will need to run a Tukey post hoc analysis to find out more detail.

A similar result is shown by our one way test below. No other methods were applicable and hence there’s nothing to compare other than the two described above.

res.aov2 <- oneway.test(coninc ~ incom16, data = question_3_detail)

tidy(res.aov2)%>%
  kbl(caption = c("One way test"), )%>%
  kable_paper("hover", full_width = F)
One way test
num.df den.df statistic p.value method
4 246.654 11.30872 0 One-way analysis of means (not assuming equal variances)

Once we account for the increased risk of type I error with the Tukey test, we can still see a significant difference between the following groups: - Above Average and Far Below Average - Above Average and Below Average - Above Average and Average

tidy(TukeyHSD(res.aov))%>%
  kbl(caption = c("Tukey post hoc analysis"))%>%
  kable_paper("hover", full_width = F)
Tukey post hoc analysis
term contrast null.value estimate conf.low conf.high adj.p.value
incom16 Below Average-Far Below Average 0 4398.047 -7110.550 15906.64 0.8350256
incom16 Average-Far Below Average 0 9457.687 -1509.506 20424.88 0.1284567
incom16 Above Average-Far Below Average 0 28072.921 15507.856 40637.99 0.0000000
incom16 Far Above Average-Far Below Average 0 20273.529 -1404.306 41951.36 0.0796375
incom16 Average-Below Average 0 5059.640 -2264.573 12383.85 0.3250145
incom16 Above Average-Below Average 0 23674.875 14122.616 33227.13 0.0000000
incom16 Far Above Average-Below Average 0 15875.482 -4206.682 35957.65 0.1961012
incom16 Above Average-Average 0 18615.235 9722.700 27507.77 0.0000001
incom16 Far Above Average-Average 0 10815.842 -8961.034 30592.72 0.5669211
incom16 Far Above Average-Above Average 0 -7799.392 -28505.101 12906.32 0.8421870
LS0tDQogICAgb3V0cHV0Og0KICAgICAgaHRtbF9kb2N1bWVudDoNCiAgICAgICAgdG9jOiB0cnVlDQogICAgICAgIHRvY19mbG9hdDogZmFsc2UNCiAgICAgICAgdG9jX2RlcHRoOiA0DQogICAgICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UNCiAgDQogICAgICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogIA0KICAgICAgICBmaWdfd2lkdGg6IDkNCiAgICAgICAgZmlnX2hlaWdodDogNA0KICAgICAgICBmaWdfYWxpZ246ICJjZW50ZXIiDQogICAgICAgIA0KICAgICAgICBoaWdobGlnaHQ6IHB5Z21lbnRzDQogICAgICAgIHRoZW1lOiBjZXJ1bGVhbg0KICAgICAgICANCiAgICAgICAga2VlcF9tZDogdHJ1ZQ0KICAgICAgICANCiAgICB0aXRsZTogIlN0YXRpc3RpY2FsIEluZmVyZW5jZSB3aXRoIHRoZSBHU1MgZGF0YSINCiAgICBzdWJ0aXRsZTogIkluLWRlcHRoIGh5cG90aGVzaXMgYW5kIGNvbmZpZGVuY2UgaW50ZXJ2YWwgdGVzdGluZyINCiAgICBhdXRob3I6ICJieSBQZXRlciBIb250YXJ1Ig0KLS0tDQoNCiMjIEJhY2tncm91bmQNCg0KIyMjIFByb2JsZW0gU3RhdGVtZW50Og0KDQpUaGlzIGRvY3VtZW50IGlzIHRoZSByZXBvcnQgZnJvbSB0aGUgZmluYWwgY291cnNlIHByb2plY3QgZm9yIHRoZSBJbmZlcmVudGlhbCBTdGF0aXN0aWNzIGNvdXJzZSwgYXMgcGFydCBvZiB0aGUgRHVrZSBVbml2ZXJzaXR5IFN0YXRpc3RpY3Mgd2l0aCBSIGNvdXJzZSBpbiBwYXJ0bmVyc2hpcCB3aXRoIENvdXJzZXJhLiBUaGUgcHJvamVjdCBjb25zaXN0ZWQgb2YgZXhwbG9yaW5nIGEgcmVhbC13b3JsZCBkYXRhc2V0IChhIHN1YnNldCBvZiB0aGUgR2VuZXJhbCBTb2NpYWwgU3VydmV5KSBhbmQgY3JlYXRlIGEgcmVwb3J0IHRoYXQgaW5jbHVkZWQgc3RhdGlzdGljYWwgaW5mZXJlbmNlIG9uIGEgcXVlc3Rpb24gb2YgaW50ZXJlc3QgKGVuZGVkIHVzaW5nIHRocmVlIHF1ZXNpdG9ucykuDQoNCiMjIyBTdW1tYXJ5Og0KDQoqIEFsdGhvdWdoIHNtYWxsLCB0aGVyZSB3ZXJlIHNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGJldHdlZW4gKipnZW5kZXJzKiogb24gd2hldGhlciAqKnNleHVhbCBlZHVjYXRpb24gc2hvdWxkIGJlIHRhdWdodCBpbiBzY2hvb2xzKiouIFRoaXMgaXMgZXNwZWNpYWxseSBpbXBvcnRhbnQgZm9yIHNpbmdsZSBwYXJlbnRzLCBvciBwYXJlbnRzIG9mIHRoZSBzYW1lIHNleCwgd2hlcmUgb25lJ3Mgc3RhbmNlIGFuZCBhY3Rpb25zIGNhbm5vdCBvdmVyY29tcGVuc2F0ZSBmb3IgdGhlIG90aGVyJ3MNCiogV2UgY291bGQgbm90IHByb3ZlIHNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGluIHRoZSByZXByZXNlbnRhdGlvbiBvZiBlYWNoICoqZ2VuZGVyKiogYW1vbmdzdCB0aGUgdmFyaW91cyAqKnNvY2lhbCBjbGFzc2VzKioNCiogVGhlcmUgd2VyZSBzaWduaWZpY2FudCBkaWZmZXJlbmNlcyBpbiAqKnRvdGFsIGZhbWlseSBpbmNvbWUqKiBiYXNlZCBvbiB0aGUgKipyZXNwb25kZW50J3MgZmFtaWx5IGluY29tZSB3aGVuIDE2IHllYXJzIG9sZCoqLiBUaGlzIGlzIGltcG9ydGFudCBhcyB0aGUgZWFybmVkIGluY29tZSBzaG91bGQgYmUgaW5kZXBlbmRlbnQgb2Ygc29tZW9uZSdzIGZhbWlseSBiYWNrZ3JvdW5kLiBGdXJ0aGVyIG1lYXN1cmVzIHNob3VsZCBiZSBwdXQgaW50byBwbGFjZSBmb3IgaGVscGluZyBvdXQgdGhvc2UgaW4gdW5mYXZvdXJhYmxlIGdyb3Vwcw0KDQoqTm90ZTogYWxsIG9mIHRoZSByZXNlYXJjaCBxdWVzdGlvbnMgYXJlIGZvY3VzaW5nIG9uIHRoZSBzdXJ2ZXkgZGF0YSBpbiB0aGUgeWVhciAyMDEyIHRvIGFjY291bnQgZm9yIHllYXItb24teWVhciB2YXJpYW5jZXMgYW5kIGRpc3BsYXkgdGhlIG1vc3QgcmVjZW50IHZpZXcgdGhhdCBvdXIgZGF0YSBjb3VsZCBwcm92aWRlLioNCg0KIyMjIE5leHQgc3RlcHMvcmVjb21tZW5kYXRpb25zOg0KDQoqIGFuYWx5c2UgY2hhbmdlcyBiZXR3ZWVuIHllYXJzIChpZS4gMTk4MCB2cyAyMDEyKQ0KKiBzb21lIHZhcmlhYmxlcyAoaWUuIHNvY2lhbCBjbGFzcykgd2VyZSBzdWJqZWN0aXZlIGFuZCByZWdpc3RlcmVkIGJhc2VkIG9uIHRoZSByZXNwb25kZW50J3Mgb3BpbmlvbiAobW9yZSBvYmplY3RpdmUgbWV0aG9kcyBzaG91bGQgYmUgY29uc2lkZXJlZCkNCiogZnVydGhlciBleHBhbmQgb24gdGhlIGFuYWx5c2lzIGJ5IGxvb2tpbmcgYXQgb3RoZXIgcmVsYXRlZCBmYWN0b3JzIChpZS4gaWYgdGhlcmUgd2FzIGEgZGlmZmVyZW5jZSBiZXR3ZWVuIHRvdGFsIGZhbWlseSBpbmNvbWUgYmFzZWQgb24gdGhlIHJlc3BvbmRlbnQncyBmYW1pbHkgaW5jb21lIHdoZW4gMTYgeWVhcnMgb2xkLCBjYW4gd2UgZmluZCBhbnkgZnVydGhlciB2YXJpYWJsZXMgdGhhdCBjYW4gcHJvdmlkZSBhIG1vcmUgaW4tZGVwdGggdmlldyBhcyB0byB3aHk/KQ0KDQojIyMgRGF0YXNldA0KDQpTaW5jZSAxOTcyLCB0aGUgR2VuZXJhbCBTb2NpYWwgU3VydmV5IChHU1MpIGhhcyBiZWVuIG1vbml0b3Jpbmcgc29jaWV0YWwgY2hhbmdlIGFuZCBzdHVkeWluZyB0aGUgZ3Jvd2luZyBjb21wbGV4aXR5IG9mIEFtZXJpY2FuIHNvY2lldHkuIFRoZSBHU1MgYWltcyB0byBnYXRoZXIgZGF0YSBvbiBjb250ZW1wb3JhcnkgQW1lcmljYW4gc29jaWV0eSBpbiBvcmRlciB0byBtb25pdG9yIGFuZCBleHBsYWluIHRyZW5kcyBhbmQgY29uc3RhbnRzIGluIGF0dGl0dWRlcywgYmVoYXZpb3JzLCBhbmQgYXR0cmlidXRlczsgdG8gZXhhbWluZSB0aGUgc3RydWN0dXJlIGFuZCBmdW5jdGlvbmluZyBvZiBzb2NpZXR5IGluIGdlbmVyYWwgYXMgd2VsbCBhcyB0aGUgcm9sZSBwbGF5ZWQgYnkgcmVsZXZhbnQgc3ViZ3JvdXBzOyB0byBjb21wYXJlIHRoZSBVbml0ZWQgU3RhdGVzIHRvIG90aGVyIHNvY2lldGllcyBpbiBvcmRlciB0byBwbGFjZSBBbWVyaWNhbiBzb2NpZXR5IGluIGNvbXBhcmF0aXZlIHBlcnNwZWN0aXZlIGFuZCBkZXZlbG9wIGNyb3NzLW5hdGlvbmFsIG1vZGVscyBvZiBodW1hbiBzb2NpZXR5OyBhbmQgdG8gbWFrZSBoaWdoLXF1YWxpdHkgZGF0YSBlYXNpbHkgYWNjZXNzaWJsZSB0byBzY2hvbGFycywgc3R1ZGVudHMsIHBvbGljeSBtYWtlcnMsIGFuZCBvdGhlcnMsIHdpdGggbWluaW1hbCBjb3N0IGFuZCB3YWl0aW5nLg0KDQpTb3VyY2U6IEdTUyBwcm9qZWN0IGRlc2NyaXB0aW9uDQpodHRwczovL3d3dy5ub3JjLm9yZy9SZXNlYXJjaC9Qcm9qZWN0cy9QYWdlcy9nZW5lcmFsLXNvY2lhbC1zdXJ2ZXkuYXNweA0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KICAgIGVjaG8gPSBUUlVFLCAjIHNob3cgYWxsIGNvZGUNCiAgICB0aWR5ID0gRkFMU0UsICMgY2xlYW5lciBjb2RlIHByaW50aW5nDQogICAgc2l6ZSA9ICJzbWFsbCIsICMgc21hbGxlciBjb2RlDQogICAgDQogICAgZmlnLnBhdGggPSAiZmlndXJlcy8iLCMgd2hlcmUgdGhlIGZpZ3VyZXMgd2lsbCBlbmQgdXANCiAgICBvdXQud2lkdGggPSAiMTAwJSIsDQoNCiAgICBtZXNzYWdlID0gRkFMU0UsDQogICAgd2FybmluZyA9IEZBTFNFDQogICAgKQ0KDQpsb2FkKCJnc3MuUmRhdGEiKQ0KYGBgDQoNCmBgYHtyIGxvYWQtcGFja2FnZXMsIG1lc3NhZ2U9RkFMU0UsIGluY2x1ZGU9RkFMU0V9DQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ21vc2FpYykNCmxpYnJhcnkoZ2d0aGVtZXMpDQpsaWJyYXJ5KGJyb29tKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KHN0YXRzcikNCmxpYnJhcnkoa2FibGVFeHRyYSkNCmxpYnJhcnkoZ2dwdWJyKQ0KbGlicmFyeShjYXIpDQpsaWJyYXJ5KHF1YW50cmVnKQ0KYGBgDQoNCiogKiAqDQoNCiMjIFBhcnQgMTogRGF0YQ0KDQojIyMgZ2VuZXJhYml6YWJpbGl0eQ0KDQpBY2NvcmRpbmcgdG8gdGhlIGJlbG93IGxpbmssIGVhY2ggc3VydmV5IGZyb20gMTk3MiB0byAyMDA0IHdhcyBhbiBpbmRlcGVuZGVudGx5IGRyYXduIHNhbXBsZSBvZiBFbmdsaXNoLXNwZWFraW5nIHBlcnNvbnMgMTggeWVhcnMgb2YgYWdlIG9yIG92ZXIsIGxpdmluZyBpbiBub24taW5zdGl0dXRpb25hbCBhcnJhbmdlbWVudHMgd2l0aGluIHRoZSBVbml0ZWQgU3RhdGVzIHRocm91Z2ggcHJvYmFiaWxpdHkgc2FtcGxpbmcgKHBhZ2UgOCkuDQpodHRwOi8vZ3NzLm5vcmMub3JnL2RvY3VtZW50cy9jb2RlYm9vay9HU1NfQ29kZWJvb2tfaW50cm8ucGRmDQoNCkhvd2V2ZXIsIHRoZXJlIGlzIGEgbWFqb3IgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBpbmRpdmlkdWFscyBwcmlvciB0byAyMDA2IGFuZCBhZnRlciwgYXMgZXhwbGFpbmVkIGJlbG93DQoNCiogMTk3Mi0yMDA0LCBkYXRhIGluY2x1ZGVzIEVuZ2xpc2ggc3BlYWtpbmcgaW5kaXZpZHVhbHMgb2xkZXIgdGhhbiAxOCB5ZWFycyBmcm9tIG5vbi1pbnN0aXR1dGlvbmFsIGFycmFuZ2VtZW50cyBpbiB0aGUgVVMNCiogMjAwNiBhbmQgYmV5b25kLCBkYXRhIGluY2x1ZGVzIEVuZ2xpc2ggKiphbmQqKiBTcGFuaXNoLXNwZWFraW5nIGluZGl2aWR1YWxzDQoNCkZ1cnRoZXJtb3JlLCB0aGUgc2VsZWN0aW9uIHByb2Nlc3Mgd2FzIHJhbiB0aHJvdWdoIHN5c3RlbWF0aWMgc2VsZWN0aW9uIGFuZCBjb250cm9sbGVkIHNlbGVjdGlvbi4gVGhlcmVmb3JlLCBpdCBjYW4gYmUgYXNzdW1lZCB0aGF0IHRoZSBkYXRhIGlzIHJlcHJlc2VudGF0aXZlIG9mIHRoZSBwb3B1bGF0aW9ucyBtZW50aW9uZWQgYWJvdmUsIGJhc2VkIG9uIHRoZSB5ZWFyIGluIGZvY3VzLg0KDQojIyMgY2F1c2FsaXR5IA0KDQpEdWUgdG8gdGhlIG9ic2VydmF0aW9uYWwgbmF0dXJlIG9mIHRoZSBzdHVkeSwgbm8gcmFuZG9tIGFzc2lnbm1lbnQgd2FzIHVzZWQgKHRlc3QvY29udHJvbCBncm91cCksIGFuZCBoZW5jZSBjYXVzYWxpdHkgY2Fubm90IGJlIGluZmVycmVkLg0KDQoqICogKg0KDQojIyBQYXJ0IDI6IFJlc2VhcmNoIHF1ZXN0aW9ucw0KDQojIyMjIyAxIC0gSXMgdGhlcmUgYSBkaWZmZXJlbmNlIGluIHRoZSAqKm9waW5pb24gb24gc2V4dWFsIGVkdWNhdGlvbiBpbiBzY2hvb2xzKiogYmFzZWQgb24gKipnZW5kZXIqKj8gDQoNCkl0IHdvdWxkIGJlIGhlbHBmdWwgdG8ga25vdyBpZiB0aGlzIHBlcmNlcHRpb24gaXMgZGVwZW5kZW50IG9uIGdlbmRlciwgc2luY2Ugc2V4IGlzIGFuIGltcG9ydGFudCB0b3BpYyBhbmQgY2FuIGxlYWQgdG8gc2VyaW91cyBmYW1pbHkgYW5kIGhlYWx0aCBjb25zZXF1ZW5jZXMsIGFtb25nc3Qgb3RoZXJzLiBUaGlzIGlzIGVzcGVjaWFsbHkgaW1wb3J0YW50IGZvciBzaW5nbGUgcGFyZW50cywgb3IgcGFyZW50cyBvZiB0aGUgc2FtZSBzZXgsIHdoZXJlIG9uZSdzIHN0YW5jZSBhbmQgYWN0aW9ucyBjYW5ub3Qgb3ZlcmNvbXBlbnNhdGUgZm9yIHRoZSBvdGhlcidzLg0KDQojIyMjIyAyIC0gQXJlIHRoZXJlIHNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGluIHRoZSByZXByZXNlbnRhdGlvbiBvZiBlYWNoICoqZ2VuZGVyKiogYW1vbmdzdCB0aGUgdmFyaW91cyAqKnNvY2lhbCBjbGFzc2VzKio/DQoNCklkZWFsbHksIHdlIHdvdWxkIGhhdmUgYW4gZXF1YWwgZGlzdHJpYnV0aW9uIG9mIGVhY2ggZ2VuZGVyIGFjcm9zcyBjbGFzc2VzLiBUaGlzIGlzIGltcG9ydGFudCBhcyB3ZSBzaG91bGRuJ3QgaGF2ZSBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgYmFzZWQgb24gc29tZW9uZSdzIGdlbmRlci4NCg0KIyMjIyMgMyAtIERvZXMgdGhlICoqdG90YWwgZmFtaWx5IGluY29tZSoqIGRlcGVuZCBvbiB0aGUgKipyZXNwb25kZW50J3MgZmFtaWx5IGluY29tZSB3aGVuIDE2IHllYXJzIG9sZCoqPw0KDQpUaGlzIGlzIGltcG9ydGFudCBhcyB0aGUgZWFybmVkIGluY29tZSBzaG91bGQgYmUgaW5kZXBlbmRlbnQgb2Ygc29tZW9uZSdzIGZhbWlseSBiYWNrZ3JvdW5kLiBJZiB0aGVyZSBhcmUgZGlmZmVyZW5jZXMsIGZ1cnRoZXIgbWVhc3VyZXMgc2hvdWxkIGJlIHB1dCBpbnRvIHBsYWNlIGZvciBoZWxwaW5nIG91dCB0aG9zZSBpbiB1bmZhdm91cmFibGUgZ3JvdXBzLg0KDQoqKk5vdGU6IGFsbCBvZiB0aGUgcmVzZWFyY2ggcXVlc3Rpb25zIGFyZSBmb2N1c2luZyBvbiB0aGUgc3VydmV5IGRhdGEgaW4gdGhlIHllYXIgMjAxMiB0byBhY2NvdW50IGZvciB5ZWFyLW9uLXllYXIgdmFyaWFuY2VzIGFuZCBkaXNwbGF5IHRoZSBtb3N0IHJlY2VudCB2aWV3IHRoYXQgb3VyIGRhdGEgY291bGQgcHJvdmlkZS4qKg0KDQoqICogKg0KDQojIyBQYXJ0IDM6IEV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMNCg0KIyMjIDEgLSBJcyB0aGVyZSBhIGRpZmZlcmVuY2UgaW4gdGhlICoqb3BpbmlvbiBvbiBzZXh1YWwgZWR1Y2F0aW9uIGluIHNjaG9vbHMqKiBiYXNlZCBvbiAqKmdlbmRlcioqPyANCg0KV2UgY2FuIHNlZSB0aGF0IHRoZXJlIGlzIGEgaGlnaGVyIHByb3BvcnRpb24gb2YgbWVuIHRoYXQgb3Bwb3NlIHNleHVhbCBlZHVjYXRpb24gaW4gc2Nob29scyAoMTElKSB0aGFuIHdvbWVuICg4JSkuIFRoZSBhYnNvbHV0ZSBudW1iZXJzIGNhbiBiZSBzZWVuIGluIHRoZSB0YWJsZSBiZWxvdy4NCg0KYGBge3J9DQpxdWVzdGlvbl8xX1NleEVkdWMgPC0gZ3NzJT4lDQogIGZpbHRlcih5ZWFyID09IDIwMTIpJT4lDQogIGZpbHRlcihzZXhlZHVjICE9ICJEZXBlbmRzIiAmICFpcy5uYShzZXhlZHVjKSklPiUNCiAgZ3JvdXBfYnkoc2V4LCBzZXhlZHVjKSU+JQ0KICBzdW1tYXJpc2UoY291bnQgPSBuKCkpJT4lDQogIG11dGF0ZShwcm9wID0gcm91bmQoY291bnQvc3VtKGNvdW50KSwyKSoxMDApDQoNCmdncGxvdChxdWVzdGlvbl8xX1NleEVkdWMsIGFlcyhzZXgsIHByb3AsIGZpbGwgPSBzZXhlZHVjKSkrDQogIGdlb21fY29sKGNvbCA9ICJibGFjayIpKw0KICB0aGVtZV9mZXcoKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUocHJvcCwgIiUiLCBzZXAgPSAiIikpLCBudWRnZV95ID0gLTMpKw0KICBsYWJzKHk9IlByb3BvcnRpb24iLA0KICAgICAgIHggPSBOVUxMLA0KICAgICAgIGZpbGwgPSAiUGVyY2VwdGlvbiBvbiBTZXh1YWwgRWR1Y2F0aW9uIGluIHNjaG9vbHMiKQ0KDQpxdWVzdGlvbl8xX1NleEVkdWMlPiUNCiAga2JsKGNhcHRpb24gPSAiU3VtbWFyeSBzdGF0aXN0aWNzIiklPiUNCiAga2FibGVfcGFwZXIoImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpDQpgYGANCg0KIyMjIDIgLSBBcmUgdGhlcmUgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgaW4gdGhlIHJlcHJlc2VudGF0aW9uIG9mIGVhY2ggKipnZW5kZXIqKiBhbW9uZ3N0IHRoZSB2YXJpb3VzICoqc29jaWFsIGNsYXNzZXMqKj8NCg0KV2UgY2Fubm90IHNlZSBhbnkgc2lnbmlmaWNhbnQgZGlzY3JlcGVuY2llcyBiZXR3ZWVuIHdvbWVuIGFuZCBtZW4gYXMgaXQgcmVnYXJkcyB0aGVpciBzb2NpYWwgY2xhc3MgaW4gZWl0aGVyIHRoZSBncmFwaCBvciBzdW1tYXJ5IHRhYmxlLg0KDQpgYGB7cn0NCiNjcmVhdGUgc3VtbWFyeSB0YWJsZQ0KcXVlc3Rpb25fMl9nZW5kZXIgPC0gZ3NzJT4lDQogIGZpbHRlcih5ZWFyID09ICIyMDEyIiklPiUNCiAgZ3JvdXBfYnkoc2V4LCBjbGFzcyklPiUNCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSU+JQ0KICBtdXRhdGUocHJvcCA9IHJvdW5kKGNvdW50L3N1bShjb3VudCksMikqMTAwKQ0KDQojY3JlYXRlIHBsb3QgdGFibGUNCnF1ZXN0aW9uXzIgPC0gZ3NzJT4lDQogIGZpbHRlcih5ZWFyID09ICIyMDEyIiklPiUNCiAgZmlsdGVyKCFpcy5uYShjbGFzcykpJT4lDQogIGRyb3BsZXZlbHMoKQ0KDQpnZ3Bsb3QocXVlc3Rpb25fMikgKw0KICBnZW9tX21vc2FpYyhhZXMoeD1wcm9kdWN0KHNleCksIGZpbGwgPSBjbGFzcyksIGNvbCA9ICJibGFjayIpKw0KICB0aGVtZV9mZXcoKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSsNCiAgbGFicyh4ID0gIiIsDQogICAgICAgeSA9ICJTb2NpYWwgY2xhc3MiKQ0KDQpxdWVzdGlvbl8yX2dlbmRlciU+JQ0KICBrYmwoY2FwdGlvbiA9ICJTdW1tYXJ5IGRhdGEiKSU+JQ0KICBrYWJsZV9wYXBlcigiaG92ZXIiLCBmdWxsX3dpZHRoID0gRikNCmBgYA0KDQojIyMgMyAtIERvZXMgdGhlICoqdG90YWwgZmFtaWx5IGluY29tZSoqIGRlcGVuZCBvbiB0aGUgKipyZXNwb25kZW50J3MgZmFtaWx5IGluY29tZSB3aGVuIDE2IHllYXJzIG9sZCoqPw0KDQpXZSBjYW4gbm90aWNlIGxhcmdlIGRpZmZlcmVuY2VzIGJvdGggaW4gbWVkaWFuIHNhbGFyeSBhbmQgdmFyaWFuY2VzIGFjcm9zcyB0aGUgZGlmZmVyZW50IGNsYXNzZXMuDQoNCmBgYHtyfQ0KcXVlc3Rpb25fM19kZXRhaWwgPC0gZ3NzJT4lDQogIGZpbHRlcih5ZWFyID09ICIyMDEyIiklPiUNCiAgZmlsdGVyKCFpcy5uYShpbmNvbTE2KSklPiUNCiAgZmlsdGVyKCFpcy5uYShjb25pbmMpKSU+JQ0KICBzZWxlY3QoaW5jb20xNiwgY29uaW5jKSU+JQ0KICBkcm9wbGV2ZWxzKCkNCg0KZ2dwbG90KHF1ZXN0aW9uXzNfZGV0YWlsLCBhZXMoaW5jb20xNiwgY29uaW5jLCBmaWxsID0gaW5jb20xNikpKw0KICBnZW9tX2JveHBsb3QoY29sID0gImJsYWNrIiwgdmFyd2lkdGggPSBUUlVFKSsNCiAgbGFicyh4ID0gTlVMTCwNCiAgICAgICB5ID0gIlRvdGFsIGZhbWlseSBpbmNvbWUgKHllYXJseSkiKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OmRvbGxhcl9mb3JtYXQoKSkrDQogIGNvb3JkX2ZsaXAoKSsNCiAgdGhlbWVfZmV3KCkrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCg0KcXVlc3Rpb25fM195ZWFyIDwtIGdzcyU+JQ0KICBmaWx0ZXIoeWVhciA9PSAiMjAxMiIpJT4lDQogIGdyb3VwX2J5KGluY29tMTYpJT4lDQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwNCiAgICAgICAgICAgIG1lZGlhbl9pbmNvbWUgPSByb3VuZChtZWRpYW4oY29uaW5jLCBuYS5ybSA9IFRSVUUpLDEpKSU+JQ0KICBtdXRhdGUocHJvcCA9IHJvdW5kKGNvdW50L3N1bShjb3VudCkqMTAwLDIpKQ0KDQpxdWVzdGlvbl8zX3llYXIlPiUNCiAga2JsKGNhcHRpb24gPSAiU3VtbWFyeSBzdGF0aXN0aWNzIiklPiUNCiAga2FibGVfcGFwZXIoImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpDQpgYGANCg0KKiAqICoNCg0KIyMgUGFydCA0OiBJbmZlcmVuY2UNCg0KIyMjIDEgLSBJcyB0aGVyZSBhIGRpZmZlcmVuY2UgaW4gdGhlICoqb3BpbmlvbiBvbiBzZXh1YWwgZWR1Y2F0aW9uIGluIHNjaG9vbHMqKiBiYXNlZCBvbiAqKmdlbmRlcioqPyANCg0KIyMjIyBIeXBvdGhlc2lzDQoNCi0gKipudWxsIGh5cG90aGVzaXMgKEhvKSoqIC0gdGhlcmUgaXMgbm8gZGlmZmVyZW5jZSBpbiB0aGUgcHJvcG9ydGlvbnMgb2YgbWVuIGFuZCB3b21lbiB0aGF0IG9wcG9zZSBzZXggZWR1Y2F0aW9uDQotICoqYWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyAoSGEpKiogLSB0aGVyZSBpcyBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgaW4gcHJvcG9ydGlvbnMgb2YgbWVuIGFuZCB3b21lbiB0aGF0IG9wcG9zZSBzZXggZWR1Y2F0aW9uDQoNCiMjIyMgQ29uZGl0aW9ucw0KDQojIyMjIyAxKSBJbmRlcGVuZGVuY2UNCg0KLSBzYW1wbGVkIG9ic2VydmF0aW9ucyBtdXN0IGJlIGluZGVwZW5kZW50IG9mIGVhY2ggb3RoZXINCiAgKiByYW5kb20gc2FtcGxlIC8gYXNzaWdubWVudCAtICp0cnVlLCBkdWUgdG8gdGhlIHN0dWR5IGRlc2lnbioNCiAgKiBzYW1wbGUgc2l6ZSBzaG91bGQgYmUgbGVzcyB0aGFuIDEwJSBvZiB0aGUgcmVzcGVjdGl2ZSBwb3B1bGF0aW9uIC0gKnRydWUsIHNpbmNlIHRoZSBzYW1wbGUgc2l6ZSBzaG93biBiZWxvdyBpcyBzbWFsbGVyIHRoYW4gMTAlIG9mIHRoZSBwb3B1bGF0aW9uIG9mIHRoZSBVU0EqDQogIA0KYGBge3J9DQpxdWVzdGlvbl8xIDwtIGdzcyU+JQ0KICBmaWx0ZXIoeWVhciA9PSAiMjAxMiIpJT4lDQogIHNlbGVjdChzZXgsc2V4ZWR1YyklPiUNCiAgZHJvcGxldmVscygpDQoNCnRhYmxlKHF1ZXN0aW9uXzEkc2V4LCBxdWVzdGlvbl8xJHNleGVkdWMpJT4lDQogIGtibChjYXB0aW9uID0gIkNvbnRpbmdlbmN5IHRhYmxlIiklPiUNCiAga2FibGVfcGFwZXIoImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpDQpgYGANCg0KIyMjIyMgMikgU2FtcGxlIHNpemUNCg0KLSBzdWNjZXNzLWZhaWx1cmUgY29uZGl0aW9uOiBhdC1sZWFzdCAxMCBzdWNjZXNlcyBhbmQgMTAgZmFpbHVyZXMgaW4gb3VyIHNhbXBsZSAtICp0cnVlLCBhcyBzZWVuIGZyb20gdGhlIGFib3ZlIHRhYmxlKg0KDQojIyMjIE1ldGhvZHMNCg0KSW4gdGhpcyBhbmFseXNpcywgd2UncmUgd29ya2luZyB3aXRoIHR3byBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgYW5kIHRodXMsIHdlIHdpbGwgYmUgdXNpbmcgYW4gaW5mZXJlbmNlIGJhc2VkIG9uIHR3byBwcm9wb3J0aW9ucy4gVGhpcyBtZWFucyB0aGF0IHdlIHdpbGwgYmUgYWJsZSB0byByZXBvcnQgYm90aCBhICoqcCB2YWx1ZSoqIGFuZCBhICoqY29uZmlkZW5jZSBpbnRlcnZhbCoqLiBHaXZlbiB0aGF0IHdlIG1ldCBhbGwgb2YgdGhlIGNvbmRpdGlvbnMsIHdlIGNhbiB1c2UgYSB0aGVvcmV0aWNhbCBiYXNlZCBtZXRob2QgcmF0aGVyIHRoYW4gYSBzaW11bGF0aW9uIGJhc2VkIGluZmVyZW5jZS4NCg0KIyMjIyMgcCB2YWx1ZQ0KDQoqKkludGVycHJldGF0aW9uKio6DQoNCldlIG9ic2VydmVkIGEgcC12YWx1ZSBsb3dlciB0aGFuIDUlLCBzbyBmb3IgdGhpcyBxdWVzdGlvbiwgd2UgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMuIFRodXMsIHRoZXJlIGlzIHN1ZmZpY2llbnQgZXZpZGVuY2UgdG8gY29uY2x1ZGUgdGhhdCBhIGxhcmdlciBwcm9wb3J0aW9uIG9mIG1hbGVzLCBjb21wYXJlZCB0byBmZW1hbGVzLCBvcHBvc2Ugc2V4IGVkdWNhdGlvbi4gSW4gdGhlIGNvbnRleHQgb2Ygb3VyIGRhdGEsIGEgcCB2YWx1ZSBvZiAwLjAyIG1lYW5zIHRoYXQgZ2l2ZW4gYSB0cnVlIG51bGwgaHlwb3RoZXNpcywgKGllLiBpZiB0aGVyZSB3ZXJlIG5vIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIGdyb3VwcyksIHRoZXJlJ3Mgb25seSBhIGNoYW5jZSBvZiAyJSBmb3IgdGhpcyBkaWZmZXJlbmNlIGJldHdlZW4gbWFsZXMgYW5kIGZlbWFsZXMgdG8gaGF2ZSBzaW1wbHkgaGFwcGVuZWQgYnkgY2hhbmNlLg0KDQpIeXBvdGhlc2lzIHRlc3RpbmcgaXMgdXNlZCB0byBhc3Nlc3MgdGhlIHBsYXVzaWJpbGl0eSBvZiBhIGh5cG90aGVzaXMgYnkgdXNpbmcgc2FtcGxlIGRhdGEuIFRoZSB0ZXN0IHByb3ZpZGVzIGV2aWRlbmNlIGNvbmNlcm5pbmcgdGhlIHBsYXVzaWJpbGl0eSBvZiB0aGUgaHlwb3RoZXNpcywgZ2l2ZW4gdGhlIGRhdGEuIFN0YXRpc3RpY2FsIGFuYWx5c3RzIHRlc3QgYSBoeXBvdGhlc2lzIGJ5IG1lYXN1cmluZyBhbmQgZXhhbWluaW5nIGEgcmFuZG9tIHNhbXBsZSBvZiB0aGUgcG9wdWxhdGlvbiBiZWluZyBhbmFseXplZA0KDQpgYGB7cn0NCnNleGVkdWNfMjAxMiA8LSBnc3MlPiUgDQogIGZpbHRlcih5ZWFyID09IDIwMTIpJT4lDQogIGZpbHRlcihzZXhlZHVjICVpbiUgYygiRmF2b3IiLCAiT3Bwb3NlIikpJT4lDQogIHNlbGVjdChzZXgsc2V4ZWR1YyklPiUNCiAgZHJvcGxldmVscygpDQogIA0KaW5mZXJlbmNlKHggPSBzZXgsDQogICAgICAgICAgeSA9IHNleGVkdWMsDQogICAgICAgICAgZGF0YSA9IHNleGVkdWNfMjAxMiwgDQogICAgICAgICAgc3RhdGlzdGljID0gInByb3BvcnRpb24iLCANCiAgICAgICAgICB0eXBlID0gImh0IiwgDQogICAgICAgICAgbWV0aG9kID0gInRoZW9yZXRpY2FsIiwgDQogICAgICAgICAgYWx0ZXJuYXRpdmUgPSAiZ3JlYXRlciIsIA0KICAgICAgICAgIHN1Y2Nlc3MgPSAiT3Bwb3NlIiwgDQogICAgICAgICAgbnVsbCA9IDApDQpgYGANCg0KIyMjIyMgY29uZmlkZW5jZSBpbnRlcnZhbA0KDQoqKkludGVycHJldGF0aW9uKio6DQoNClRoZSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3IgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBwcm9wb3J0aW9ucyBvZiBtYWxlcyBhbmQgZmVtYWxlcyB0aGF0IG9wcG9zZSBzZXggZWR1Y2F0aW9uIGlzIGJldHdlZW4gMC4wMDA5IHRvIDAuMDY1MyAoaXQgZXhjbHVkZXMgMCkuIFRob3VnaCB0aGUgZGlmZmVyZW5jZSBpcyByZWFsbHkgc21hbGwsIGl0IHN0aWxsIGV4aXN0cy4gSGVuY2UgdGhlIHJlc3VsdHMgZm9yIGJvdGggdGVzdHMgYWdyZWUsIGFuZCB3ZSBjYW4gc2F5IHRoYXQgYSBncmVhdGVyIHByb3BvcnRpb24gb2YgbWVuLCB0aGFuIGZlbWFsZXMsIG9wcG9zZSBzZXggZWR1Y2F0aW9uLCBhbmQgc3RlcHMgY2FuIGJlIHRha2VuIHRvIGJldHRlciBlZHVjYXRlIHRoZSBtZW4gb24gdGhlIGlzc3VlLg0KDQpgYGB7cn0NCmluZmVyZW5jZSh4ID0gc2V4LA0KICAgICAgICAgIHkgPSBzZXhlZHVjLA0KICAgICAgICAgIGRhdGEgPSBzZXhlZHVjXzIwMTIsIA0KICAgICAgICAgIHN0YXRpc3RpYyA9ICJwcm9wb3J0aW9uIiwgDQogICAgICAgICAgdHlwZSA9ICJjaSIsIA0KICAgICAgICAgIG1ldGhvZCA9ICJ0aGVvcmV0aWNhbCIsDQogICAgICAgICAgI251bGwgPSAwLA0KICAgICAgICAgICNhbHRlcm5hdGl2ZSA9ICJncmVhdGVyIiwgDQogICAgICAgICAgc3VjY2VzcyA9ICJPcHBvc2UiKQ0KYGBgDQoNCiMjIyAyIC0gQXJlIHRoZXJlIHNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGluIHRoZSByZXByZXNlbnRhdGlvbiBvZiBlYWNoICoqZ2VuZGVyKiogYW1vbmdzdCB0aGUgdmFyaW91cyAqKnNvY2lhbCBjbGFzc2VzKio/DQoNCiMjIyMgSHlwb3RoZXNpcw0KDQotICoqbnVsbCBoeXBvdGhlc2lzIChIbykqKiAtIHRoZSByZXNwb25kZW50J3MgZ2VuZGVyIGFuZCBzb2NpYWwgY2xhc3MgYXJlIGluZGVwZW5kZW50IHZhcmlhYmxlcw0KLSAqKmFsdGVybmF0aXZlIGh5cG90aGVzaXMgKEhhKSoqIC0gdGhlIHJlc3BvbmRlbnQncyBzb2NpYWwgY2xhc3MgYW5kIGdlbmRlciBhcmUgZGVwZW5kZW50IHZhcmlhYmxlcw0KDQojIyMjIENvbmRpdGlvbnMNCg0KIyMjIyMgMSkgSW5kZXBlbmRlbmNlDQoNCi0gc2FtcGxlZCBvYnNlcnZhdGlvbnMgbXVzdCBiZSBpbmRlcGVuZGVudCBvZiBlYWNoIG90aGVyDQogICogcmFuZG9tIHNhbXBsZSAvIGFzc2lnbm1lbnQgLSAqdHJ1ZSwgZHVlIHRvIHRoZSBzdHVkeSBkZXNpZ24qDQogICogc2FtcGxlIHNpemUgc2hvdWxkIGJlIGxlc3MgdGhhbiAxMCUgb2YgdGhlIHBvcHVsYXRpb24gLSAqdHJ1ZSwgc2luY2UgdGhlIHNhbXBsZSBzaXplIHNob3duIGJlbG93IGlzIHNtYWxsZXIgdGhhbiAxMCUgb2YgdGhlIHBvcHVsYXRpb24gb2YgdGhlIFVTQSoNCiAgKiBlYWNoIGNhc2Ugb25seSBjb250cmlidXRlcyB0byBvbmUgY2VsbCBpbiB0aGUgdGFibGUgLSAqdHJ1ZSoNCg0KYGBge3J9DQp0YWJsZShxdWVzdGlvbl8yJHByZW1hcnN4LCBxdWVzdGlvbl8yJHNleCklPiUNCiAga2JsKGNhcHRpb24gPSAiQ29udGluZ2VuY3kgdGFibGUiKSU+JQ0KICBrYWJsZV9wYXBlcigiaG92ZXIiLCBmdWxsX3dpZHRoID0gRikNCmBgYA0KDQojIyMjIyAyKSBTYW1wbGUgc2l6ZQ0KDQotIGVhY2ggcGFydGljdWxhciBzY2VuYXJpbyBtdXN0IGhhdmUgYXQgbGVhc3QgNSBleHBlY3RlZCBjYXNlcyAtICp0cnVlLCBhcyBzZWVuIGluIHRoZSBhYm92ZSB0YWJsZSoNCg0KIyMjIyBNZXRob2RzDQoNClNpbmNlIHRoZSBkYXRhc2V0IGNvbnNpc3RzIG9mIHR3byBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgKGdlbmRlciBhbmQgc29jaWFsIGNsYXNzKSwgdGhlIGFkZXF1YXRlIHRlc3QgdG8gYmUgdXNlZCBpcyB0aGUgY2hpLXNxdWFyZSB0ZXN0IG9mIGluZGVwZW5kZW5jZS4gVGhpcyB0ZXN0IGlzIHRvIGJlIHVzZWQgd2hlbiBjb21wYXJpbmcgMiBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgd2hlcmUgb25lIG9mIHRoZSB2YXJpYWJsZXMgaGFzIG1vcmUgdGhhbiAyIGxldmVscyhzb2NpYWwgY2xhc3MpLiBUaGlzIG1lYW5zIHRoYXQgd2Ugd2lsbCBiZSB1c2luZyByZXBvcnRpbmcgYSAqKnAgdmFsdWUqKiBidXQgbm90IGEgKipjb25maWRlbmNlIGludGVydmFsKiosIHNpbmNlIHRoZSBsYXR0ZXIgaXNuJ3QgZGVmaW5lZCBieSBhIGNoaS1zcXVhcmUgdGVzdCBvZiBpbmRlcGVuZGVuY2UuDQoNClRoZSBDaGktc3F1YXJlIHRlc3Qgb2YgaW5kZXBlbmRlbmNlIHdvcmtzIGJ5IGNvbXBhcmluZyB0aGUgZGlzdHJpYnV0aW9uIHRoYXQgeW91IG9ic2VydmUgdG8gdGhlIGRpc3RyaWJ1dGlvbiB0aGF0IHlvdSBleHBlY3QgaWYgdGhlcmUgaXMgbm8gcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIGNhdGVnb3JpY2FsIHZhcmlhYmxlcy4gSW4gdGhlIENoaS1zcXVhcmUgY29udGV4dCwgdGhlIHdvcmQg4oCcZXhwZWN0ZWTigJ0gaXMgZXF1aXZhbGVudCB0byB3aGF0IHlvdSdkIGV4cGVjdCBpZiB0aGUgbnVsbCBoeXBvdGhlc2lzIGlzIHRydWUuDQoNCiMjIyMjIHAgdmFsdWUNCg0KKipJbnRlcnByZXRhdGlvbioqOg0KDQpUaGUgbG93IFgtc3F1YXJlZCBzdGF0aXN0aWMgKDEuODUpIHdpdGggMyBkZWdyZWVzIG9mIGZyZWVkb20gbGVhZHMgdG8gYSBoaWdoIHAtdmFsdWUgKDAuNjApLiBTaW5jZSB0aGUgcC12YWx1ZSBpcyBhYm92ZSBhbHBoYSAoMC4wNSksIHdlIGNhbiBjb25jbHVkZSB0aGF0IHRoZXJlIGlzIHN1ZmZpY2llbnQgZXZpZGVuY2UgdG8gZmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyAoSG8pLg0KDQpJbiB0aGUgY29udGV4dCBvZiB0aGUgcmVzZWFyY2ggcXVlc3Rpb24sIHRoaXMgcmVzdWx0IHByb3ZpZGVzIGV2aWRlbmNlIHRoYXQgdGhlcmUgaXNuJ3QgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGJldHdlZW4gbWFsZXMgYW5kIGZlbWFsZXMsIGFzIG9mIHRoZSBkYXRhIHJlY29yZGVkIGluIDIwMTIuIEluIG90aGVyIHdvcmRzLCBnaXZlbiBhIHRydWUgbnVsbCBoeXBvdGhlc2lzIChpZS4gbm8gZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgZ3JvdXBzKSwgdGhlcmUncyBhIDYwJSBjaGFuY2UgdGhhdCBhbnkgZGlmZmVyZW5jZXMgc2VlbiBoYXZlIGhhcHBlbmVkIGJ5IGNoYW5jZS4NCg0KYGBge3J9DQp0aWR5KGNoaXNxLnRlc3QocXVlc3Rpb25fMiRzZXgscXVlc3Rpb25fMiRjbGFzcykpJT4lDQogIGtibChjYXB0aW9uID0gIkNoaS1zcXVhcmUgdGVzdCBvZiBpbmRlcGVuZGVuY2UiKSU+JQ0KICBrYWJsZV9wYXBlcigiaG92ZXIiLCBmdWxsX3dpZHRoID0gRikNCmBgYA0KDQpObyBvdGhlciBtZXRob2RzIHdlcmUgYXBwbGljYWJsZSBhbmQgaGVuY2UgdGhlcmUncyBub3RoaW5nIHRvIGNvbXBhcmUgdGhlIHJlc3VsdCB0by4NCg0KIyMjIDMgLSBEb2VzIHRoZSAqKnRvdGFsIGZhbWlseSBpbmNvbWUqKiBkZXBlbmQgb24gdGhlICoqcmVzcG9uZGVudCdzIGZhbWlseSBpbmNvbWUgd2hlbiAxNiB5ZWFycyBvbGQqKj8NCg0KIyMjIyBIeXBvdGhlc2lzDQoNCi0gKipudWxsIGh5cG90aGVzaXMgKEhvKSoqIC0gdGhlcmUgYXJlIG5vIHNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIHRvdGFsIGZhbWlseSBpbmNvbWVzIGJhc2VkIG9uIHRoZWlyIGZhbWlseSBpbmNvbWUgd2hlbiAxNiB5ZWFycyBvbGQNCi0gKiphbHRlcm5hdGl2ZSBoeXBvdGhlc2lzIChIYSkqKiAtIGF0IGxlYXN0IG9uZSBvZiB0aGUgZ3JvdXBzIChhcyBkZWZpbmVkIGJ5IGZhbWlseSBpbmNvbWUgd2hlbiAxNiB5ZWFycyBvbGQpIGlzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGluIHRoZWlyIHRvdGFsIGZhbWlseSBpbmNvbWUgdG8gdGhlIG90aGVycw0KDQojIyMjIENvbmRpdGlvbnMNCg0KIyMjIyMgMSkgSW5kZXBlbmRlbmNlDQoNCi0gKip3aXRoaW4gZ3JvdXBzKio6IHNhbXBsZWQgb2JzZXJ2YXRpb25zIG11c3QgYmUgaW5kZXBlbmRlbnQgb2YgZWFjaCBvdGhlcg0KICAqIHJhbmRvbSBzYW1wbGUgLyBhc3NpZ25tZW50IC0gKnRydWUsIGR1ZSB0byB0aGUgc3R1ZHkgZGVzaWduKg0KICAqIGVhY2ggZ3JvdXAncyBzYW1wbGUgc2l6ZSBzaG91bGQgYmUgbGVzcyB0aGFuIDEwJSBvZiB0aGUgcmVzcGVjdGl2ZSBwb3B1bGF0aW9uIC0gKnRydWUsIGFzIHNlZW4gaW4gdGhlIGJlbG93IHRhYmxlKg0KLSAqKmJldHdlZW4gZ3JvdXBzKio6IGdyb3VwcyBtdXN0IGJlIGluZGVwZW5kZW50IG9mIGVhY2ggb3RoZXIgLSAqdHJ1ZSwgd2UgY2FuIGFzc3VtZSB0aGF0IHRoZSBncm91cHMgYXJlIGluZGVwZW5kZW50IHRvIGVhY2ggb3RoZXIgZHVlIHRvIHRoZSBzdHVkeSBkZXNpZ24qDQoNCmBgYHtyfQ0KcXVlc3Rpb25fM195ZWFyJT4lDQogIGZpbHRlcighaXMubmEoaW5jb20xNikpJT4lDQogIGtibChjYXB0aW9uID0gIlN1bW1hcnkgc3RhdGlzdGljcyIpJT4lDQogIGthYmxlX3BhcGVyKCJob3ZlciIsIGZ1bGxfd2lkdGggPSBGKQ0KYGBgDQoNCiMjIyMjIDIpIFNrZXduZXNzDQoNCi0gZGlzdHJpYnV0aW9uIG9mIHJlc3BvbnNlIHZhcmlhYmxlIHdpdGhpbiBlYWNoIGdyb3VwIHNob3VsZCBiZSBhcHByb3hpbWF0ZWx5IG5vcm1hbCAoZXNwZWNpYWxseSBpbXBvcnRhbnQgd2hlbiBzYW1wbGUgc2l6ZXMgYXJlIHNtYWxsKSAtICB3ZSBjYW4gY2hlY2sgdGhpcyB1c2luZyAqKm5vcm1hbCBwcm9iYWJpbGl0eSBwbG90cyAoUVEgcGxvdHMpKiogb3IgdGhlICoqU2hhcGlyby1XaWxrIG5vcm1hbGl0eSB0ZXN0KioNCiAgKiB0aGUgKipRUSBwbG90KiogZG9lcyBub3Qgc2hvdyBhIG5vcm1hbCBkaXN0cmlidXRpb24gb2Ygb3VyIGRhdGENCiAgKiBnaXZlbiB0aGUgZXh0cmVtZWx5IGxvdyBwLXZhbHVlLCB0aGUgKipTaGFwaXJvLVdpbGsgbm9ybWFsaXR5IHRlc3QqKiBpbXBsaWVzIHRoYXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgZGF0YSBpcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiBhbmQgdGhhdCB3ZSBjYW5ub3QgYXNzdW1lIHRoZSBub3JtYWxpdHkNCg0KSG93ZXZlciwgdGhlIHNhbXBsZSBzaXplIGlzIHJlbGF0aXZlbHkgbGFyZ2UgZm9yIGVhY2ggY2xhc3MgdGh1cywgdW5saWtlIHRoZSBpbmRlcGVuZGVuY2Ugb2YgZGF0YSwgdGhpcyBhc3N1bXB0aW9uIGlzIG5vdCBjcnVjaWFsLg0KDQpgYGB7cn0NCmdncGxvdChxdWVzdGlvbl8zX2RldGFpbCwgYWVzKHNhbXBsZT1jb25pbmMsIGNvbCA9IGluY29tMTYpKSsNCiAgc3RhdF9xcSgpKw0KICBzdGF0X3FxX2xpbmUoKSsNCiAgZmFjZXRfd3JhcCgufmluY29tMTYpKw0KICBsYWJzKHRpdGxlID0gIlFRIHBsb3QiKSsNCiAgdGhlbWVfZmV3KCkrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCg0KcXVlc3Rpb25fM19kZXRhaWwgJT4lIA0KICBzZWxlY3QoaW5jb20xNiwgY29uaW5jKSAlPiUgDQogIGdyb3VwX2J5KGdyb3VwID0gYXMuY2hhcmFjdGVyKGluY29tMTYpKSAlPiUNCiAgZG8odGlkeShzaGFwaXJvLnRlc3QoLiRjb25pbmMpKSklPiUNCiAgI3B1dCB0aGlzIGludG8gYSBhZXN0aGV0aWNhbGx5IHBsZWFzaW5nIGRhdGFmcmFtZQ0KICBrYmwoY2FwdGlvbiA9ICJTaGFwaXJvLVdpbGsgbm9ybWFsaXR5IHRlc3QiKSU+JQ0KICBrYWJsZV9wYXBlcigiaG92ZXIiLCBmdWxsX3dpZHRoID0gRikNCmBgYA0KDQojIyMjIyAzKSBWYXJpYW5jZQ0KDQotIHZhcmlhYmlsaXR5IHNob3VsZCBiZSBjb25zaXN0ZW50IGFjcm9zcyBncm91cHMgKGhvbW9zY2VkYXN0aWMgZ3JvdXBzKS4gVGhpcyBpcyBlc3BlY2lhbGx5IGltcG9ydGFudCB3aGVuIHNhbXBsZSBzaXplcyBkaWZmZXIgYmV0d2VlbiBncm91cHMsIGFzIGl0IGlzIGluIG91ciBjYXNlIGFuZCB3ZSBjYW4gY2hlY2sgdGhpcyB1c2luZzoNCiAgKiAqKnNpZGUgYnkgc2lkZSBib3ggcGxvdHMqKiAocHJldmlvdXNseSBzaG93biBpbiB0aGUgRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcykqbm90IG1ldCBhcyB0aGUgdmFyaWFiaWxpdHkgd2l0aGluIHRoZSBsb3dlciBjbGFzcyBncm91cCBpcyBtdWNoIGhpZ2hlciB0aGFuIGluIHRoZSBvdGhlciBncm91cHMqDQogICogKipSZXNpZHVhbCB2cy4gRml0dGVkIHBsb3RzKiogLSAqbm90IHRydWUsIGdpdmVuIHRoZSBzaGFwZSBvZiB0aGUgZGF0YSBhbmQgZXh0cmVtZSBvdXRsaWVycyBhY3Jvc3MgYWxsIGdyb3VwcyoNCiAgKiAqKkxldmVuZSdzIHRlc3QqKiAtICpmcm9tIHRoZSBvdXRwdXQgYmVsb3cgd2UgY2FuIHNlZSB0aGF0IHRoZSBwLXZhbHVlIGlzIGxlc3MgdGhhbiB0aGUgc2lnbmlmaWNhbmNlIGxldmVsIG9mIDAuMDUuIFRoZXJlZm9yZSwgd2UgY2FuIG5vdCBhc3N1bWUgdGhlIGhvbW9nZW5laXR5IG9mIHZhcmlhbmNlcyBpbiB0aGUgZGlmZmVyZW50IHRyZWF0bWVudCBncm91cHMuKg0KDQpXaGVuIHRoZSBob21vZ2VuZWl0eSBhc3N1bXB0aW9uIGlzIHZpb2xhdGVkLCBhcyBzZWVuIGFib3ZlLCB3ZSBjb3VsZCB1c2UgdGhlIFdlbGNoIG9uZS13YXkgdGVzdCwgd2hpY2ggZG9lcyBub3QgcmVxdWlyZSBmb3IgdGhlIGFzc3VtcHRpb24gb2YgZXF1YWwgdmFyaWFuY2VzIHRvIGJlIG1ldC4NCg0KYGBge3J9DQpyZXMuYW92IDwtIGFvdihjb25pbmMgfiBpbmNvbTE2LCBkYXRhID0gcXVlc3Rpb25fM19kZXRhaWwpDQoNCnRpZHkobGV2ZW5lVGVzdChxdWVzdGlvbl8zX2RldGFpbCRjb25pbmN+cXVlc3Rpb25fM19kZXRhaWwkaW5jb20xNikpJT4lDQogIGtibChjYXB0aW9uID0gIkxldmVuZSdzIHRlc3QiKSU+JQ0KICBrYWJsZV9wYXBlcigiaG92ZXIiLCBmdWxsX3dpZHRoID0gRikNCg0KZ2dwbG90KHJlcy5hb3YsIGFlcyguZml0dGVkLCAucmVzaWQsIGNvbCA9IGluY29tMTYpKSsNCiAgZ2VvbV9wb2ludCgpKw0KICBzdGF0X3Ntb290aChtZXRob2Q9ImxvZXNzIiwgc2hvdy5sZWdlbmQgPSBGQUxTRSkrDQogIGdlb21faGxpbmUoeWludGVyY2VwdD0wLCBjb2w9InJlZCIsIGxpbmV0eXBlPSJkYXNoZWQiKSsNCiAgbGFicyh4ID0gIkZpdHRlZCB2YWx1ZXMiLA0KICAgICAgIHkgPSAiUmVzaWR1YWxzIiwNCiAgICAgICB0aXRsZSA9ICJSZXNpZHVhbCB2cyBGaXR0ZWQgUGxvdCIsDQogICAgICAgY29sID0gIkNsYXNzIikrDQogIHRoZW1lX2ZldygpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikNCmBgYA0KDQojIyMjIE1ldGhvZHMNCg0KR2l2ZW4gdGhhdCB3ZSBoYXZlIG9uZSBjYXRlZ29yaWNhbCB2YXJpYWJsZSB3aXRoIG11bHRpcGxlIGxldmVscyAoY2xhc3MpIGFuZCBvbmUgbnVtZXJpY2FsIHZhcmlhYmxlICh0diBob3VycyBwZXIgZGF5KSwgdGhlIGFwcHJvcHJpYXRlIG1ldGhvZCBmb3IgYW5hbHlzaXMgaXMgQU5PVkEuIEF0IHRoZSBzYW1lIHRpbWUsIHdlIHZpb2xhdGVkIHRoZSBob21vZ2VuZWl0eSBhc3N1bXB0aW9uIGFuZCBhIG9uZSB3YXkgdGVzdCBpcyBtb3JlIGFwcHJvcHJpYXRlIGluIHRoaXMgY2FzZS4gRnVydGhlcm1vcmUsIHdlIHdpbGwgYWNjb3VudCBmb3IgdGhlIGluY3JlYXNlZCByaXNrIG9mIHR5cGUgSSBlcnJvciB3aXRoIHRoZSBUdWtleSB0ZXN0KGR1ZSB0byBtdWx0cGxlIGNvbXBhcmlzb25zKSwgYXMgd2VsbCBhcyB1bmRlcnN0YW5kIHdoaWNoIGdyb3VwcyBhcmUgc2lnbmlmaWNhbnQgKG9yIG5vdCkuIExhc3RseSwgdGhpcyBtZWFucyB0aGF0IHdlIHdpbGwgYmUgdXNpbmcgcmVwb3J0aW5nIGEgKipwIHZhbHVlKiogYnV0IG5vdCBhICoqY29uZmlkZW5jZSBpbnRlcnZhbCoqLCBzaW5jZSB0aGlzIHR5cGUgb2Ygc3RhdGlzdGljYWwgYW5hbHlzaXMgZG9lcyBub3Qgc3VwcG9ydCB0aGUgbGF0dGVyLg0KDQpBTk9WQSBpcyB1c2VkIHRvIGNvbXBhcmUgZGlmZmVyZW5jZXMgb2YgbWVhbnMgYW1vbmcgbW9yZSB0aGFuIDIgZ3JvdXBzLiBJdCBkb2VzIHRoaXMgYnkgbG9va2luZyBhdCB2YXJpYXRpb24gaW4gdGhlIGRhdGEgYW5kIHdoZXJlIHRoYXQgdmFyaWF0aW9uIGlzIGZvdW5kIChoZW5jZSBpdHMgbmFtZSkuIFNwZWNpZmljYWxseSwgQU5PVkEgY29tcGFyZXMgdGhlIGFtb3VudCBvZiB2YXJpYXRpb24gYmV0d2VlbiBncm91cHMgd2l0aCB0aGUgYW1vdW50IG9mIHZhcmlhdGlvbiB3aXRoaW4gZ3JvdXBzLiBJdCBjYW4gYmUgdXNlZCBmb3IgYm90aCBvYnNlcnZhdGlvbmFsIGFuZCBleHBlcmltZW50YWwgc3R1ZGllcy4NCg0KIyMjIyMgcCB2YWx1ZQ0KDQoqKkludGVycHJldGF0aW9uKio6DQoNCldlIGNhbiBzdGFydCBieSBjb25kdWN0aW5nIGEgQU5PVkEgdGVzdCwgZGVzcGl0ZSB0aGUgaG9tb2dlbmVpdHkgYXNzdW1wdGlvbiBiZWluZyB2aW9sYXRlZCwgYXMgYSBwb2ludCBvZiBjb21wYXJpc29uIHdpdGggdGhlIG9uZSB3YXkgdGVzdCAoYmVsb3cpLiBXZSBjYW4gc2VlIHRoYXQgdGhlIHAgdmFsdWUgaXMgYWxtb3N0IDAsIHdoaWNoIG1lYW5zIHdlIGNhbiByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyBhbmQgdGhhdCB0aGVyZSBhcmUgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgYmV0d2VlbiBhdCBsZWFzdCB0d28gb2Ygb3VyIGdyb3Vwcy4NCg0KYGBge3J9DQp0aWR5KHJlcy5hb3YpJT4lDQogIGtibChjYXB0aW9uID0gYygiQU5PVkEgdGFibGUgLSB3aXRob3V0IGludGVyY2VwdCIpLCApJT4lDQogIGthYmxlX3BhcGVyKCJob3ZlciIsIGZ1bGxfd2lkdGggPSBGKQ0KDQojIHRpZHkoQW5vdmEocmVzLmFvdiwgdHlwZSA9MykpJT4lDQojICAga2JsKGNhcHRpb24gPSBjKCJBTk9WQSB0YWJsZSAtIHdpdGggaW50ZXJjZXB0IikpJT4lDQojICAga2FibGVfcGFwZXIoImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpDQoNCnZhcmlhbmNlX2V4cGxhaW5lZCA8LSByb3VuZCgNCiAgc3VtbWFyeS5sbShyZXMuYW92KSRyLnNxdWFyZWQqMTAwLCAxDQogICkNCmBgYA0KDQpJbiB0aGUgY29udGV4dCBvZiB0aGUgcmVzZWFyY2ggcXVlc3Rpb24sIHRoZSBBTk9WQSBvdXRwdXQgYWxzbyBzaG93cyB1cyB0aGF0IG9ubHkgYXJvdW5kICoqYHIgcGFzdGUodmFyaWFuY2VfZXhwbGFpbmVkLCAiJSIsIHNlcCA9IiIpYCoqIG9mIHRoZSB2YXJpYW5jZSBpbiB0b3RhbCBmYW1pbHkgaW5jb21lIGlzIGV4cGxhaW5lZCBieSB0aGUgcmVzcG9uZGVudCdzIGluY29tZSB3aGVuIDE2IHllYXJzIG9sZC4gSG93ZXZlciwgdGhpcyBvbmx5IHRlbGxzIHVzIHRoYXQgc29tZSBncm91cHMgYXJlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IHRvIG90aGVycywgbm90IHdoaWNoIG9uZXMuIFdlIHdpbGwgbmVlZCB0byBydW4gYSAqKlR1a2V5IHBvc3QgaG9jIGFuYWx5c2lzKiogdG8gZmluZCBvdXQgbW9yZSBkZXRhaWwuDQoNCkEgc2ltaWxhciByZXN1bHQgaXMgc2hvd24gYnkgb3VyIG9uZSB3YXkgdGVzdCBiZWxvdy4gTm8gb3RoZXIgbWV0aG9kcyB3ZXJlIGFwcGxpY2FibGUgYW5kIGhlbmNlIHRoZXJlJ3Mgbm90aGluZyB0byBjb21wYXJlIG90aGVyIHRoYW4gdGhlIHR3byBkZXNjcmliZWQgYWJvdmUuDQoNCmBgYHtyfQ0KcmVzLmFvdjIgPC0gb25ld2F5LnRlc3QoY29uaW5jIH4gaW5jb20xNiwgZGF0YSA9IHF1ZXN0aW9uXzNfZGV0YWlsKQ0KDQp0aWR5KHJlcy5hb3YyKSU+JQ0KICBrYmwoY2FwdGlvbiA9IGMoIk9uZSB3YXkgdGVzdCIpLCApJT4lDQogIGthYmxlX3BhcGVyKCJob3ZlciIsIGZ1bGxfd2lkdGggPSBGKQ0KYGBgDQoNCk9uY2Ugd2UgYWNjb3VudCBmb3IgdGhlIGluY3JlYXNlZCByaXNrIG9mIHR5cGUgSSBlcnJvciB3aXRoIHRoZSBUdWtleSB0ZXN0LCB3ZSBjYW4gc3RpbGwgc2VlIGEgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBmb2xsb3dpbmcgZ3JvdXBzOg0KLSBBYm92ZSBBdmVyYWdlIGFuZCBGYXIgQmVsb3cgQXZlcmFnZQ0KLSBBYm92ZSBBdmVyYWdlIGFuZCBCZWxvdyBBdmVyYWdlDQotIEFib3ZlIEF2ZXJhZ2UgYW5kIEF2ZXJhZ2UNCg0KYGBge3J9DQp0aWR5KFR1a2V5SFNEKHJlcy5hb3YpKSU+JQ0KICBrYmwoY2FwdGlvbiA9IGMoIlR1a2V5IHBvc3QgaG9jIGFuYWx5c2lzIikpJT4lDQogIGthYmxlX3BhcGVyKCJob3ZlciIsIGZ1bGxfd2lkdGggPSBGKQ0KYGBg