Statistical processes are based on probability models. This means some (hopefully small) chance of error will always be present due to randomness. We don’t question the validity of every statistical result, but one should wonder if some way exists to quantify how certain we are that our results are accurate.

Spoiler Alert: there is a way!

Initializing RStudio

Please install the package pwr before initializing RStudio for this session. Use Tools: Install Packages to do so. The code block below uses the library function to ensure that the Mosaic and pwr packages are loaded and will also import the data frame used in this module: Data3350

library(mosaic)
library(pwr)
library(readxl)
Data3350 = read_excel("Data3350.xlsx")

I. Statistical Power

The power of a statistical test is the percentage chance that a specific test will reject the null hypothesis when, in fact, the null is actually false. Seems simple, right? Yet, we don’t know if the null is false without statistical tests. Some chance of error is always lurking, but we rarely know when a statistical error has actually occurred.

The goal is having enough power each time we perform a statistics-based investigation. Three ways exist to improve power:

  1. Increase the sample size.
  2. Increase the effect size.
  3. Increase \(\alpha\).

The first two ideas seem straightforward. Increasing the sample size invokes the Law of Large Numbers which says that estimates of parameters become more accurate as sample size increases. With increased accuracy of estimates, we will correctly reject the null more often. For the second, we face the ubiquitous scientific problem of separating signal from noise. In a study with an experimental design, we test the main effect of the treatment. If we can magnify the main effect, we have a better chance of picking up on difference between the treatment and control groups. The main effect can be made larger, for example, by increasing the duration or intensity of the treatment.

The first two options for improving power are not always possible. Increasing the intensity of a treatment may threaten participant safety. For some research, it is hard to find enough participants. What terminally ill patients will sign up for a randomized treatment vs. control group design where they have a 50-50 chance of being assigned to the placebo (control) group? Also, some current cancer researchers have found that certain treatments work well only if specific genetic markers are present in the patient. Every study would have a huge sample size and adequate power if data were inexpensive and easy to collect, but ethical standards, privacy protections and many other concerns mean the opposite. High quality, ethical data sets are expensive and time-consuming to generate.

What about the third way: increasing \(\alpha\) to improve power? To understand how to set \(\alpha\) requires an investigation of statistical error.

II. Statistical Error

In statistics, we have two forms of randomness-based errors:

  1. Type I Error. Falsely rejecting the null hypothesis.
  2. Type II Error. Falsely failing to reject the null hypothesis.

The level of significance \(\alpha\) is the percent chance of making a Type I error. Why is this true?

Consider a hypothesis test of Perfectionism where we know the population follows exactly a \(N(82,18)\) distribution (measured using the APS-R). Perhaps we’ve measured the Perfectionism level for every single undergraduate student currently enrolled at a certain university. Let’s test a hypothesis: \[H_0 : \mu = 82\] \[H_a : \mu > 82\] The population is known to be exactly 82, so rejecting the null would be incorrect. Yet, let’s test the above hypothesis repeatedly by drawing samples of size 40 from this exact \(N(82,18)\) distribution. Over thousands of samples, we will find a mean far enough above \(\mu = 82\) to reject the null 5% of the time. Yet, it would be an error. We’ll falsely reject the null approximately 5% of the times.

When we set \(\alpha\), we are choosing the probability of making a Type I error. This is not a researcher error. Type I errors occur due to randomness because we use probability models in hypothesis testing. Type I and Type II errors are inescapable realities for any statistical test.

# library(mosaic)
tests = do(1000) * t.test(rnorm(40,82,18),mu = 82)
tests
histogram(tests$p.value, width = 0.05 )

When we enter a logical statement into the sum function, it will count instead of adding.

sum(tests$p.value < 0.05)
[1] 43

While results will vary if we rerun the code blocks, we see that in this example 3 of samples turned up with \(p\)-values less than 0.05. The actual Type I error in our randomized experiment was 4.3%.

No matter what, we will always have a Type I error rate. While we can set \(\alpha\) lower, say \(\alpha = 0.01\), when we do then Type II error will increase and power will decrease.

1. Power = \(1-\beta\)

The percentage chance of a Type II error is defined to be \(\beta\). There is no exact formula for the relationship between \(\alpha\) and \(\beta\), but we do know they have an inverse relationship. As Type I error increases (with everything else held constant), Type II error will decrease, and vice versa.

If \(\beta\) is the probability of a Type II error occurring, what is it’s opposite? Think of it this way: \(\beta\) is the probability of an event occurring. What event? Let \(T2\) represent the event that a Type II error occurs, and we’re simply saying \[P(T2)=\beta\] We know that \(P(\overline{T2})= 1 - \beta\), so what is the event \(\overline{T2}\)? The logical opposite of “falsely failing to reject the null” is “correctly rejecting the null,” which is the definition of power.

Thus, as we set \(\alpha\), we are making a choice that affects \(\beta\) and therefore power. If we increase \(\alpha\), \(\beta\) will decrease and power will increase.

2. Adequate Power

Jacob Cohen was the statistics pioneer who investigated power, and his work still underpins our understanding. According to Cohen,

  • Power = 0.6 is poor
  • Power = 0.7 is adequate
  • Power = 0.8 is good
  • Power = 0.9 is excellent

3. Calculating Power

Recall the matched pairs example from Module S5 where we measured Stress in a pretest vs. post test format. We created the gain scores (increase in Stress) as follows

Pre = Data3350$Stress1
Post = Data3350$Stress2
Gain = Post - Pre

To estimate power, we first must calculate effect size which, for matched pairs, will be the average gain score divided by the standard deviation. Let’s store the summary stats in a variable called \(\text{g}\) so we can access them as needed.

g = favstats(Gain)
g

We refer to the various objects in the \(\text{favstats}\) output using dollar signs. For example, let’s list the mean, standard deviation and sample size for the gain scores.

g$mean
[1] 0.7682927
g$sd
[1] 3.190472
g$n
[1] 164

The power guru Jacob Cohen used the variable \(d\) to indicate effect size which he defined to be, for this case, the average Gain score divided by the sample standard deviation.

d = g$mean / g$sd
d
[1] 0.2408085

Cohen defined different levels of effect sizes. \[\begin{array}{ccl}d &&\text{Effect Size}\\ \hline 0.2 && \text{Small}\\ 0.5 && \text{Medium}\\ 0.8 && \text{Large} \end{array}\] In our example, we have a small effect size since it’s close to \(0.2\). We loaded the \(\textbf{pwr}\) package which implements the recommendations in the seminal textbook on power by Cohen (1988). Through the pwr package, we now have access to the function pwr.t.test which will pretty much do what its name suggests: estimate the power of a \(t\)-test.

library(pwr)
pwr.t.test(n = g$n, d = g$mean/g$sd, sig.level = .05, type = "paired")

     Paired t test power calculation 

              n = 164
              d = 0.2408085
      sig.level = 0.05
          power = 0.8655655
    alternative = two.sided

NOTE: n is number of *pairs*

The default hypothesis is a two-tailed test, but if you recall we were running a one-tailed test that the Stress measured at midterm would be greater than Stress at the beginning of the semester. Let’s add the alternative hypothesis and see if changes the power which, in this case, was approximately .87 which is good (see chart above).

pwr.t.test(n = g$n, d = g$mean/g$sd, sig.level = .05, type = "paired", alternative = "greater")

     Paired t test power calculation 

              n = 164
              d = 0.2408085
      sig.level = 0.05
          power = 0.9230891
    alternative = greater

NOTE: n is number of *pairs*

While this is excellent power, notice that the for this small effect size, we needed a very large sample to generate excellent power. What if our sample size had only been 50 yet the effect size was d = 0.25?

pwr.t.test(n = 50, d = 0.25, sig.level = .05, type = "paired", alternative = "greater")

     Paired t test power calculation 

              n = 50
              d = 0.25
      sig.level = 0.05
          power = 0.5392054
    alternative = greater

NOTE: n is number of *pairs*

For sample size of 50, we don’t even have poor power, and similar sample sizes are pretty typical for many research situations.

III. Power Charts

Both charts below clearly show the impact of increasing sample sizes on power. As sample size increases, power increases. The two charts below focus on the impact of the other two ways for increasing power: increasing the effect size and increasing the level of significance \(\alpha\).

1. Effect Size and Power

The chart below summarizes the power for different levels of effect size (small, medium, large) using 2-Tailed, 1-Sample \(t\)-tests with \(\alpha = 0.05\). Notice how low the power is for small effect sizes (left column) even for sample sizes of 100. On the other hand, consider that we have excellent power for samples of only 20 if the effect size is large (right column).

2. Level of Significance \((\alpha)\) and Power

The chart below summarizes the power for different levels of \(\alpha\) using 2-Tailed, 1-Sample \(t\)-tests with effect sizes \(d = 0.30\). Notice how low the power is for small levels of significance (left column) even for sample sizes of 100. The power is much better for higher levels of significance.

3. Overpowering Statistical Test

Oddly, you can have too much power. When sample sizes are ridiculously large, almost any miniscule effect size will be enough to reject the null. Yet, the results will be meaningless because no real-world difference between groups exists.

Consider a two-sample comparison of test scores where the average Treatment group score is an 80.1, and the average Control group score is an 80.0. If the standard deviations are both 10, then Cohen’s effect size is \[d = \frac{80.1-80.0}{10}=\frac{.1}{10}=0.01\] We can all agree that with test scores out of 100 points, there is no real-world difference between the Treatment and Control groups. Yet, consider the following sample sizes

Power when \(n = 1000\)

pwr.t.test(n = 1000, d = 0.01, type = "two.sample")$power
[1] 0.05574171

A very large sample size, but not much power. This seems fine as we shouldn’t be rejecting the null.

Power when \(n = 10,000\)

pwr.t.test(n = 10000, d = 0.01, type = "two.sample")$power
[1] 0.1089488

A huge sample size but still hardly any power. Good so far.

Power when \(n = 100,000\)

pwr.t.test(n = 100000, d = 0.01, type = "two.sample")$power
[1] 0.6087754

Whoa - now we have a reasonable chance of rejecting the null.

Power when \(n = 1,000,000\)

pwr.t.test(n = 1000000, d = 0.01, type = "two.sample")$power
[1] 0.9999998

With a ridiculous sample size of one million, we will always be rejecting the null despite the fact that there is no real-world difference between the group means.

Word of Caution

Generally, the issue of overpowering a test isn’t one we’re worried about. As mentioned above, data is often both difficult and expensive to collect. However, in the era of big data, we can often find massive data sets readily available online. While interesting results can certainly be derived from studying huge data sets, researchers do need to ask themselves the question: “Is this finding significant, not statistically, but in the real world context of the study?”

LS0tDQp0aXRsZTogIkVycm9yIGFuZCBQb3dlciINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNClN0YXRpc3RpY2FsIHByb2Nlc3NlcyBhcmUgYmFzZWQgb24gcHJvYmFiaWxpdHkgbW9kZWxzLiBUaGlzIG1lYW5zIHNvbWUgKGhvcGVmdWxseSBzbWFsbCkgY2hhbmNlIG9mIGVycm9yIHdpbGwgYWx3YXlzIGJlIHByZXNlbnQgZHVlIHRvIHJhbmRvbW5lc3MuIFdlIGRvbid0IHF1ZXN0aW9uIHRoZSB2YWxpZGl0eSBvZiBldmVyeSBzdGF0aXN0aWNhbCByZXN1bHQsIGJ1dCBvbmUgc2hvdWxkIHdvbmRlciBpZiBzb21lIHdheSBleGlzdHMgdG8gcXVhbnRpZnkgaG93IGNlcnRhaW4gd2UgYXJlIHRoYXQgb3VyIHJlc3VsdHMgYXJlIGFjY3VyYXRlLg0KDQpTcG9pbGVyIEFsZXJ0OiB0aGVyZSBpcyBhIHdheSENCg0KPGRpdiBzdHlsZT0iZmxvYXQ6Y2VudGVyOyBtYXJnaW46IDhweDsgYm9yZGVyOjJweCBibGFjayBzb2xpZDsgcGFkZGluZzogMHB4IDEwcHggNXB4Ij4NCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6IHJlZDsiPkluaXRpYWxpemluZyBSU3R1ZGlvPC9zcGFuPg0KUGxlYXNlIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPmluc3RhbGwgdGhlIHBhY2thZ2UgKipwd3IqKjwvc3Bhbj4gYmVmb3JlIGluaXRpYWxpemluZyBSU3R1ZGlvIGZvciB0aGlzIHNlc3Npb24uIFVzZSAqKlRvb2xzOiBJbnN0YWxsIFBhY2thZ2VzKiogdG8gZG8gc28uIFRoZSBjb2RlIGJsb2NrIGJlbG93IHVzZXMgdGhlICoqbGlicmFyeSoqIGZ1bmN0aW9uIHRvIGVuc3VyZSB0aGF0IHRoZSAqKk1vc2FpYyoqIGFuZCAqKnB3cioqIHBhY2thZ2VzIGFyZSBsb2FkZWQgYW5kIHdpbGwgYWxzbyBpbXBvcnQgdGhlIGRhdGEgZnJhbWUgdXNlZCBpbiB0aGlzIG1vZHVsZTogKipEYXRhMzM1MCoqDQoNCmBgYHtyfQ0KbGlicmFyeShtb3NhaWMpDQpsaWJyYXJ5KHB3cikNCmxpYnJhcnkocmVhZHhsKQ0KRGF0YTMzNTAgPSByZWFkX2V4Y2VsKCJEYXRhMzM1MC54bHN4IikNCmBgYA0KPC9kaXY+DQoNCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+SS4gU3RhdGlzdGljYWwgUG93ZXI8L3NwYW4+DQoNClRoZSBwb3dlciBvZiBhIHN0YXRpc3RpY2FsIHRlc3QgaXMgdGhlIHBlcmNlbnRhZ2UgY2hhbmNlIHRoYXQgYSBzcGVjaWZpYyB0ZXN0IHdpbGwgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgd2hlbiwgaW4gZmFjdCwgdGhlIG51bGwgaXMgYWN0dWFsbHkgZmFsc2UuIFNlZW1zIHNpbXBsZSwgcmlnaHQ/IFlldCwgd2UgZG9uJ3Qga25vdyBpZiB0aGUgbnVsbCBpcyBmYWxzZSB3aXRob3V0IHN0YXRpc3RpY2FsIHRlc3RzLiBTb21lIGNoYW5jZSBvZiBlcnJvciBpcyBhbHdheXMgbHVya2luZywgYnV0IHdlIHJhcmVseSBrbm93IHdoZW4gYSBzdGF0aXN0aWNhbCBlcnJvciBoYXMgYWN0dWFsbHkgb2NjdXJyZWQuDQoNClRoZSBnb2FsIGlzIGhhdmluZyBlbm91Z2ggcG93ZXIgZWFjaCB0aW1lIHdlIHBlcmZvcm0gYSBzdGF0aXN0aWNzLWJhc2VkIGludmVzdGlnYXRpb24uIFRocmVlIHdheXMgZXhpc3QgdG8gaW1wcm92ZSBwb3dlcjoNCg0KMS4gSW5jcmVhc2UgdGhlIHNhbXBsZSBzaXplLg0KMi4gSW5jcmVhc2UgdGhlIGVmZmVjdCBzaXplLg0KMy4gSW5jcmVhc2UgJFxhbHBoYSQuDQoNClRoZSBmaXJzdCB0d28gaWRlYXMgc2VlbSBzdHJhaWdodGZvcndhcmQuIEluY3JlYXNpbmcgdGhlIHNhbXBsZSBzaXplIGludm9rZXMgdGhlIExhdyBvZiBMYXJnZSBOdW1iZXJzIHdoaWNoIHNheXMgdGhhdCBlc3RpbWF0ZXMgb2YgcGFyYW1ldGVycyBiZWNvbWUgbW9yZSBhY2N1cmF0ZSBhcyBzYW1wbGUgc2l6ZSBpbmNyZWFzZXMuIFdpdGggaW5jcmVhc2VkIGFjY3VyYWN5IG9mIGVzdGltYXRlcywgd2Ugd2lsbCBjb3JyZWN0bHkgcmVqZWN0IHRoZSBudWxsIG1vcmUgb2Z0ZW4uIEZvciB0aGUgc2Vjb25kLCB3ZSBmYWNlIHRoZSB1YmlxdWl0b3VzIHNjaWVudGlmaWMgcHJvYmxlbSBvZiBzZXBhcmF0aW5nIHNpZ25hbCBmcm9tIG5vaXNlLiBJbiBhIHN0dWR5IHdpdGggYW4gZXhwZXJpbWVudGFsIGRlc2lnbiwgd2UgdGVzdCB0aGUgbWFpbiBlZmZlY3Qgb2YgdGhlIHRyZWF0bWVudC4gSWYgd2UgY2FuIG1hZ25pZnkgdGhlIG1haW4gZWZmZWN0LCB3ZSBoYXZlIGEgYmV0dGVyIGNoYW5jZSBvZiBwaWNraW5nIHVwIG9uIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgdHJlYXRtZW50IGFuZCBjb250cm9sIGdyb3Vwcy4gVGhlIG1haW4gZWZmZWN0IGNhbiBiZSBtYWRlIGxhcmdlciwgZm9yIGV4YW1wbGUsIGJ5IGluY3JlYXNpbmcgdGhlIGR1cmF0aW9uIG9yIGludGVuc2l0eSBvZiB0aGUgdHJlYXRtZW50LiANCg0KVGhlIGZpcnN0IHR3byBvcHRpb25zIGZvciBpbXByb3ZpbmcgcG93ZXIgYXJlIG5vdCBhbHdheXMgcG9zc2libGUuIEluY3JlYXNpbmcgdGhlIGludGVuc2l0eSBvZiBhIHRyZWF0bWVudCBtYXkgdGhyZWF0ZW4gcGFydGljaXBhbnQgc2FmZXR5LiBGb3Igc29tZSByZXNlYXJjaCwgaXQgaXMgaGFyZCB0byBmaW5kIGVub3VnaCBwYXJ0aWNpcGFudHMuIFdoYXQgdGVybWluYWxseSBpbGwgcGF0aWVudHMgd2lsbCBzaWduIHVwIGZvciBhIHJhbmRvbWl6ZWQgdHJlYXRtZW50IHZzLiBjb250cm9sIGdyb3VwIGRlc2lnbiB3aGVyZSB0aGV5IGhhdmUgYSA1MC01MCBjaGFuY2Ugb2YgYmVpbmcgYXNzaWduZWQgdG8gdGhlIHBsYWNlYm8gKGNvbnRyb2wpIGdyb3VwPyBBbHNvLCBzb21lIGN1cnJlbnQgY2FuY2VyIHJlc2VhcmNoZXJzIGhhdmUgZm91bmQgdGhhdCBjZXJ0YWluIHRyZWF0bWVudHMgd29yayB3ZWxsIG9ubHkgaWYgc3BlY2lmaWMgZ2VuZXRpYyBtYXJrZXJzIGFyZSBwcmVzZW50IGluIHRoZSBwYXRpZW50LiBFdmVyeSBzdHVkeSB3b3VsZCBoYXZlIGEgaHVnZSBzYW1wbGUgc2l6ZSBhbmQgYWRlcXVhdGUgcG93ZXIgaWYgZGF0YSB3ZXJlIGluZXhwZW5zaXZlIGFuZCBlYXN5IHRvIGNvbGxlY3QsIGJ1dCBldGhpY2FsIHN0YW5kYXJkcywgcHJpdmFjeSBwcm90ZWN0aW9ucyBhbmQgbWFueSBvdGhlciBjb25jZXJucyBtZWFuIHRoZSBvcHBvc2l0ZS4gSGlnaCBxdWFsaXR5LCBldGhpY2FsIGRhdGEgc2V0cyBhcmUgZXhwZW5zaXZlIGFuZCB0aW1lLWNvbnN1bWluZyB0byBnZW5lcmF0ZS4NCg0KV2hhdCBhYm91dCB0aGUgdGhpcmQgd2F5OiBpbmNyZWFzaW5nICRcYWxwaGEkIHRvIGltcHJvdmUgcG93ZXI/IFRvIHVuZGVyc3RhbmQgaG93IHRvIHNldCAkXGFscGhhJCByZXF1aXJlcyBhbiBpbnZlc3RpZ2F0aW9uIG9mICoqc3RhdGlzdGljYWwgZXJyb3IqKi4NCg0KIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5JSS4gU3RhdGlzdGljYWwgRXJyb3I8L3NwYW4+DQoNCkluIHN0YXRpc3RpY3MsIHdlIGhhdmUgdHdvIGZvcm1zIG9mIHJhbmRvbW5lc3MtYmFzZWQgZXJyb3JzOg0KDQoxLiAqKlR5cGUgSSBFcnJvci4qKiBGYWxzZWx5IHJlamVjdGluZyB0aGUgbnVsbCBoeXBvdGhlc2lzLg0KMi4gKipUeXBlIElJIEVycm9yLioqIEZhbHNlbHkgZmFpbGluZyB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4NCg0KVGhlIGxldmVsIG9mIHNpZ25pZmljYW5jZSAkXGFscGhhJCBpcyB0aGUgcGVyY2VudCBjaGFuY2Ugb2YgbWFraW5nIGEgVHlwZSBJIGVycm9yLiBXaHkgaXMgdGhpcyB0cnVlPw0KDQpDb25zaWRlciBhIGh5cG90aGVzaXMgdGVzdCBvZiBQZXJmZWN0aW9uaXNtIHdoZXJlIHdlIGtub3cgdGhlIHBvcHVsYXRpb24gZm9sbG93cyBleGFjdGx5IGEgJE4oODIsMTgpJCBkaXN0cmlidXRpb24gKG1lYXN1cmVkIHVzaW5nIHRoZSA8YSBocmVmID0gaHR0cDovL2tlbm5ldGh3YW5nLmNvbS9hcHNyL3NjYWxlcy9BUFMtUl85Ni5wZGY+QVBTLVI8L2E+KS4gUGVyaGFwcyB3ZSd2ZSBtZWFzdXJlZCB0aGUgUGVyZmVjdGlvbmlzbSBsZXZlbCBmb3IgZXZlcnkgc2luZ2xlIHVuZGVyZ3JhZHVhdGUgc3R1ZGVudCBjdXJyZW50bHkgZW5yb2xsZWQgYXQgYSBjZXJ0YWluIHVuaXZlcnNpdHkuIExldCdzIHRlc3QgYSBoeXBvdGhlc2lzOg0KJCRIXzAgOiBcbXUgPSA4MiQkDQokJEhfYSA6IFxtdSA+IDgyJCQNClRoZSBwb3B1bGF0aW9uIGlzIGtub3duIHRvIGJlIGV4YWN0bHkgODIsIHNvIHJlamVjdGluZyB0aGUgbnVsbCB3b3VsZCBiZSBpbmNvcnJlY3QuIFlldCwgbGV0J3MgdGVzdCB0aGUgYWJvdmUgaHlwb3RoZXNpcyByZXBlYXRlZGx5IGJ5IGRyYXdpbmcgc2FtcGxlcyBvZiBzaXplIDQwIGZyb20gdGhpcyBleGFjdCAkTig4MiwxOCkkIGRpc3RyaWJ1dGlvbi4gT3ZlciB0aG91c2FuZHMgb2Ygc2FtcGxlcywgd2Ugd2lsbCBmaW5kIGEgbWVhbiBmYXIgZW5vdWdoIGFib3ZlICRcbXUgPSA4MiQgdG8gcmVqZWN0IHRoZSBudWxsIDUlIG9mIHRoZSB0aW1lLiBZZXQsIGl0IHdvdWxkIGJlIGFuIGVycm9yLiBXZSdsbCBmYWxzZWx5IHJlamVjdCB0aGUgbnVsbCBhcHByb3hpbWF0ZWx5IDUlIG9mIHRoZSB0aW1lcy4NCg0KV2hlbiB3ZSBzZXQgJFxhbHBoYSQsIHdlIGFyZSBjaG9vc2luZyB0aGUgcHJvYmFiaWxpdHkgb2YgbWFraW5nIGEgVHlwZSBJIGVycm9yLiBUaGlzIGlzIG5vdCBhIHJlc2VhcmNoZXIgZXJyb3IuIFR5cGUgSSBlcnJvcnMgb2NjdXIgZHVlIHRvIHJhbmRvbW5lc3MgYmVjYXVzZSB3ZSB1c2UgcHJvYmFiaWxpdHkgbW9kZWxzIGluIGh5cG90aGVzaXMgdGVzdGluZy4gVHlwZSBJIGFuZCBUeXBlIElJIGVycm9ycyBhcmUgaW5lc2NhcGFibGUgcmVhbGl0aWVzIGZvciBhbnkgc3RhdGlzdGljYWwgdGVzdC4NCg0KYGBge3J9DQojIGxpYnJhcnkobW9zYWljKQ0KdGVzdHMgPSBkbygxMDAwKSAqIHQudGVzdChybm9ybSg0MCw4MiwxOCksbXUgPSA4MikNCnRlc3RzDQpgYGANCg0KYGBge3J9DQpoaXN0b2dyYW0odGVzdHMkcC52YWx1ZSwgd2lkdGggPSAwLjA1ICkNCg0KYGBgDQoNCldoZW4gd2UgZW50ZXIgYSBsb2dpY2FsIHN0YXRlbWVudCBpbnRvIHRoZSAqKnN1bSoqIGZ1bmN0aW9uLCBpdCB3aWxsIGNvdW50IGluc3RlYWQgb2YgYWRkaW5nLg0KDQpgYGB7cn0NCnN1bSh0ZXN0cyRwLnZhbHVlIDwgMC4wNSkNCmBgYA0KDQpXaGlsZSByZXN1bHRzIHdpbGwgdmFyeSBpZiB3ZSByZXJ1biB0aGUgY29kZSBibG9ja3MsIHdlIHNlZSB0aGF0IGluIHRoaXMgZXhhbXBsZSAzIG9mIHNhbXBsZXMgdHVybmVkIHVwIHdpdGggJHAkLXZhbHVlcyBsZXNzIHRoYW4gMC4wNS4gVGhlIGFjdHVhbCBUeXBlIEkgZXJyb3IgaW4gb3VyIHJhbmRvbWl6ZWQgZXhwZXJpbWVudCB3YXMgYHIgcGFzdGUoc3VtKHRlc3RzJHAudmFsdWUgPCAwLjA1KS8xMClgJS4NCg0KTm8gbWF0dGVyIHdoYXQsIHdlIHdpbGwgYWx3YXlzIGhhdmUgYSBUeXBlIEkgZXJyb3IgcmF0ZS4gV2hpbGUgd2UgY2FuIHNldCAkXGFscGhhJCBsb3dlciwgc2F5ICRcYWxwaGEgPSAwLjAxJCwgd2hlbiB3ZSBkbyB0aGVuIFR5cGUgSUkgZXJyb3Igd2lsbCBpbmNyZWFzZSBhbmQgcG93ZXIgd2lsbCBkZWNyZWFzZS4NCg0KIyMgMS4gUG93ZXIgPSAkMS1cYmV0YSQNCg0KVGhlIHBlcmNlbnRhZ2UgY2hhbmNlIG9mIGEgVHlwZSBJSSBlcnJvciBpcyBkZWZpbmVkIHRvIGJlICRcYmV0YSQuIFRoZXJlIGlzIG5vIGV4YWN0IGZvcm11bGEgZm9yIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiAkXGFscGhhJCBhbmQgJFxiZXRhJCwgYnV0IHdlIGRvIGtub3cgdGhleSBoYXZlIGFuIGludmVyc2UgcmVsYXRpb25zaGlwLiBBcyBUeXBlIEkgZXJyb3IgaW5jcmVhc2VzICh3aXRoIGV2ZXJ5dGhpbmcgZWxzZSBoZWxkIGNvbnN0YW50KSwgVHlwZSBJSSBlcnJvciB3aWxsIGRlY3JlYXNlLCBhbmQgdmljZSB2ZXJzYS4NCg0KSWYgJFxiZXRhJCBpcyB0aGUgcHJvYmFiaWxpdHkgb2YgYSBUeXBlIElJIGVycm9yIG9jY3VycmluZywgd2hhdCBpcyBpdCdzIG9wcG9zaXRlPyBUaGluayBvZiBpdCB0aGlzIHdheTogJFxiZXRhJCBpcyB0aGUgcHJvYmFiaWxpdHkgb2YgYW4gZXZlbnQgb2NjdXJyaW5nLiBXaGF0IGV2ZW50PyBMZXQgJFQyJCByZXByZXNlbnQgdGhlIGV2ZW50IHRoYXQgYSBUeXBlIElJIGVycm9yIG9jY3VycywgYW5kIHdlJ3JlIHNpbXBseSBzYXlpbmcgJCRQKFQyKT1cYmV0YSQkDQpXZSBrbm93IHRoYXQgJFAoXG92ZXJsaW5le1QyfSk9IDEgLSBcYmV0YSQsIHNvIHdoYXQgaXMgdGhlIGV2ZW50ICRcb3ZlcmxpbmV7VDJ9JD8gVGhlIGxvZ2ljYWwgb3Bwb3NpdGUgb2YgImZhbHNlbHkgZmFpbGluZyB0byByZWplY3QgdGhlIG51bGwiIGlzICJjb3JyZWN0bHkgcmVqZWN0aW5nIHRoZSBudWxsLCIgd2hpY2ggaXMgdGhlIGRlZmluaXRpb24gb2YgcG93ZXIuDQoNClRodXMsIGFzIHdlIHNldCAkXGFscGhhJCwgd2UgYXJlIG1ha2luZyBhIGNob2ljZSB0aGF0IGFmZmVjdHMgJFxiZXRhJCBhbmQgdGhlcmVmb3JlIHBvd2VyLiBJZiB3ZSBpbmNyZWFzZSAkXGFscGhhJCwgJFxiZXRhJCB3aWxsIGRlY3JlYXNlIGFuZCBwb3dlciB3aWxsIGluY3JlYXNlLg0KDQojIyAyLiBBZGVxdWF0ZSBQb3dlcg0KDQpKYWNvYiBDb2hlbiB3YXMgdGhlIHN0YXRpc3RpY3MgcGlvbmVlciB3aG8gaW52ZXN0aWdhdGVkIHBvd2VyLCBhbmQgaGlzIHdvcmsgc3RpbGwgdW5kZXJwaW5zIG91ciB1bmRlcnN0YW5kaW5nLiBBY2NvcmRpbmcgdG8gQ29oZW4sDQoNCiogUG93ZXIgPSAwLjYgaXMgcG9vcg0KKiBQb3dlciA9IDAuNyBpcyBhZGVxdWF0ZQ0KKiBQb3dlciA9IDAuOCBpcyBnb29kDQoqIFBvd2VyID0gMC45IGlzIGV4Y2VsbGVudA0KDQojIyAzLiBDYWxjdWxhdGluZyBQb3dlcg0KDQpSZWNhbGwgdGhlIG1hdGNoZWQgcGFpcnMgZXhhbXBsZSBmcm9tIE1vZHVsZSBTNSB3aGVyZSB3ZSBtZWFzdXJlZCBTdHJlc3MgaW4gYSBwcmV0ZXN0IHZzLiBwb3N0IHRlc3QgZm9ybWF0LiBXZSBjcmVhdGVkIHRoZSBnYWluIHNjb3JlcyAoaW5jcmVhc2UgaW4gU3RyZXNzKSBhcyBmb2xsb3dzDQoNCmBgYHtyfQ0KUHJlID0gRGF0YTMzNTAkU3RyZXNzMQ0KUG9zdCA9IERhdGEzMzUwJFN0cmVzczINCkdhaW4gPSBQb3N0IC0gUHJlDQpgYGANCg0KVG8gZXN0aW1hdGUgcG93ZXIsIHdlIGZpcnN0IG11c3QgY2FsY3VsYXRlIGVmZmVjdCBzaXplIHdoaWNoLCBmb3IgbWF0Y2hlZCBwYWlycywgd2lsbCBiZSB0aGUgYXZlcmFnZSBnYWluIHNjb3JlIGRpdmlkZWQgYnkgdGhlIHN0YW5kYXJkIGRldmlhdGlvbi4gTGV0J3Mgc3RvcmUgdGhlIHN1bW1hcnkgc3RhdHMgaW4gYSB2YXJpYWJsZSBjYWxsZWQgJFx0ZXh0e2d9JCBzbyB3ZSBjYW4gYWNjZXNzIHRoZW0gYXMgbmVlZGVkLg0KDQpgYGB7cn0NCmcgPSBmYXZzdGF0cyhHYWluKQ0KZw0KYGBgDQoNCldlIHJlZmVyIHRvIHRoZSB2YXJpb3VzIG9iamVjdHMgaW4gdGhlICRcdGV4dHtmYXZzdGF0c30kIG91dHB1dCB1c2luZyBkb2xsYXIgc2lnbnMuIEZvciBleGFtcGxlLCBsZXQncyBsaXN0IHRoZSBtZWFuLCBzdGFuZGFyZCBkZXZpYXRpb24gYW5kIHNhbXBsZSBzaXplIGZvciB0aGUgZ2FpbiBzY29yZXMuDQoNCmBgYHtyfQ0KZyRtZWFuDQpnJHNkDQpnJG4NCmBgYA0KDQpUaGUgcG93ZXIgZ3VydSBKYWNvYiBDb2hlbiB1c2VkIHRoZSB2YXJpYWJsZSAkZCQgdG8gaW5kaWNhdGUgZWZmZWN0IHNpemUgd2hpY2ggaGUgZGVmaW5lZCB0byBiZSwgZm9yIHRoaXMgY2FzZSwgdGhlIGF2ZXJhZ2UgR2FpbiBzY29yZSBkaXZpZGVkIGJ5IHRoZSBzYW1wbGUgc3RhbmRhcmQgZGV2aWF0aW9uLg0KDQpgYGB7cn0NCmQgPSBnJG1lYW4gLyBnJHNkDQpkDQpgYGANCg0KQ29oZW4gZGVmaW5lZCBkaWZmZXJlbnQgbGV2ZWxzIG9mIGVmZmVjdCBzaXplcy4NCiQkXGJlZ2lue2FycmF5fXtjY2x9ZCAmJlx0ZXh0e0VmZmVjdCBTaXplfVxcIFxobGluZQ0KMC4yICYmIFx0ZXh0e1NtYWxsfVxcIDAuNSAmJiBcdGV4dHtNZWRpdW19XFwgMC44ICYmIFx0ZXh0e0xhcmdlfQ0KXGVuZHthcnJheX0kJA0KSW4gb3VyIGV4YW1wbGUsIHdlIGhhdmUgYSBzbWFsbCBlZmZlY3Qgc2l6ZSBzaW5jZSBpdCdzIGNsb3NlIHRvICQwLjIkLiBXZSBsb2FkZWQgdGhlICRcdGV4dGJme3B3cn0kIHBhY2thZ2Ugd2hpY2ggaW1wbGVtZW50cyB0aGUgcmVjb21tZW5kYXRpb25zIGluIHRoZSBzZW1pbmFsIHRleHRib29rIG9uIHBvd2VyIGJ5IENvaGVuICgxOTg4KS4gVGhyb3VnaCB0aGUgKipwd3IqKiBwYWNrYWdlLCB3ZSBub3cgaGF2ZSBhY2Nlc3MgdG8gdGhlIGZ1bmN0aW9uICoqcHdyLnQudGVzdCoqIHdoaWNoIHdpbGwgcHJldHR5IG11Y2ggZG8gd2hhdCBpdHMgbmFtZSBzdWdnZXN0czogZXN0aW1hdGUgdGhlIHBvd2VyIG9mIGEgJHQkLXRlc3QuDQoNCmBgYHtyfQ0KcHdyLnQudGVzdChuID0gZyRuLCBkID0gZyRtZWFuL2ckc2QsIHNpZy5sZXZlbCA9IC4wNSwgdHlwZSA9ICJwYWlyZWQiKQ0KYGBgDQpUaGUgZGVmYXVsdCBoeXBvdGhlc2lzIGlzIGEgdHdvLXRhaWxlZCB0ZXN0LCBidXQgaWYgeW91IHJlY2FsbCB3ZSB3ZXJlIHJ1bm5pbmcgYSBvbmUtdGFpbGVkIHRlc3QgdGhhdCB0aGUgU3RyZXNzIG1lYXN1cmVkIGF0IG1pZHRlcm0gd291bGQgYmUgZ3JlYXRlciB0aGFuIFN0cmVzcyBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBzZW1lc3Rlci4gTGV0J3MgYWRkIHRoZSBhbHRlcm5hdGl2ZSBoeXBvdGhlc2lzIGFuZCBzZWUgaWYgY2hhbmdlcyB0aGUgcG93ZXIgd2hpY2gsIGluIHRoaXMgY2FzZSwgd2FzIGFwcHJveGltYXRlbHkgLjg3IHdoaWNoIGlzIGdvb2QgKHNlZSBjaGFydCBhYm92ZSkuDQoNCmBgYHtyfQ0KcHdyLnQudGVzdChuID0gZyRuLCBkID0gZyRtZWFuL2ckc2QsIHNpZy5sZXZlbCA9IC4wNSwgdHlwZSA9ICJwYWlyZWQiLCBhbHRlcm5hdGl2ZSA9ICJncmVhdGVyIikNCmBgYA0KDQpXaGlsZSB0aGlzIGlzIGV4Y2VsbGVudCBwb3dlciwgbm90aWNlIHRoYXQgdGhlIGZvciB0aGlzIHNtYWxsIGVmZmVjdCBzaXplLCB3ZSBuZWVkZWQgYSB2ZXJ5IGxhcmdlIHNhbXBsZSB0byBnZW5lcmF0ZSBleGNlbGxlbnQgcG93ZXIuIFdoYXQgaWYgb3VyIHNhbXBsZSBzaXplIGhhZCBvbmx5IGJlZW4gNTAgeWV0IHRoZSBlZmZlY3Qgc2l6ZSB3YXMgZCA9IDAuMjU/DQoNCg0KYGBge3J9DQpwd3IudC50ZXN0KG4gPSA1MCwgZCA9IDAuMjUsIHNpZy5sZXZlbCA9IC4wNSwgdHlwZSA9ICJwYWlyZWQiLCBhbHRlcm5hdGl2ZSA9ICJncmVhdGVyIikNCmBgYA0KDQpGb3Igc2FtcGxlIHNpemUgb2YgNTAsIHdlIGRvbid0IGV2ZW4gaGF2ZSBwb29yIHBvd2VyLCBhbmQgc2ltaWxhciBzYW1wbGUgc2l6ZXMgYXJlIHByZXR0eSB0eXBpY2FsIGZvciBtYW55IHJlc2VhcmNoIHNpdHVhdGlvbnMuDQoNCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+SUlJLiBQb3dlciBDaGFydHM8L3NwYW4+DQoNCkJvdGggY2hhcnRzIGJlbG93IGNsZWFybHkgc2hvdyB0aGUgaW1wYWN0IG9mIGluY3JlYXNpbmcgc2FtcGxlIHNpemVzIG9uIHBvd2VyLiBBcyBzYW1wbGUgc2l6ZSBpbmNyZWFzZXMsIHBvd2VyIGluY3JlYXNlcy4gVGhlIHR3byBjaGFydHMgYmVsb3cgZm9jdXMgb24gdGhlIGltcGFjdCBvZiB0aGUgb3RoZXIgdHdvIHdheXMgZm9yIGluY3JlYXNpbmcgcG93ZXI6IGluY3JlYXNpbmcgdGhlIGVmZmVjdCBzaXplIGFuZCBpbmNyZWFzaW5nIHRoZSBsZXZlbCBvZiBzaWduaWZpY2FuY2UgJFxhbHBoYSQuDQoNCiMjIDEuIEVmZmVjdCBTaXplIGFuZCBQb3dlcg0KVGhlIGNoYXJ0IGJlbG93IHN1bW1hcml6ZXMgdGhlIHBvd2VyIGZvciBkaWZmZXJlbnQgbGV2ZWxzIG9mIGVmZmVjdCBzaXplIChzbWFsbCwgbWVkaXVtLCBsYXJnZSkgdXNpbmcgMi1UYWlsZWQsIDEtU2FtcGxlICR0JC10ZXN0cyB3aXRoICRcYWxwaGEgPSAwLjA1JC4gTm90aWNlIGhvdyBsb3cgdGhlIHBvd2VyIGlzIGZvciBzbWFsbCBlZmZlY3Qgc2l6ZXMgKGxlZnQgY29sdW1uKSBldmVuIGZvciBzYW1wbGUgc2l6ZXMgb2YgMTAwLiBPbiB0aGUgb3RoZXIgaGFuZCwgY29uc2lkZXIgdGhhdCB3ZSBoYXZlIGV4Y2VsbGVudCBwb3dlciBmb3Igc2FtcGxlcyBvZiBvbmx5IDIwIGlmIHRoZSBlZmZlY3Qgc2l6ZSBpcyBsYXJnZSAocmlnaHQgY29sdW1uKS4NCg0KYGBge3IgZWNobyA9IEZBTFNFfQ0KIyBDcmVhdGUgYSAxMHg0IGRhdGEgZnJhbWUgY2FsbGVkIFAgYW5kIGZpbGwgaXQgd2l0aCB6ZXJvcw0KIw0KTiA9IDEwDQp0ZW1wID0gTio0DQpQID0gZGF0YS5mcmFtZShtYXRyaXgoMTp0ZW1wLG5jb2wgPSA0KSkgICAjIENyZWF0ZSAxMHg0IHRhYmxlDQpQID0gUCAqMEwNCiMNCiMgQ3JlYXRlIGxhYmVscyBmb3IgdGhlIGNvbHVtbnMgb2YgUA0KIw0KY29sbmFtZXMoUCkgPSBjKCJuIiwgIlB3ciBpZiBkID0gMC4yIiwgIlB3ciBpZiBkID0gMC41IiwgIlB3ciBpZiBkID0gMC44IikNCiMNCiMgUnVuIENvaGVuJ3MgcG93ZXIgY2FsY3VsYXRpb25zICgybmQsIDNyZCBhbmQgNHRoIGNvbHVtbnMgaW4gUCkNCiMNClAkbiA9IDEwKjE6Tg0KZm9yIChrIGluIDE6bGVuZ3RoKFAkbikpIHsNCiAgUFtrLDJdID0gcm91bmQocHdyLnQudGVzdChuID0gayoxMCwgZCA9IDAuMiwgdHlwZSA9ICJvbmUuc2FtcGxlIikkcG93ZXIsMikNCn0NCmZvciAoayBpbiAxOmxlbmd0aChQJG4pKSB7DQogIFBbaywzXSA9IHJvdW5kKHB3ci50LnRlc3QobiA9IGsqMTAsIGQgPSAwLjUsIHR5cGUgPSAib25lLnNhbXBsZSIpJHBvd2VyLDIpDQp9DQpmb3IgKGsgaW4gMTpsZW5ndGgoUCRuKSkgew0KICBQW2ssNF0gPSByb3VuZChwd3IudC50ZXN0KG4gPSBrKjEwLCBkID0gMC44LCB0eXBlID0gIm9uZS5zYW1wbGUiKSRwb3dlciwyKQ0KfQ0KUA0KYGBgDQoNCiMjIDIuIExldmVsIG9mIFNpZ25pZmljYW5jZSAkKFxhbHBoYSkkIGFuZCBQb3dlcg0KDQpUaGUgY2hhcnQgYmVsb3cgc3VtbWFyaXplcyB0aGUgcG93ZXIgZm9yIGRpZmZlcmVudCBsZXZlbHMgb2YgJFxhbHBoYSQgdXNpbmcgMi1UYWlsZWQsIDEtU2FtcGxlICR0JC10ZXN0cyB3aXRoIGVmZmVjdCBzaXplcyAkZCA9IDAuMzAkLiBOb3RpY2UgaG93IGxvdyB0aGUgcG93ZXIgaXMgZm9yIHNtYWxsIGxldmVscyBvZiBzaWduaWZpY2FuY2UgKGxlZnQgY29sdW1uKSBldmVuIGZvciBzYW1wbGUgc2l6ZXMgb2YgMTAwLiBUaGUgcG93ZXIgaXMgbXVjaCBiZXR0ZXIgZm9yIGhpZ2hlciBsZXZlbHMgb2Ygc2lnbmlmaWNhbmNlLg0KDQpgYGB7ciBlY2hvID0gRkFMU0V9DQojIENyZWF0ZSBhIDEweDQgZGF0YSBmcmFtZSBjYWxsZWQgUCBhbmQgZmlsbCBpdCB3aXRoIHplcm9zDQojDQpOID0gMTANCnRlbXAgPSBOKjQNClAgPSBkYXRhLmZyYW1lKG1hdHJpeCgxOnRlbXAsbmNvbCA9IDQpKSAgICMgQ3JlYXRlIDEweDQgdGFibGUNClAgPSBQICowTA0KIw0KIyBDcmVhdGUgbGFiZWxzIGZvciB0aGUgY29sdW1ucyBvZiBQDQojDQpjb2xuYW1lcyhQKSA9IGMoIm4iLCAiUHdyIGlmIGFscGhhID0gMC4wMSIsICJQd3IgaWYgYWxwaGEgPSAwLjA1IiwgIlB3ciBpZiBhbHBoYSA9IDAuMTAiKQ0KIw0KIyBSdW4gQ29oZW4ncyBwb3dlciBjYWxjdWxhdGlvbnMgKDJuZCwgM3JkIGFuZCA0dGggY29sdW1ucyBpbiBQKQ0KIw0KUCRuID0gMTAqMTpODQpmb3IgKGsgaW4gMTpsZW5ndGgoUCRuKSkgew0KICBQW2ssMl0gPSByb3VuZChwd3IudC50ZXN0KG4gPSBrKjEwLCBkID0gMC4zLCB0eXBlID0gIm9uZS5zYW1wbGUiLCBzaWcubGV2ZWwgPSAwLjAxKSRwb3dlciwyKQ0KfQ0KZm9yIChrIGluIDE6bGVuZ3RoKFAkbikpIHsNCiAgUFtrLDNdID0gcm91bmQocHdyLnQudGVzdChuID0gayoxMCwgZCA9IDAuMywgdHlwZSA9ICJvbmUuc2FtcGxlIiwgc2lnLmxldmVsID0gMC4wNSkkcG93ZXIsMikNCn0NCmZvciAoayBpbiAxOmxlbmd0aChQJG4pKSB7DQogIFBbayw0XSA9IHJvdW5kKHB3ci50LnRlc3QobiA9IGsqMTAsIGQgPSAwLjMsIHR5cGUgPSAib25lLnNhbXBsZSIsIHNpZy5sZXZlbCA9IDAuMTApJHBvd2VyLDIpDQp9DQpQDQpgYGANCg0KDQojIyAzLiBPdmVycG93ZXJpbmcgU3RhdGlzdGljYWwgVGVzdA0KDQpPZGRseSwgeW91IGNhbiBoYXZlIHRvbyBtdWNoIHBvd2VyLiBXaGVuIHNhbXBsZSBzaXplcyBhcmUgcmlkaWN1bG91c2x5IGxhcmdlLCBhbG1vc3QgYW55IG1pbmlzY3VsZSBlZmZlY3Qgc2l6ZSB3aWxsIGJlIGVub3VnaCB0byByZWplY3QgdGhlIG51bGwuIFlldCwgdGhlIHJlc3VsdHMgd2lsbCBiZSBtZWFuaW5nbGVzcyBiZWNhdXNlIG5vIHJlYWwtd29ybGQgZGlmZmVyZW5jZSBiZXR3ZWVuIGdyb3VwcyBleGlzdHMuDQoNCkNvbnNpZGVyIGEgdHdvLXNhbXBsZSBjb21wYXJpc29uIG9mIHRlc3Qgc2NvcmVzIHdoZXJlIHRoZSBhdmVyYWdlIFRyZWF0bWVudCBncm91cCBzY29yZSBpcyBhbiA4MC4xLCBhbmQgdGhlIGF2ZXJhZ2UgQ29udHJvbCBncm91cCBzY29yZSBpcyBhbiA4MC4wLiBJZiB0aGUgc3RhbmRhcmQgZGV2aWF0aW9ucyBhcmUgYm90aCAxMCwgdGhlbiBDb2hlbidzIGVmZmVjdCBzaXplIGlzIA0KJCRkID0gXGZyYWN7ODAuMS04MC4wfXsxMH09XGZyYWN7LjF9ezEwfT0wLjAxJCQNCldlIGNhbiBhbGwgYWdyZWUgdGhhdCB3aXRoIHRlc3Qgc2NvcmVzIG91dCBvZiAxMDAgcG9pbnRzLCB0aGVyZSBpcyBubyByZWFsLXdvcmxkIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgVHJlYXRtZW50IGFuZCBDb250cm9sIGdyb3Vwcy4gWWV0LCBjb25zaWRlciB0aGUgZm9sbG93aW5nIHNhbXBsZSBzaXplcw0KDQojIyMgUG93ZXIgd2hlbiAkbiA9IDEwMDAkDQoNCmBgYHtyfQ0KcHdyLnQudGVzdChuID0gMTAwMCwgZCA9IDAuMDEsIHR5cGUgPSAidHdvLnNhbXBsZSIpJHBvd2VyDQpgYGANCkEgdmVyeSBsYXJnZSBzYW1wbGUgc2l6ZSwgYnV0IG5vdCBtdWNoIHBvd2VyLiBUaGlzIHNlZW1zIGZpbmUgYXMgd2Ugc2hvdWxkbid0IGJlIHJlamVjdGluZyB0aGUgbnVsbC4NCg0KIyMjIFBvd2VyIHdoZW4gJG4gPSAxMCwwMDAkDQoNCmBgYHtyfQ0KcHdyLnQudGVzdChuID0gMTAwMDAsIGQgPSAwLjAxLCB0eXBlID0gInR3by5zYW1wbGUiKSRwb3dlcg0KYGBgDQpBIGh1Z2Ugc2FtcGxlIHNpemUgYnV0IHN0aWxsIGhhcmRseSBhbnkgcG93ZXIuIEdvb2Qgc28gZmFyLg0KDQojIyMgUG93ZXIgd2hlbiAkbiA9IDEwMCwwMDAkDQoNCmBgYHtyfQ0KcHdyLnQudGVzdChuID0gMTAwMDAwLCBkID0gMC4wMSwgdHlwZSA9ICJ0d28uc2FtcGxlIikkcG93ZXINCmBgYA0KV2hvYSAtIG5vdyB3ZSBoYXZlIGEgcmVhc29uYWJsZSBjaGFuY2Ugb2YgcmVqZWN0aW5nIHRoZSBudWxsLg0KDQojIyMgUG93ZXIgd2hlbiAkbiA9IDEsMDAwLDAwMCQNCg0KYGBge3J9DQpwd3IudC50ZXN0KG4gPSAxMDAwMDAwLCBkID0gMC4wMSwgdHlwZSA9ICJ0d28uc2FtcGxlIikkcG93ZXINCmBgYA0KV2l0aCBhIHJpZGljdWxvdXMgc2FtcGxlIHNpemUgb2Ygb25lIG1pbGxpb24sIHdlIHdpbGwgYWx3YXlzIGJlIHJlamVjdGluZyB0aGUgbnVsbCBkZXNwaXRlIHRoZSBmYWN0IHRoYXQgdGhlcmUgaXMgbm8gcmVhbC13b3JsZCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGdyb3VwIG1lYW5zLg0KDQojIyMgV29yZCBvZiBDYXV0aW9uDQoNCkdlbmVyYWxseSwgdGhlIGlzc3VlIG9mIG92ZXJwb3dlcmluZyBhIHRlc3QgaXNuJ3Qgb25lIHdlJ3JlIHdvcnJpZWQgYWJvdXQuIEFzIG1lbnRpb25lZCBhYm92ZSwgZGF0YSBpcyBvZnRlbiBib3RoIGRpZmZpY3VsdCBhbmQgZXhwZW5zaXZlIHRvIGNvbGxlY3QuIEhvd2V2ZXIsIGluIHRoZSBlcmEgb2YgYmlnIGRhdGEsIHdlIGNhbiBvZnRlbiBmaW5kIG1hc3NpdmUgZGF0YSBzZXRzIHJlYWRpbHkgYXZhaWxhYmxlIG9ubGluZS4gV2hpbGUgaW50ZXJlc3RpbmcgcmVzdWx0cyBjYW4gY2VydGFpbmx5IGJlIGRlcml2ZWQgZnJvbSBzdHVkeWluZyBodWdlIGRhdGEgc2V0cywgcmVzZWFyY2hlcnMgZG8gbmVlZCB0byBhc2sgdGhlbXNlbHZlcyB0aGUgcXVlc3Rpb246ICJJcyB0aGlzIGZpbmRpbmcgc2lnbmlmaWNhbnQsIG5vdCBzdGF0aXN0aWNhbGx5LCBidXQgaW4gdGhlIHJlYWwgd29ybGQgY29udGV4dCBvZiB0aGUgc3R1ZHk/IiANCg==