1 Introduction

This module focuses on the three most commonly used statistical tests in subsequent courses: the Wald, Score, and Likelihood Ratio tests. These three methods form the cornerstone of inference in parametric models, providing powerful and versatile approaches for testing hypotheses, constructing confidence intervals, and assessing model fit.

While rooted in the elegant framework of maximum likelihood estimation, each test offers a distinct geometric or algebraic perspective on the evidence against a null hypothesis. Understanding their theoretical foundations, comparative strengths, and intrinsic relationships is essential for mastering advanced statistical methodology and applying it correctly to complex data.

In this module, we will state formulation, assumptions, steps to perform these tests and explained by numerical examples with manual solution and verification using R.

2 Review of Likelihood Formulation and Estimation

In maximum likelihood estimation, we fit models by finding parameters that make the observed data most probable. This process naturally leads to three related methods for testing hypotheses such as the likelihood ratio, Wald, and score tests. Each test uses a different feature of the likelihood function, but all are rooted in the same principles of likelihood and asymptotic theory. This section reviews basics of maximum likelihood estimation and their asymptotic normality.

Likelihood Function

Let \(X_1, X_2, \dots, X_n\) be independent and identically distributed (i.i.d) random variables with probability density (or mass) function \(f(x_i; \boldsymbol{\theta})\), where \(\boldsymbol{\theta} = (\theta_1, \dots, \theta_p)^T\) is a \(p\)-dimensional parameter vector. The likelihood function is:

\[ L(\boldsymbol{\theta}) = \prod_{i=1}^n f(x_i; \boldsymbol{\theta}) \]

The log-likelihood function is:

\[ \ell(\boldsymbol{\theta}) = \log L(\boldsymbol{\theta}) = \sum_{i=1}^n \log f(x_i; \boldsymbol{\theta}) \]

Maximum Likelihood Estimation

The maximum likelihood estimator (MLE) \(\hat{\boldsymbol{\theta}}\) satisfies:

\[ \hat{\boldsymbol{\theta}} = \arg\max_{\boldsymbol{\theta}} \ell(\boldsymbol{\theta}) \]

Under regularity conditions, \(\hat{\boldsymbol{\theta}}\) is obtained by solving the score equations:

\[ U(\boldsymbol{\theta}) = \frac{\partial \ell(\boldsymbol{\theta})}{\partial \boldsymbol{\theta}} = \boldsymbol{0} \]

Fisher Information Matrix

The Fisher information matrix of \(\theta\) based on an entire sample with size \(n\) is given by:

\[ I_n(\boldsymbol{\theta}) = E\left[-\frac{\partial^2 \ell(\boldsymbol{\theta})}{\partial \boldsymbol{\theta} \partial \boldsymbol{\theta}^T}\right] \]

The above (theoretical) Fisher information matrix requires integral that integrates variables out from the expression. In practice, we use the following observed information matrix:

\[ J_n(\boldsymbol{\theta}) = -\frac{\partial^2 \ell(\boldsymbol{\theta})}{\partial \boldsymbol{\theta} \partial \boldsymbol{\theta}^T} \]

Some software programs return Hessian matrix \(H_n( \boldsymbol{\theta}) = -J_n( \boldsymbol{\theta})\), that is

\[ H_n(\boldsymbol{\theta}) = \frac{\partial^2 \ell(\boldsymbol{\theta})}{\partial \boldsymbol{\theta} \partial \boldsymbol{\theta}^T} \]

Note that, in some textbooks, research articles and web postings, the Fisher Information Matrix based on single data point is denoted by \(I_0(\boldsymbol{\theta})\),

\[ I_n(\boldsymbol{\theta}) = n\times I_1(\boldsymbol{\theta}) \]

Under some regularity conditions and the null hypothesis \(H_0: \boldsymbol{\theta} = \boldsymbol{\theta}_0\), we have the following

\[ \sqrt{n}(\hat{\boldsymbol{\theta}} - \boldsymbol{\theta}_0) \xrightarrow{d} N(\boldsymbol{0}, I_1^{-1}(\boldsymbol{\theta}_0)). \]

The relationship between Fisher Information Matrix of \(\boldsymbol{\theta}\) and the variance of the MLE \(\hat{\boldsymbol{\theta}}\) is

\[ \text{var}(\hat{\boldsymbol{\theta}}) \approx I_n^{-1}(\boldsymbol{\theta}) = [n\times I_1(\boldsymbol{\theta})]^{-1} = \frac{I_1^{-1}(\boldsymbol{\theta})}{n} \] Therefore, we can rewrite the above asymptotic distribution of \(\boldsymbol{\theta}\) as

\[ \hat{\boldsymbol{\theta}}\to N\left( \boldsymbol{\theta}, \frac{I_1^{-1}(\boldsymbol{\theta})}{n} \right) \quad \text{or equivalently} \quad \hat{\boldsymbol{\theta}}\to N\left( \boldsymbol{\theta}, I_n^{-1}(\boldsymbol{\theta}) \right) \]

The diagonal elements in the covariance \(I_n^{-1}(\boldsymbol{\theta})\) represent the variance of the corresponding parameters in \(\hat{\boldsymbol{\theta}} = (\hat{\theta}_1, \hat{\theta}_2, \cdots, \hat{\theta_k})\). For example. $(_1) = $ the first element in the main diagonal of the inverse of the fisher information matrix based on the entire sample.

For example, let \(\boldsymbol{\theta} =(\theta_1, \theta_2)\), the corresponding MLE is \(\hat{\boldsymbol{\theta}} =(\hat{\theta_1}, \hat{\theta_2)}\). Let the observed Fisher information matrix be

\[ J_n(\boldsymbol{\theta}) = -\frac{\partial^2 \ell(\boldsymbol{\theta})}{\partial \boldsymbol{\theta} \partial \boldsymbol{\theta}^T}=-\begin{pmatrix} \frac{\partial^2 \ell(\boldsymbol{\theta})}{\partial^2 \theta_1} & \frac{\partial^2 \ell(\boldsymbol{\theta})}{\partial \theta_1\partial \theta_2} \\ \frac{\partial^2 \ell(\boldsymbol{\theta})}{\partial \theta_2\partial \theta_1} & \frac{\partial^2 \ell(\boldsymbol{\theta})}{\partial^2 \theta_2} \end{pmatrix} \]

The estimated Fisher information matrix is given by

\[ \widehat{J_n(\boldsymbol{\theta})} = -\begin{pmatrix} \frac{\partial^2 \ell(\boldsymbol{\theta})}{\partial^2 \theta_1} & \frac{\partial^2 \ell(\boldsymbol{\theta})}{\partial \theta_1\partial \theta_2} \\ \frac{\partial^2 \ell(\boldsymbol{\theta})}{\partial \theta_2\partial \theta_1} & \frac{\partial^2 \ell(\boldsymbol{\theta})}{\partial^2 \theta_2} \end{pmatrix}\Bigg|_{\boldsymbol{\theta} = \hat{\boldsymbol{\theta}}}. \]

Note that R function optim() returns Hessian matrix \(\widehat{H_n(\boldsymbol{\theta})}=- \widehat{J_n(\boldsymbol{\theta})}\).

Let the inverse of \(widehat{J_n(\boldsymbol{\theta})}\) be of the following form

\[ \left[\widehat{J_n(\boldsymbol{\theta})}\right]^{-1} = -\left[\begin{pmatrix} \frac{\partial^2 \ell(\boldsymbol{\theta})}{\partial^2 \theta_1} & \frac{\partial^2 \ell(\boldsymbol{\theta})}{\partial \theta_1\partial \theta_2} \\ \frac{\partial^2 \ell(\boldsymbol{\theta})}{\partial \theta_2\partial \theta_1} & \frac{\partial^2 \ell(\boldsymbol{\theta})}{\partial^2 \theta_2} \end{pmatrix}\Bigg|_{\boldsymbol{\theta} = \hat{\boldsymbol{\theta}}}\right]^{-1} =\begin{pmatrix} a & c \\ c & d \end{pmatrix}. \]

Then we have

\[ \widehat{\text{var}(\hat{\boldsymbol{\theta})}} \approx \begin{pmatrix} a & c \\ c & d \end{pmatrix}. \]

That is,

\[ \text{var}(\hat{\theta}_1) \approx a, \quad \text{var}(\hat{\theta}_2) \approx d, \quad \text{and} \quad \text{cov}(\hat{\theta}_1, \hat{\theta}_2) \approx c. \]

The above asymptotic normality is the foundation of the Wald and Score tests.


3 The Three Asymptotic \(\chi^2\) Tests

At the foundation of parametric hypothesis testing lies a trio of asymptotically equivalent methods: the likelihood ratio, Wald, and score tests. All three derive from maximum likelihood theory and converge to the same chi-squared distribution under the null hypothesis, yet they approach the problem of testing from meaningfully different angles.

The likelihood ratio test directly compares the goodness-of-fit between the unrestricted model and the model constrained by the null hypothesis. The Wald test evaluates the distance between the estimated parameter vector and its hypothesized value, standardized by the estimated curvature of the likelihood. The score test, alternatively, examines whether the slope of the log-likelihood at the null parameter value is sufficiently close to zero—an indication that the null point is a plausible maximum.

Despite their asymptotic equivalence, these tests differ in computation, finite-sample performance, and invariance properties, leading to practical trade-offs in applied work. The following sub-sections develop their formulations, contrasts their theoretical and practical attributes, and provide guidance for choosing among them in statistical modeling.

3.1 Wald Test

Formulation Tests the distance between the unconstrained MLE and the hypothesized value. It measures geometric displacement from \(H_0\) in parameter space. To make it simple, let’s \(\boldsymbol{\theta} = (\theta_1, \theta_2)\) be the vector of the parameters of a distribution. Consider hypothesis

\[ H_0: \boldsymbol{\theta} = \boldsymbol{\theta}_0, \quad \text{i.e.}\quad \begin{pmatrix} \theta_1 \\ \theta_2 \end{pmatrix} = \begin{pmatrix} \theta_{10} \\ \theta_{20} \end{pmatrix}. \]

The difference between the hypothesized value and the unrestricted MLE is given by

\[ D = \hat{\boldsymbol{\theta}} - \boldsymbol{\theta}_0 = \begin{pmatrix} \hat{\theta}_1 -\theta_{10} \\ \hat{\theta}_2 -\theta_{20} \end{pmatrix} \]

Test Statistic

With the above notations, the Wald test statistic is given by

\[ W = \hat{D}^{T} \, \left[ \widehat{\text{var}(\hat{\boldsymbol{\theta}})}\right]^{-1} \, \hat{D} = \hat{D}^{T} \,\text{I}_n(\hat{\boldsymbol{\theta}}) \, \hat{D} \]

More explicitly, we have

\[ W = \begin{pmatrix} \hat{\theta}_1 - \theta_{10} & \hat{\theta}_2 - \theta_{20} \end{pmatrix} \begin{pmatrix} \text{var}(\hat{\theta}_1) & \text{cov}(\hat{\theta}_1, \hat{\theta}_2) \\ \text{cov}(\hat{\theta}_1, \hat{\theta}_2) & \text{var}(\hat{\theta}_2) \end{pmatrix}^{-1} \begin{pmatrix} \hat{\theta}_1 - \theta_{10} \\ \hat{\theta}_2 - \theta_{20} \end{pmatrix}. \]

For testing single parameter case \(H_0: \boldsymbol{\theta}_1 = \boldsymbol{\theta}_{10}\)

\[ W = (\hat{\theta} - \theta_0)[\text{var}(\hat{\theta}_1)]^{-1}(\hat{\theta} - \theta_0) = \frac{(\hat{\theta} - \theta_0)^2}{\text{var}(\hat{\theta}_1)} \]

Asymptotic Distribution: \(W \xrightarrow{d} \chi^2_q\) under \(H_0\), where \(q\) is the number of parameters specified under the null hypothesis.

In the two-parameter and one-parameter cases described above, the degrees of freedom of the \(\chi^2\) test are \(q = 2\) and \(q=1\), respectively.

Assumptions: Wald test requires only the unconstrained MLE (as well as Information matrix to derive the covariance matrix of the MLE) and is sensitive to parameterization.

3.2 Score Test (Rao’s Score Test)

Rao’s score is also known as the Lagrange multiplier test.

Formulation: Tests whether the score at the null hypothesis is significantly different from zero. It measures local gradient at \(H_0\) in likelihood space.

Test Statistic:

\[ S = U(\tilde{\boldsymbol{\theta}})^T I_n^{-1}(\tilde{\boldsymbol{\theta}}) U(\tilde{\boldsymbol{\theta}}) \] where \(\tilde{\boldsymbol{\theta}}\) is the MLE under \(H_0\) (constrained MLE).

Asymptotic Distribution: \(S \xrightarrow{d} \chi^2_q\) under \(H_0\).

Assumptions: Requires only the constrained MLE. Invariant to reparameterization.

3.3 Likelihood Ratio Test

Formulation: Compares the maximized log-likelihood under \(H_0\) and \(H_1\). It measures information loss when imposing \(H_0\).

Test Statistic:

\[ \Lambda = -2[\ell(\tilde{\boldsymbol{\theta}}) - \ell(\hat{\boldsymbol{\theta}})] = 2[\ell(\hat{\boldsymbol{\theta}}) - \ell(\tilde{\boldsymbol{\theta}})] \]

Asymptotic Distribution: \(\Lambda \xrightarrow{d} \chi^2_q\) under \(H_0\).

Assumptions: Requires both constrained and unconstrained MLEs. Invariant to reparameterization.


4 Practical Examples: Single Parameter

To concretely demonstrate the similarities and differences among the three likelihood-based tests, we now turn to practical implementation in R. While these tests often yield similar conclusions with large samples, their distinctions become particularly instructive when examining simple yet fundamental distributions.

Through hands-on examples using Poisson and normal distributions, we will systematically apply the Likelihood Ratio, Wald, and Score tests to identical hypotheses. This comparative approach will illuminate how each test statistic is calculated, showcase scenarios where their results diverge meaningfully, and provide reusable code templates that reveal the computational machinery underlying common statistical procedures.

Unlike t-tests and z-tests which have closed-form formulas, likelihood-based chi-squared tests require explicit derivation of the likelihood function, parameter estimation under null/alternative, and careful construction of the test statistics. This is why they’re more flexible but require more preparation. The key preparation steps required

  • Derive log-likelihood function \(\ell(\theta; x)\)
  • Derive score function \(U(\theta) = \partial \ell/\partial \theta\)
  • Derive Fisher Information \(I_n(\theta) = -E[\partial^2 \ell/\partial \theta^2]\)
  • Find MLEs under both \(H_0\) and \(H_1\)
  • Compute standard errors from inverse Fisher Information
  • Construct test statistics using appropriate formulas

Note that likelihood-based inferences rely on large-sample asymptotic theory. For the purpose of clearly illustrating the procedure, the examples in the following subsections will use small toy datasets.

4.1 Example 1: Poisson Distribution

Problem: Test \(H_0: \lambda = 2\) vs \(H_1: \lambda \neq 2\) for \(X_1, \dots, X_n \sim \text{Poisson}(\lambda)\).

Observed data: 3, 1, 4, 2, 3.

Manual Solution:

  • Likelihood: \(L(\lambda) = \prod_{i=1}^n \frac{e^{-\lambda} \lambda^{x_i}}{x_i!}\)

  • Log-likelihood: \(\ell(\lambda) = -n\lambda + (\sum x_i)\log\lambda - \sum \log(x_i!)\)

  • MLE: \(\hat{\lambda} = \bar{x} = \frac{3+1+4+2+3}{5} = 2.6\)

  • Score function: \(U(\lambda) = \frac{d\ell}{d\lambda} = -n + \frac{\sum x_i}{\lambda}\)

  • Information: \(I_n(\lambda) = \frac{n}{\lambda}\) (expected), \(J_n(\lambda) = \frac{\sum x_i}{\lambda^2}\) (observed)

Wald Test

\[ W = (\hat{\lambda} - \lambda_0)^2 \hat{I}_n(\hat{\lambda}) = (2.6 - 2)^2 \times \frac{5}{2.6} = 0.36 \times 1.923 = 0.692 \] Using observed information: \(W = (0.6)^2 \times \frac{13}{2.6^2} = 0.36 \times 1.923 = 0.692\)

Score Test

Score at \(\lambda_0=2\): \(U(2) = -5 + \frac{13}{2} = 1.5\)

\[ I(2) = \frac{5}{2} = 2.5 \]

\[ S = U(2)^2 I_n^{-1}(2) = (1.5)^2 \times \frac{1}{2.5} = 2.25 \times 0.4 = 0.9 \]

Likelihood Ratio Test

\[ \ell(\hat{\lambda}) = -5(2.6) + 13\log(2.6) - \sum \log(x_i!) = -13 + 13(0.9555) - \log(1728) \approx -8.0335 \]

\[ \ell(\lambda_0) = -5(2) + 13\log(2) - \sum \log(x_i!) = -10 + 13(0.6931) - 7.455 \approx -8.4447 \]

\[ \Lambda = 2[-8.0335 - (-8.4447)] = 2(0.4112) = 0.8224 \]

Conclusion All test statistics are approximately between 0.7 and 0.9. Since all three test statistics are less than the critical value \(\chi^2_{1,0.05} = 3.841\), we fail to reject \(H_0\).

R Verification

# Poisson example
x <- c(3, 1, 4, 2, 3)
n <- length(x)

# MLE
lambda_mle <- mean(x)

# Wald test
se_wald <- sqrt(lambda_mle/n)
W <- ((lambda_mle - 2)/se_wald)^2

# Score test
U <- -n + sum(x)/2
I <- n/2
S <- U^2/I

# Likelihood ratio test
ll_mle <- sum(dpois(x, lambda_mle, log = TRUE))
ll_null <- sum(dpois(x, 2, log = TRUE))
LR <- 2*(ll_mle - ll_null)

cat("  Wald:", W, "p-value:", 1-pchisq(W, 1), "\n",
    "Score:", S, "p-value:", 1-pchisq(S, 1), "\n",
    "   LR:", LR, "p-value:", 1-pchisq(LR, 1), "\n")
  Wald: 0.6923077 p-value: 0.4053806 
 Score: 0.9 p-value: 0.3427817 
    LR: 0.8214709 p-value: 0.3647505 

4.2 Example 2: Normal Distribution Mean Test

Problem Test \(H_0: \mu = 10\) vs \(H_1: \mu \neq 10\) for \(X_i \sim N(\mu, \sigma^2)\), where \(\sigma^2 = 0.1\).

Data: 10.2, 9.8, 10.0, 10.2, 9.9.

Manual Solution

  • Likelihood: \(L(\mu) = (2\pi\sigma^2)^{-n/2} \exp\left\{-\frac{1}{2\sigma^2} \sum_{i=1}^n (x_i - \mu)^2\right\}\).

  • Log-likelihood: \(\ell(\mu) = \log L(\mu) = -\frac{n}{2}\log(2\pi\sigma^2) - \frac{1}{2\sigma^2} \sum_{i=1}^n (x_i - \mu)^2\)

  • Score Equation: \(S(\mu) = \frac{\partial \ell(\mu)}{\partial \mu} = \frac{1}{\sigma^2} \sum_{i=1}^n (x_i - \mu)\)

  • MLE \(\hat{\mu} = \bar{x} = \frac{1}{n} \sum_{i=1}^n x_i = \frac{10.2+9.8+10.0+10.2+9.9}{5} = 10.02\)

  • Information \(I(\mu) = -\frac{\partial^2 \ell(\mu)}{\partial \mu^2} = \frac{n}{\sigma^2} = \frac{5}{0.1} = 50\)

With the above manual work, we next define the three test statistic:

Wald Test

\[ W = (\hat{\mu} - \mu_0)^2 I(\hat{\mu}) = (0.02)^2 \times 50 = 0.0004 \times 50 = 0.02 \]

Score Test

\[ U(\mu) = \frac{n}{\sigma^2}(\bar{x} - \mu) \]

At \(\mu_0=10\): \(U(10) = 50 \times (10.02 - 10) = 1\)

\[ S = U(10)^2 I^{-1}(10) = 1^2 \times \frac{1}{50} = 0.02 \]

Likelihood Ratio Test

\[ \ell(\mu) = -\frac{n}{2}\log(2\pi\sigma^2) - \frac{1}{2\sigma^2}\sum(x_i - \mu)^2 \]

\[ \ell(\mu_0) = -\frac{n}{2}\log(2\pi\sigma^2) - \frac{1}{2\sigma^2}\sum(x_i - \mu_0)^2 \]

\[ \ell(\hat{\mu}) - \ell(\mu_0) = -\frac{1}{2\sigma^2}[\sum(x_i - \hat{\mu})^2 - \sum(x_i - \mu_0)^2] \]

\[ = -\frac{1}{0.2}[0.13 - 0.128] = -5 \times 0.002 = -0.01 \]

\[ \Lambda = 2 \times 0.01 = 0.02. \]


R Verification

# Normal example
x <- c(10.2, 9.8, 10.0, 10.2, 9.9)
n <- length(x)
sigma2 <- 0.1
mu0 <- 10

mu_mle <- mean(x)

# Wald test
W <- (mu_mle - mu0)^2 * (n/sigma2)   # Wald test statistic

# Score test
U <- (n/sigma2) * (mu_mle - mu0)
I <- n/sigma2
S <- U^2/I    # Rao test statistic

# Likelihood ratio test
ll_mle <- sum(dnorm(x, mu_mle, sqrt(sigma2), log = TRUE))  # log = TRUE yields log-likelihood
ll_null <- sum(dnorm(x, mu0, sqrt(sigma2), log = TRUE))
LR <- 2*(ll_mle - ll_null)    # log-likelihood ratio test statistic

cat("  Wald:", W, "p-value:", 1-pchisq(W, 1), "\n",
    "Score:", S, "p-value:", 1-pchisq(S, 1), "\n",
    "   LR:", LR, "p-value:", 1-pchisq(LR, 1), "\n")
  Wald: 0.02 p-value: 0.8875371 
 Score: 0.02 p-value: 0.8875371 
    LR: 0.02 p-value: 0.8875371 


5 Practical Example: Multiple Parameters

In the single-parameter case, the Fisher information number is relatively straightforward to derive. For multi-parameter cases, however, we need to obtain the Fisher information matrix in order to conduct both the Wald and score tests. This section uses the Weibull distribution as an example to illustrate the procedure for the three chi-square tests.

5.1 Components for the Three \(\chi^2\) Tests

In this subsection, we use the gamma distribution as an example to illustrate how to test the significance of parameters. Since the gamma distribution is commonly expressed in two distinct formulations, we adopt the following parameterization.

The gamma distribution with shape parameter \(\alpha > 0\) and rate parameter \(\beta > 0\) has probability density function:

\[ f(x; \alpha, \beta) = \frac{\beta^{\alpha}}{\Gamma(\alpha)} x^{\alpha-1} e^{-\beta x}, \quad x > 0 \]

The case where the shape parameter \(\alpha = 1\) reduces the gamma to an exponential distribution. Thus, testing this null hypothesis indicates whether the gamma distribution provides a significantly better fit or leads to overfitting for the given data.

Assume \(\{x_1, x_2, \cdots, x_n\} \xrightarrow{i.i.d} \text{gamma}(\alpha, \beta)\). \(\psi(\alpha)\) denotes the digamma function

\[ \psi(z) = \frac{d}{dz} \ln \Gamma(z) = \frac{\Gamma'(z)}{\Gamma(z)}. \]

R functions digamma(z), trigamma(z), tetragamma(z) evaluate \(\psi(x), \psi^\prime (z)\) and \(\psi^{\prime\prime}(z)\), respectively.

The objective is to test \(H_0: \alpha = 1\). The major components required for testing the hypothesis are given below.

Log-likelihood

\[ \ell(\alpha, \beta) = n\alpha\log\beta - n\log\Gamma(\alpha) + (\alpha-1)\sum_{i=1}^n \log x_i - \beta\sum_{i=1}^n x_i \]

Score Equations

\[ \frac{\partial\ell}{\partial\alpha} = n\log\beta - n\psi(\alpha) + \sum_{i=1}^n \log x_i = 0 \]

\[ \frac{\partial\ell}{\partial\beta} = \frac{n\alpha}{\beta} - \sum_{i=1}^n x_i = 0 \]

Maximum Likelihood Estimation

The maximum likelihood estimates of \(\alpha\) and \(\beta\), denoted by \(\hat{\alpha}\) and \(\hat{\beta}\), are the solutions to the above system of score equations.


Information Matrix

\(\mathcal{I}_n(2,2)\) is the (2,2) element of the Fisher information matrix of \(\alpha\) and \(\beta\) based on entire sample with size \(n\):

\[ \mathcal{I}_n(\alpha, \beta) = - E\begin{pmatrix} \frac{\partial^2\ell}{\partial \alpha^2} & \frac{\partial^2\ell}{\partial\alpha\partial\beta} \\ \frac{\partial^2\ell}{\partial\beta\partial\alpha}& \frac{\partial^2\ell}{\partial\beta^2} \end{pmatrix} = -\begin{pmatrix} n\psi'(\alpha) & \frac{n}{\beta} \\ \frac{n}{\beta} & \frac{n\alpha}{\beta^2} \end{pmatrix} \]

Remark: For the likelihood ratio test, we must obtain both the restricted and unrestricted maximum likelihood estimates (MLEs). The restricted MLE is derived under the null hypothesis \(H_0: \alpha = 1\) (i.e., \(\alpha\) fixed to a constant), while the unrestricted MLE treats both \(\alpha\) and \(\beta\) as unknown parameters. In general, these MLEs must be obtained using numerical approximation methods.

5.2 Numerical Implementation

The dataset used in this example contains measurements of microtubule catastrophe times (the time until a microtubule stops growing). In their Cell paper (2011), Gardner, Zanic, and colleagues (Gardner, Zanic, et al. (2011). Cell, 147(5), 1092-1103.) explicitly modeled these catastrophe times using a gamma distribution. For illustrative purpose, we only use complete times in this example.

We first load the data into R and then follow the steps above to perform the three likelihood-based \(\chi^2\) tests.

time2event <- read.table("https://pengdsci.github.io/STA506/w11/Time2Catastrophe.txt")
colnames(time2event) <- "time"
x <- time2event$time

Loglikelihood function

The following R function evaluate the loglikelihood function and will be used to find the unrestricted MLE of \(\alpha\) and \(\beta\).

# loglikelihood function
log_likelihood <- function(param) {
  alpha <- param[1] 
  beta <- param[2]
  n <- length(x)
  sum_x <- sum(x)
  sum_logx <- sum(log(x))
  ##
  ll <- n * alpha * log(beta) - n * log(gamma(alpha)) + 
         (alpha - 1) * sum_logx - beta * sum(x)
  ll
}

Score Equations: The following R function returns a vector score functions, computed from the data values and parameter estimates.

# Score equations (should be zero at solution)
score_equ <-function(par){
    alpha <- par[1]
    beta <- par[2]
    ##
    n <- length(x)
    sum_x <- sum(x)
    sum_logx <- sum(log(x))
    ##
    score_alpha <- n * log(beta) - n * digamma(alpha) + sum_logx
    score_beta <- n * alpha / beta - sum_x
    c(score_alpha, score_beta)
  }

Fisher Information Matrix is coded in the following

FisherInfo <- function(par){
    # Fisher information matrix (negative expected Hessian)
    # Used for Newton-Raphson update
    # It contains only parameters
    alpha <- par[1]
    beta <- par[2]
    
    # Fisher Info cell
    I_11 <- n * trigamma(alpha)
    I_12 <- -n / beta
    I_22 <- n * alpha / beta^2
    
    # Information matrix
    Fisher <- matrix(c(I_11, I_12, I_12, I_22), nrow = 2, byrow = TRUE)
    Fisher   
}

5.3 Maximum Likelihood Estimation

Instead of relying on special built-in R functions that compute maximum likelihood estimates (MLEs) for specific distribution families, we introduce a general purpose optimization function optim() for obtaining MLEs for arbitrary distributions. Specifically, we will derive the MLEs of the parameters \(\alpha\) and \(\beta\), along with the corresponding Fisher information matrix, which will be used in the Score and Wald tests.

optim() is a wrapper function that provides access to several optimization algorithms. The specific numerical method invoked internally depends on the information supplied to the function. In practice, a popular variant of the Newton–Raphson algorithm known as the Broyden–Fletcher–Goldfarb–Shanno (BFGS) algorithm is frequently employed. BFGS requires the gradient (score vector) to efficiently guide the search toward the optimal solution. The following R code illustrates how to use the BFGS method via optim().

 x <- time2event$time
 n = length(x)
 # initial values
###
 result <- optim(
          par = c(100,0.1), 
          #need to provide initial values to start the iteration.
                                    # Choosing appropriate initial values is critical.
          fn = log_likelihood,      # Caution: need negative log-likelihood
          gr = score_equ,           # also nee negative score
          method = "BFGS",          # calling BFGS algorithm
          hessian = TRUE,           # return Hessian matrix
          control = list(           # some controls in numerical iteration
                fnscale = -1,       # turn the minimization to maximization problem
                maxit = 1000,       # stopping rule 1: cap number of iterations
                reltol = 1e-8,      # stopping rule: precision control
                REPORT = 10         # The algorithm will print progress updates 
                                    # every 10 iterations
          )
  )
 result
$par
[1] 2.407544212 0.005462866

$value
[1] -1458.997

$counts
function gradient 
      91       20 

$convergence
[1] 0

$message
NULL

$hessian
           [,1]         [,2]
[1,]  -108.2844     38844.57
[2,] 38844.5676 -17612367.12

Double check with the hessian matrix using the derived formula

Fisher <- FisherInfo(result$par)
Fisher
            [,1]        [,2]
[1,]    108.2844   -38624.41
[2,] -38624.4144 17022197.79

Which is consistent with the hessian matrix in the output of optim().

The variance and covariance matrix can be approximated by inverting the Fisher Information Matrix or the inverse of the negative Hessian matrix returned from optim().

varcov <- solve(-result$hessian)   # solve() is a matrix inversion function
varcov
             [,1]         [,2]
[1,] 4.422498e-02 9.753942e-05
[2,] 9.753942e-05 2.719042e-07

That is, \(\text{var}(\alpha) = 4.42\times 10^{-2}\) and \(\text{var}(\beta) = 2.72\times 10^{-7}\).

5.4 Two \(\chi^2\) Tests

The three \(\chi^2\) tests are given respectively in the following.

5.4.1 Likelihood Ratio Test

We have found the un-restrictive MLEs of \(\alpha\) and \(\beta\):

MLE <- result$par
MLE
[1] 2.407544212 0.005462866

We now find restrictive MLE of \(\beta\) under \(H_0: \alpha = 1\). The optimization problems becomes single parameter problem.

##
loglik <- function(beta) n*log(beta)-n -beta*sum(x)
##
score <- function(beta) n/beta - sum(x)
##
 x <- time2event$time
 n = length(x)
 result0 <- optim(
          par = 0.05,             # need to provide initial values to start the iteration.
                                    # Choosing appropriate initial values is critical.
          fn = loglik,              # Caution: need negative log-likelihood
          gr = score,               # also nee negative score
          method = "BFGS",          # calling BFGS algorithm
          hessian = TRUE,           # return Hessian matrix
          control = list(           # some controls in numerical iteration
                fnscale = -1,       # turn the minimization to maximization problem
                maxit = 1000,       # stopping rule 1: cap number of iterations
                reltol = 1e-8,      # stopping rule: precision control
                REPORT = 10         # The algorithm will print progress updates 
                                    # every 10 iterations
          )
  )
 result0
$par
[1] 0.002269067

$value
[1] -1706.65

$counts
function gradient 
      42        7 

$convergence
[1] 0

$message
NULL

$hessian
          [,1]
[1,] -50859711

That is the restrictive MLE of \(\beta\), denoted by \(\hat{\beta}=0.002269067\).

The likelihood ratio test statistic is

\[ LR = −2[\ell(\hat{\alpha}, \hat{\beta})−\ell(1,\hat{\beta})] \to \chi^2_1. \]

The R code that evaluates the above test statistic is given by

 x <- time2event$time
 n = length(x)
 ##
 LR = -2*(loglik(result0$par) - log_likelihood(result$par))
 LR
[1] 495.3061

Since the chi-square test is always right-tailed, the p-value based on the test statistic above is given by \(p = P(\chi^2_1 > LR)\). The p-value can be obtained using the following R code.

pval <- 1 - pchisq(LR, df = 1)
pval
[1] 0

The p-value is nearly zero, leading to the rejection of the null hypothesis \(H_0: \alpha = 1\).

5.4.2 Wald \(\chi^2\) Test

The Wald \(\chi^2\) test statistics for the null hypothesis \(H_0: \alpha = 1\) is given by

\[ W_{\text{Wald}} = [\frac{\hat{\alpha} - 1}{\text{se}(\hat{\alpha})}]^2 = \frac{(\hat{\alpha}-1)^2}{\text{var}(\hat{\alpha})} \to \chi^2_1 \]

where \(\text{Var}(\hat{\alpha})\) is the diagonal element of the inverse of the observed Fisher information matrix (i.e., the variance–covariance matrix). This means that the Fisher information matrix is required for the Wald test.

Next, we define the test statistic and calculate the p-value using the following R code

alpha.hat  <- result$par[1]     # based on the unrestricted likelihood estimation
se.alpha <- sqrt(varcov[1, 1])  # the square root of the top-left diagonal value
W <- (alpha.hat - 1)^2/(se.alpha)^2   # Wald test statistic
##
pval.W <- 1 - pchisq(W, df = 1)
c(W = W, pval.W = pval.W)
           W       pval.W 
4.479778e+01 2.184708e-11 

The p-value is also near 0 implying the rejection of the null hypothesis.


6 Performance Comparison

At the heart of modern statistical inference lies a powerful trio: the Likelihood Ratio, Wald, and Score tests. Each provides a distinct lens for testing hypotheses, transforming the same likelihood function into a chi-squared statistic through different logical and geometrical principles. Their asymptotic equivalence provides a reassuring theoretical foundation, yet their finite-sample divergence reveals a rich landscape of statistical trade-offs, where the choice of test balances considerations of accuracy, convenience, invariance, and computational burden.

Core Performance Characteristics

  • Likelihood Ratio Test (LRT) - best overall performance in most situations
    • Accuracy: Most reliable in finite samples, closest to nominal Type I error rates
    • Robustness: Invariant to parameter transformations (unique advantage)
    • Conservatism: Slightly conservative in very small samples
    • Computation: Most intensive (requires fitting both models)
  • Wald Test - fastest but least reliable in non-ideal conditions
    • Accuracy: Can be poor in small samples, especially with:
      • Skewed likelihoods
      • Parameters near boundaries (variances, probabilities near 0/1)
      • Nonlinear parameters
    • Bias: Often anti-conservative (inflates Type I error)
    • Computation: Fastest (only needs full model)
  • Score Test (Rao)- efficient compromise with specific strengths
    • Accuracy: Good when null hypothesis is true, but can be inconsistent when alternative is true
    • Power: Sometimes less powerful than LRT in small samples
    • Computation: Moderate (only needs null model)
    • Special strength: Best for boundary testing and initial model building

General Recommendations

  • Use the LRT when:
    • Computational cost is not a concern.
    • Sample size is small to moderate.
    • when comparing nested models of general types (GLMs, mixed models, etc.).
  • Use the Wald Test when:
    • only having the unrestricted model output (e.g., from a standard regression summary).
    • Doing quick approximate inference or constructing confidence intervals.
    • The sample size is large and the likelihood is well-behaved (\(\approx\) quadratic).
    • Caution: Can be misleading for parameters like odds ratios (always exponentiate first, then form Wald CI on log scale).
  • Use the Score Test when:
    • The null model is simpler to fit (e.g., testing for an additional regressor in a large data set; only fit the reduced model).
    • In model checking and diagnostics (e.g., residuals tests).
    • When the MLE under the alternative is hard to obtain or at a boundary.

Logical Paradoxes and Resolutions

  • Paradox 1: “Wald can reject when LRT doesn’t”
    • Occurs when: Likelihood is highly non-quadratic
    • Logical explanation: Wald assumes symmetric CI based on curvature at MLE; LRT uses actual likelihood shape
    • Resolution: Trust LRT—it respects the true likelihood geometry
  • Paradox 2: “Score test more powerful than LRT”
    • Occurs when: Parameter at boundary, small samples
    • Logical explanation: Score uses exact null distribution; LRT uses asymptotic \(\chi^2\) approximation
    • Resolution: Use exact distributions or corrected LRT (50:50 mixture \(\chi^2\))
  • Paradox 3: “Tests disagree asymptotically”
    • Logical implication: Likely model misspecification or computational error
    • Resolution: Check model assumptions and numerical stability
LS0tDQp0aXRsZTogIldhbGQsIFNjb3JlIGFuZCBMaWtlbGlob29kIFJhdGlvIFRlc3RzIg0KYXV0aG9yOiAiQ2hlbmcgUGVuZyINCmRhdGU6ICJXZXN0IENoZXN0ZXIgVW5pdmVyc2l0eSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdG9jX2NvbGxhcHNlZDogeWVzDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgc21vb3RoX3Njcm9sbDogeWVzDQogICAgdGhlbWU6IGx1bWVuDQogIHBkZl9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICBmaWdfd2lkdGg6IDMNCiAgICBmaWdfaGVpZ2h0OiAzDQogIHdvcmRfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgZmlnX2NhcHRpb246IHllcw0KICAgIGtlZXBfbWQ6IHllcw0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lDQotLS0NCg0KYGBge2NzcywgZWNobyA9IEZBTFNFfQ0KI1RPQzo6YmVmb3JlIHsNCiAgY29udGVudDogIlRhYmxlIG9mIENvbnRlbnRzIjsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtc2l6ZTogMS4yZW07DQogIGRpc3BsYXk6IGJsb2NrOw0KICBjb2xvcjogbmF2eTsNCiAgbWFyZ2luLWJvdHRvbTogMTBweDsNCn0NCg0KDQpkaXYjVE9DIGxpIHsgICAgIC8qIHRhYmxlIG9mIGNvbnRlbnQgICovDQogICAgbGlzdC1zdHlsZTp1cHBlci1yb21hbjsNCiAgICBiYWNrZ3JvdW5kLWltYWdlOm5vbmU7DQogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOjA7DQp9DQoNCmgxLnRpdGxlIHsgICAgLyogbGV2ZWwgMSBoZWFkZXIgb2YgdGl0bGUgICovDQogIGZvbnQtc2l6ZTogMjJweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQogIGZvbnQtZmFtaWx5OiAiR2lsbCBTYW5zIiwgc2Fucy1zZXJpZjsNCn0NCg0KaDQuYXV0aG9yIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxNXB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6IHN5c3RlbS11aTsNCiAgY29sb3I6IG5hdnk7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDQuZGF0ZSB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiAiR2lsbCBTYW5zIiwgc2Fucy1zZXJpZjsNCiAgY29sb3I6IERhcmtCbHVlOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmgxIHsgLyogSGVhZGVyIDEgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDIwcHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoMiB7IC8qIEhlYWRlciAyIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE2cHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDQgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMTRweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KLyogQWRkIGRvdHMgYWZ0ZXIgbnVtYmVyZWQgaGVhZGVycyAqLw0KLmhlYWRlci1zZWN0aW9uLW51bWJlcjo6YWZ0ZXIgew0KICBjb250ZW50OiAiLiI7DQoNCmJvZHkgeyBiYWNrZ3JvdW5kLWNvbG9yOndoaXRlOyB9DQoNCi5oaWdobGlnaHRtZSB7IGJhY2tncm91bmQtY29sb3I6eWVsbG93OyB9DQoNCnAgeyBiYWNrZ3JvdW5kLWNvbG9yOndoaXRlOyB9DQoNCn0NCmBgYA0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiMgY29kZSBjaHVuayBzcGVjaWZpZXMgd2hldGhlciB0aGUgUiBjb2RlLCB3YXJuaW5ncywgYW5kIG91dHB1dCANCiMgd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGUgb3V0cHV0IGZpbGVzLg0KaWYgKCFyZXF1aXJlKCJrbml0ciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpDQogICBsaWJyYXJ5KGtuaXRyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJwYW5kZXIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygicGFuZGVyIikNCiAgIGxpYnJhcnkocGFuZGVyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJwc3ljaCIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInBzeWNoIikNCiAgbGlicmFyeShwc3ljaCkNCn0NCmlmICghcmVxdWlyZSgiUkNvbG9yQnJld2VyIikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygiUkNvbG9yQnJld2VyIikNCiAgbGlicmFyeShSQ29sb3JCcmV3ZXIpDQp9DQoNCmlmICghcmVxdWlyZSgiYm9vdCIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoImJvb3QiKQ0KICBsaWJyYXJ5KGJvb3QpDQp9DQppZiAoIXJlcXVpcmUoImVmZnNpemUiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJlZmZzaXplIikNCiAgbGlicmFyeShlZmZzaXplKQ0KfQ0KIyMgbGlicmFyeShlZmZzaXplKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCAgICAgICAjIGluY2x1ZGUgY29kZSBjaHVuayBpbiB0aGUgb3V0cHV0IGZpbGUNCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gRkFMU0UsICAgIyBzb21ldGltZXMsIHlvdSBjb2RlIG1heSBwcm9kdWNlIHdhcm5pbmcgbWVzc2FnZXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgeW91IGNhbiBjaG9vc2UgdG8gaW5jbHVkZSB0aGUgd2FybmluZyBtZXNzYWdlcyBpbg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRoZSBvdXRwdXQgZmlsZS4gDQogICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cyA9IFRSVUUsICAgICMgeW91IGNhbiBhbHNvIGRlY2lkZSB3aGV0aGVyIHRvIGluY2x1ZGUgdGhlIG91dHB1dA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGluIHRoZSBvdXRwdXQgZmlsZS4NCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgY29tbWVudCA9IE5BDQogICAgICAgICAgICAgICAgICAgICAgKSAgDQpgYGANCg0KXA0KDQojIEludHJvZHVjdGlvbg0KDQoNClRoaXMgbW9kdWxlIGZvY3VzZXMgb24gdGhlIHRocmVlIG1vc3QgY29tbW9ubHkgdXNlZCBzdGF0aXN0aWNhbCB0ZXN0cyBpbiBzdWJzZXF1ZW50IGNvdXJzZXM6IHRoZSBXYWxkLCBTY29yZSwgYW5kIExpa2VsaWhvb2QgUmF0aW8gdGVzdHMuIFRoZXNlIHRocmVlIG1ldGhvZHMgZm9ybSB0aGUgY29ybmVyc3RvbmUgb2YgaW5mZXJlbmNlIGluIHBhcmFtZXRyaWMgbW9kZWxzLCBwcm92aWRpbmcgcG93ZXJmdWwgYW5kIHZlcnNhdGlsZSBhcHByb2FjaGVzIGZvciB0ZXN0aW5nIGh5cG90aGVzZXMsIGNvbnN0cnVjdGluZyBjb25maWRlbmNlIGludGVydmFscywgYW5kIGFzc2Vzc2luZyBtb2RlbCBmaXQuIA0KDQpXaGlsZSByb290ZWQgaW4gdGhlIGVsZWdhbnQgZnJhbWV3b3JrIG9mIG1heGltdW0gbGlrZWxpaG9vZCBlc3RpbWF0aW9uLCBlYWNoIHRlc3Qgb2ZmZXJzIGEgZGlzdGluY3QgZ2VvbWV0cmljIG9yIGFsZ2VicmFpYyBwZXJzcGVjdGl2ZSBvbiB0aGUgZXZpZGVuY2UgYWdhaW5zdCBhIG51bGwgaHlwb3RoZXNpcy4gVW5kZXJzdGFuZGluZyB0aGVpciB0aGVvcmV0aWNhbCBmb3VuZGF0aW9ucywgY29tcGFyYXRpdmUgc3RyZW5ndGhzLCBhbmQgaW50cmluc2ljIHJlbGF0aW9uc2hpcHMgaXMgZXNzZW50aWFsIGZvciBtYXN0ZXJpbmcgYWR2YW5jZWQgc3RhdGlzdGljYWwgbWV0aG9kb2xvZ3kgYW5kIGFwcGx5aW5nIGl0IGNvcnJlY3RseSB0byBjb21wbGV4IGRhdGEuDQoNCkluIHRoaXMgbW9kdWxlLCB3ZSB3aWxsIHN0YXRlIGZvcm11bGF0aW9uLCBhc3N1bXB0aW9ucywgc3RlcHMgdG8gcGVyZm9ybSB0aGVzZSB0ZXN0cyBhbmQgZXhwbGFpbmVkIGJ5IG51bWVyaWNhbCBleGFtcGxlcyB3aXRoIG1hbnVhbCBzb2x1dGlvbiBhbmQgdmVyaWZpY2F0aW9uIHVzaW5nIFIuDQoNCg0KIyBSZXZpZXcgb2YgTGlrZWxpaG9vZCBGb3JtdWxhdGlvbiBhbmQgRXN0aW1hdGlvbg0KDQpJbiBtYXhpbXVtIGxpa2VsaWhvb2QgZXN0aW1hdGlvbiwgd2UgZml0IG1vZGVscyBieSBmaW5kaW5nIHBhcmFtZXRlcnMgdGhhdCBtYWtlIHRoZSBvYnNlcnZlZCBkYXRhIG1vc3QgcHJvYmFibGUuIFRoaXMgcHJvY2VzcyBuYXR1cmFsbHkgbGVhZHMgdG8gdGhyZWUgcmVsYXRlZCBtZXRob2RzIGZvciB0ZXN0aW5nIGh5cG90aGVzZXMgc3VjaCBhcyB0aGUgbGlrZWxpaG9vZCByYXRpbywgV2FsZCwgYW5kIHNjb3JlIHRlc3RzLiBFYWNoIHRlc3QgdXNlcyBhIGRpZmZlcmVudCBmZWF0dXJlIG9mIHRoZSBsaWtlbGlob29kIGZ1bmN0aW9uLCBidXQgYWxsIGFyZSByb290ZWQgaW4gdGhlIHNhbWUgcHJpbmNpcGxlcyBvZiBsaWtlbGlob29kIGFuZCBhc3ltcHRvdGljIHRoZW9yeS4gVGhpcyBzZWN0aW9uIHJldmlld3MgYmFzaWNzIG9mIG1heGltdW0gbGlrZWxpaG9vZCBlc3RpbWF0aW9uIGFuZCB0aGVpciBhc3ltcHRvdGljIG5vcm1hbGl0eS4NCg0KDQoqKkxpa2VsaWhvb2QgRnVuY3Rpb24qKg0KDQpMZXQgJFhfMSwgWF8yLCBcZG90cywgWF9uJCBiZSBpbmRlcGVuZGVudCBhbmQgaWRlbnRpY2FsbHkgZGlzdHJpYnV0ZWQgKGkuaS5kKSByYW5kb20gdmFyaWFibGVzIHdpdGggcHJvYmFiaWxpdHkgZGVuc2l0eSAob3IgbWFzcykgZnVuY3Rpb24gJGYoeF9pOyBcYm9sZHN5bWJvbHtcdGhldGF9KSQsIHdoZXJlICRcYm9sZHN5bWJvbHtcdGhldGF9ID0gKFx0aGV0YV8xLCBcZG90cywgXHRoZXRhX3ApXlQkIGlzIGEgJHAkLWRpbWVuc2lvbmFsIHBhcmFtZXRlciB2ZWN0b3IuIFRoZSBsaWtlbGlob29kIGZ1bmN0aW9uIGlzOg0KDQokJA0KTChcYm9sZHN5bWJvbHtcdGhldGF9KSA9IFxwcm9kX3tpPTF9Xm4gZih4X2k7IFxib2xkc3ltYm9se1x0aGV0YX0pDQokJA0KDQpUaGUgbG9nLWxpa2VsaWhvb2QgZnVuY3Rpb24gaXM6DQoNCiQkDQpcZWxsKFxib2xkc3ltYm9se1x0aGV0YX0pID0gXGxvZyBMKFxib2xkc3ltYm9se1x0aGV0YX0pID0gXHN1bV97aT0xfV5uIFxsb2cgZih4X2k7IFxib2xkc3ltYm9se1x0aGV0YX0pDQokJA0KDQoqKk1heGltdW0gTGlrZWxpaG9vZCBFc3RpbWF0aW9uKioNCg0KVGhlIG1heGltdW0gbGlrZWxpaG9vZCBlc3RpbWF0b3IgKE1MRSkgJFxoYXR7XGJvbGRzeW1ib2x7XHRoZXRhfX0kIHNhdGlzZmllczoNCg0KJCQNClxoYXR7XGJvbGRzeW1ib2x7XHRoZXRhfX0gPSBcYXJnXG1heF97XGJvbGRzeW1ib2x7XHRoZXRhfX0gXGVsbChcYm9sZHN5bWJvbHtcdGhldGF9KQ0KJCQNCg0KVW5kZXIgcmVndWxhcml0eSBjb25kaXRpb25zLCAkXGhhdHtcYm9sZHN5bWJvbHtcdGhldGF9fSQgaXMgb2J0YWluZWQgYnkgc29sdmluZyB0aGUgc2NvcmUgZXF1YXRpb25zOg0KDQokJA0KVShcYm9sZHN5bWJvbHtcdGhldGF9KSA9IFxmcmFje1xwYXJ0aWFsIFxlbGwoXGJvbGRzeW1ib2x7XHRoZXRhfSl9e1xwYXJ0aWFsIFxib2xkc3ltYm9se1x0aGV0YX19ID0gXGJvbGRzeW1ib2x7MH0NCiQkDQoNCg0KKipGaXNoZXIgSW5mb3JtYXRpb24gTWF0cml4KioNCg0KVGhlIEZpc2hlciBpbmZvcm1hdGlvbiBtYXRyaXggb2YgJFx0aGV0YSQgYmFzZWQgb24gYW4gZW50aXJlIHNhbXBsZSB3aXRoIHNpemUgJG4kIGlzIGdpdmVuIGJ5Og0KDQokJA0KSV9uKFxib2xkc3ltYm9se1x0aGV0YX0pID0gRVxsZWZ0Wy1cZnJhY3tccGFydGlhbF4yIFxlbGwoXGJvbGRzeW1ib2x7XHRoZXRhfSl9e1xwYXJ0aWFsIFxib2xkc3ltYm9se1x0aGV0YX0gXHBhcnRpYWwgXGJvbGRzeW1ib2x7XHRoZXRhfV5UfVxyaWdodF0NCiQkDQoNClRoZSBhYm92ZSAodGhlb3JldGljYWwpIEZpc2hlciBpbmZvcm1hdGlvbiBtYXRyaXggcmVxdWlyZXMgaW50ZWdyYWwgdGhhdCBpbnRlZ3JhdGVzIHZhcmlhYmxlcyBvdXQgZnJvbSB0aGUgZXhwcmVzc2lvbi4gSW4gcHJhY3RpY2UsIHdlIHVzZSB0aGUgZm9sbG93aW5nIG9ic2VydmVkIGluZm9ybWF0aW9uIG1hdHJpeDoNCg0KJCQNCkpfbihcYm9sZHN5bWJvbHtcdGhldGF9KSA9IC1cZnJhY3tccGFydGlhbF4yIFxlbGwoXGJvbGRzeW1ib2x7XHRoZXRhfSl9e1xwYXJ0aWFsIFxib2xkc3ltYm9se1x0aGV0YX0gXHBhcnRpYWwgXGJvbGRzeW1ib2x7XHRoZXRhfV5UfQ0KJCQNCg0KU29tZSBzb2Z0d2FyZSBwcm9ncmFtcyByZXR1cm4gSGVzc2lhbiBtYXRyaXggJEhfbiggXGJvbGRzeW1ib2x7XHRoZXRhfSkgPSAtSl9uKCBcYm9sZHN5bWJvbHtcdGhldGF9KSQsIHRoYXQgaXMNCg0KJCQNCkhfbihcYm9sZHN5bWJvbHtcdGhldGF9KSA9IFxmcmFje1xwYXJ0aWFsXjIgXGVsbChcYm9sZHN5bWJvbHtcdGhldGF9KX17XHBhcnRpYWwgXGJvbGRzeW1ib2x7XHRoZXRhfSBccGFydGlhbCBcYm9sZHN5bWJvbHtcdGhldGF9XlR9DQokJA0KDQpOb3RlIHRoYXQsIGluIHNvbWUgdGV4dGJvb2tzLCByZXNlYXJjaCBhcnRpY2xlcyBhbmQgd2ViIHBvc3RpbmdzLCB0aGUgKipGaXNoZXIgSW5mb3JtYXRpb24gTWF0cml4KiogYmFzZWQgb24gc2luZ2xlIGRhdGEgcG9pbnQgaXMgZGVub3RlZCBieSAkSV8wKFxib2xkc3ltYm9se1x0aGV0YX0pJCwNCg0KJCQNCklfbihcYm9sZHN5bWJvbHtcdGhldGF9KSA9IG5cdGltZXMgSV8xKFxib2xkc3ltYm9se1x0aGV0YX0pDQokJA0KDQpVbmRlciBzb21lIHJlZ3VsYXJpdHkgY29uZGl0aW9ucyBhbmQgdGhlIG51bGwgaHlwb3RoZXNpcyAkSF8wOiBcYm9sZHN5bWJvbHtcdGhldGF9ID0gXGJvbGRzeW1ib2x7XHRoZXRhfV8wJCwgd2UgaGF2ZSB0aGUgZm9sbG93aW5nIA0KDQokJA0KXHNxcnR7bn0oXGhhdHtcYm9sZHN5bWJvbHtcdGhldGF9fSAtIFxib2xkc3ltYm9se1x0aGV0YX1fMCkgXHhyaWdodGFycm93e2R9IE4oXGJvbGRzeW1ib2x7MH0sIElfMV57LTF9KFxib2xkc3ltYm9se1x0aGV0YX1fMCkpLg0KJCQNCg0KDQpUaGUgcmVsYXRpb25zaGlwIGJldHdlZW4gKipGaXNoZXIgSW5mb3JtYXRpb24gTWF0cml4Kiogb2YgJFxib2xkc3ltYm9se1x0aGV0YX0kIGFuZCB0aGUgdmFyaWFuY2Ugb2YgdGhlIE1MRSAkXGhhdHtcYm9sZHN5bWJvbHtcdGhldGF9fSQgaXMNCg0KJCQNClx0ZXh0e3Zhcn0oXGhhdHtcYm9sZHN5bWJvbHtcdGhldGF9fSkgXGFwcHJveCBJX25eey0xfShcYm9sZHN5bWJvbHtcdGhldGF9KSA9IFtuXHRpbWVzIElfMShcYm9sZHN5bWJvbHtcdGhldGF9KV1eey0xfSA9IFxmcmFje0lfMV57LTF9KFxib2xkc3ltYm9se1x0aGV0YX0pfXtufQ0KJCQNClRoZXJlZm9yZSwgd2UgY2FuIHJld3JpdGUgdGhlIGFib3ZlIGFzeW1wdG90aWMgZGlzdHJpYnV0aW9uIG9mICRcYm9sZHN5bWJvbHtcdGhldGF9JCBhcw0KDQokJA0KXGhhdHtcYm9sZHN5bWJvbHtcdGhldGF9fVx0byBOXGxlZnQoIFxib2xkc3ltYm9se1x0aGV0YX0sIFxmcmFje0lfMV57LTF9KFxib2xkc3ltYm9se1x0aGV0YX0pfXtufSBccmlnaHQpIFxxdWFkIFx0ZXh0e29yIGVxdWl2YWxlbnRseX0gXHF1YWQgXGhhdHtcYm9sZHN5bWJvbHtcdGhldGF9fVx0byBOXGxlZnQoIFxib2xkc3ltYm9se1x0aGV0YX0sIElfbl57LTF9KFxib2xkc3ltYm9se1x0aGV0YX0pIFxyaWdodCkNCiQkDQoNClRoZSBkaWFnb25hbCBlbGVtZW50cyBpbiB0aGUgY292YXJpYW5jZSAkSV9uXnstMX0oXGJvbGRzeW1ib2x7XHRoZXRhfSkkIHJlcHJlc2VudCB0aGUgdmFyaWFuY2Ugb2YgdGhlIGNvcnJlc3BvbmRpbmcgcGFyYW1ldGVycyBpbiAkXGhhdHtcYm9sZHN5bWJvbHtcdGhldGF9fSA9IChcaGF0e1x0aGV0YX1fMSwgXGhhdHtcdGhldGF9XzIsIFxjZG90cywgXGhhdHtcdGhldGFfa30pJC4gRm9yIGV4YW1wbGUuICRcdGV4dHt2YXJ9KFxoYXR7XHRoZXRhfV8xKSA9ICQgdGhlIGZpcnN0IGVsZW1lbnQgaW4gdGhlIG1haW4gZGlhZ29uYWwgb2YgdGhlIGludmVyc2Ugb2YgdGhlIGZpc2hlciBpbmZvcm1hdGlvbiBtYXRyaXggYmFzZWQgb24gdGhlIGVudGlyZSBzYW1wbGUuICANCg0KRm9yIGV4YW1wbGUsIGxldCAkXGJvbGRzeW1ib2x7XHRoZXRhfSA9KFx0aGV0YV8xLCBcdGhldGFfMikkLCB0aGUgY29ycmVzcG9uZGluZyBNTEUgaXMgJFxoYXR7XGJvbGRzeW1ib2x7XHRoZXRhfX0gPShcaGF0e1x0aGV0YV8xfSwgXGhhdHtcdGhldGFfMil9JC4gTGV0IHRoZSAqKm9ic2VydmVkIEZpc2hlciBpbmZvcm1hdGlvbiBtYXRyaXgqKiBiZQ0KDQokJA0KSl9uKFxib2xkc3ltYm9se1x0aGV0YX0pID0gLVxmcmFje1xwYXJ0aWFsXjIgXGVsbChcYm9sZHN5bWJvbHtcdGhldGF9KX17XHBhcnRpYWwgXGJvbGRzeW1ib2x7XHRoZXRhfSBccGFydGlhbCBcYm9sZHN5bWJvbHtcdGhldGF9XlR9PS1cYmVnaW57cG1hdHJpeH0NClxmcmFje1xwYXJ0aWFsXjIgXGVsbChcYm9sZHN5bWJvbHtcdGhldGF9KX17XHBhcnRpYWxeMiBcdGhldGFfMX0gJiBcZnJhY3tccGFydGlhbF4yIFxlbGwoXGJvbGRzeW1ib2x7XHRoZXRhfSl9e1xwYXJ0aWFsIFx0aGV0YV8xXHBhcnRpYWwgXHRoZXRhXzJ9IFxcDQpcZnJhY3tccGFydGlhbF4yIFxlbGwoXGJvbGRzeW1ib2x7XHRoZXRhfSl9e1xwYXJ0aWFsIFx0aGV0YV8yXHBhcnRpYWwgXHRoZXRhXzF9ICYgXGZyYWN7XHBhcnRpYWxeMiBcZWxsKFxib2xkc3ltYm9se1x0aGV0YX0pfXtccGFydGlhbF4yIFx0aGV0YV8yfQ0KXGVuZHtwbWF0cml4fQ0KJCQNCg0KVGhlIGVzdGltYXRlZCBGaXNoZXIgaW5mb3JtYXRpb24gbWF0cml4IGlzIGdpdmVuIGJ5DQoNCiQkDQpcd2lkZWhhdHtKX24oXGJvbGRzeW1ib2x7XHRoZXRhfSl9ID0gLVxiZWdpbntwbWF0cml4fQ0KXGZyYWN7XHBhcnRpYWxeMiBcZWxsKFxib2xkc3ltYm9se1x0aGV0YX0pfXtccGFydGlhbF4yIFx0aGV0YV8xfSAmIFxmcmFje1xwYXJ0aWFsXjIgXGVsbChcYm9sZHN5bWJvbHtcdGhldGF9KX17XHBhcnRpYWwgXHRoZXRhXzFccGFydGlhbCBcdGhldGFfMn0gXFwNClxmcmFje1xwYXJ0aWFsXjIgXGVsbChcYm9sZHN5bWJvbHtcdGhldGF9KX17XHBhcnRpYWwgXHRoZXRhXzJccGFydGlhbCBcdGhldGFfMX0gJiBcZnJhY3tccGFydGlhbF4yIFxlbGwoXGJvbGRzeW1ib2x7XHRoZXRhfSl9e1xwYXJ0aWFsXjIgXHRoZXRhXzJ9DQpcZW5ke3BtYXRyaXh9XEJpZ2d8X3tcYm9sZHN5bWJvbHtcdGhldGF9ID0gXGhhdHtcYm9sZHN5bWJvbHtcdGhldGF9fX0uDQokJA0KDQpOb3RlIHRoYXQgUiBmdW5jdGlvbiBgb3B0aW0oKWAgcmV0dXJucyBIZXNzaWFuIG1hdHJpeCAkXHdpZGVoYXR7SF9uKFxib2xkc3ltYm9se1x0aGV0YX0pfT0tIFx3aWRlaGF0e0pfbihcYm9sZHN5bWJvbHtcdGhldGF9KX0kLg0KDQpMZXQgdGhlIGludmVyc2Ugb2YgJHdpZGVoYXR7Sl9uKFxib2xkc3ltYm9se1x0aGV0YX0pfSQgYmUgb2YgdGhlIGZvbGxvd2luZyBmb3JtDQoNCiQkDQpcbGVmdFtcd2lkZWhhdHtKX24oXGJvbGRzeW1ib2x7XHRoZXRhfSl9XHJpZ2h0XV57LTF9ID0gLVxsZWZ0W1xiZWdpbntwbWF0cml4fQ0KXGZyYWN7XHBhcnRpYWxeMiBcZWxsKFxib2xkc3ltYm9se1x0aGV0YX0pfXtccGFydGlhbF4yIFx0aGV0YV8xfSAmIFxmcmFje1xwYXJ0aWFsXjIgXGVsbChcYm9sZHN5bWJvbHtcdGhldGF9KX17XHBhcnRpYWwgXHRoZXRhXzFccGFydGlhbCBcdGhldGFfMn0gXFwNClxmcmFje1xwYXJ0aWFsXjIgXGVsbChcYm9sZHN5bWJvbHtcdGhldGF9KX17XHBhcnRpYWwgXHRoZXRhXzJccGFydGlhbCBcdGhldGFfMX0gJiBcZnJhY3tccGFydGlhbF4yIFxlbGwoXGJvbGRzeW1ib2x7XHRoZXRhfSl9e1xwYXJ0aWFsXjIgXHRoZXRhXzJ9DQpcZW5ke3BtYXRyaXh9XEJpZ2d8X3tcYm9sZHN5bWJvbHtcdGhldGF9ID0gXGhhdHtcYm9sZHN5bWJvbHtcdGhldGF9fX1ccmlnaHRdXnstMX0NCj1cYmVnaW57cG1hdHJpeH0NCmEgJiBjIFxcDQpjICYgZA0KXGVuZHtwbWF0cml4fS4NCiQkDQoNClRoZW4gd2UgaGF2ZQ0KDQokJA0KXHdpZGVoYXR7XHRleHR7dmFyfShcaGF0e1xib2xkc3ltYm9se1x0aGV0YX0pfX0gXGFwcHJveCBcYmVnaW57cG1hdHJpeH0NCmEgJiBjIFxcDQpjICYgZA0KXGVuZHtwbWF0cml4fS4NCiQkDQoNClRoYXQgaXMsDQoNCiQkDQpcdGV4dHt2YXJ9KFxoYXR7XHRoZXRhfV8xKSBcYXBwcm94IGEsIFxxdWFkICBcdGV4dHt2YXJ9KFxoYXR7XHRoZXRhfV8yKSBcYXBwcm94IGQsIFxxdWFkIFx0ZXh0e2FuZH0gXHF1YWQgIFx0ZXh0e2Nvdn0oXGhhdHtcdGhldGF9XzEsIFxoYXR7XHRoZXRhfV8yKSBcYXBwcm94IGMuDQokJA0KDQpUaGUgYWJvdmUgYXN5bXB0b3RpYyBub3JtYWxpdHkgaXMgdGhlIGZvdW5kYXRpb24gb2YgdGhlIFdhbGQgYW5kIFNjb3JlIHRlc3RzLg0KDQoNClwNCg0KIyBUaGUgVGhyZWUgQXN5bXB0b3RpYyAkXGNoaV4yJCBUZXN0cw0KDQpBdCB0aGUgZm91bmRhdGlvbiBvZiBwYXJhbWV0cmljIGh5cG90aGVzaXMgdGVzdGluZyBsaWVzIGEgdHJpbyBvZiBhc3ltcHRvdGljYWxseSBlcXVpdmFsZW50IG1ldGhvZHM6IHRoZSBsaWtlbGlob29kIHJhdGlvLCBXYWxkLCBhbmQgc2NvcmUgdGVzdHMuIEFsbCB0aHJlZSBkZXJpdmUgZnJvbSBtYXhpbXVtIGxpa2VsaWhvb2QgdGhlb3J5IGFuZCBjb252ZXJnZSB0byB0aGUgc2FtZSBjaGktc3F1YXJlZCBkaXN0cmlidXRpb24gdW5kZXIgdGhlIG51bGwgaHlwb3RoZXNpcywgeWV0IHRoZXkgYXBwcm9hY2ggdGhlIHByb2JsZW0gb2YgdGVzdGluZyBmcm9tIG1lYW5pbmdmdWxseSBkaWZmZXJlbnQgYW5nbGVzLg0KDQpUaGUgKipsaWtlbGlob29kIHJhdGlvIHRlc3QqKiBkaXJlY3RseSBjb21wYXJlcyB0aGUgZ29vZG5lc3Mtb2YtZml0IGJldHdlZW4gdGhlIHVucmVzdHJpY3RlZCBtb2RlbCBhbmQgdGhlIG1vZGVsIGNvbnN0cmFpbmVkIGJ5IHRoZSBudWxsIGh5cG90aGVzaXMuIFRoZSAqKldhbGQgdGVzdCoqIGV2YWx1YXRlcyB0aGUgZGlzdGFuY2UgYmV0d2VlbiB0aGUgZXN0aW1hdGVkIHBhcmFtZXRlciB2ZWN0b3IgYW5kIGl0cyBoeXBvdGhlc2l6ZWQgdmFsdWUsIHN0YW5kYXJkaXplZCBieSB0aGUgZXN0aW1hdGVkIGN1cnZhdHVyZSBvZiB0aGUgbGlrZWxpaG9vZC4gVGhlICoqc2NvcmUgdGVzdCoqLCBhbHRlcm5hdGl2ZWx5LCBleGFtaW5lcyB3aGV0aGVyIHRoZSBzbG9wZSBvZiB0aGUgbG9nLWxpa2VsaWhvb2QgYXQgdGhlIG51bGwgcGFyYW1ldGVyIHZhbHVlIGlzIHN1ZmZpY2llbnRseSBjbG9zZSB0byB6ZXJv4oCUYW4gaW5kaWNhdGlvbiB0aGF0IHRoZSBudWxsIHBvaW50IGlzIGEgcGxhdXNpYmxlIG1heGltdW0uDQoNCkRlc3BpdGUgdGhlaXIgYXN5bXB0b3RpYyBlcXVpdmFsZW5jZSwgdGhlc2UgdGVzdHMgZGlmZmVyIGluIGNvbXB1dGF0aW9uLCBmaW5pdGUtc2FtcGxlIHBlcmZvcm1hbmNlLCBhbmQgaW52YXJpYW5jZSBwcm9wZXJ0aWVzLCBsZWFkaW5nIHRvIHByYWN0aWNhbCB0cmFkZS1vZmZzIGluIGFwcGxpZWQgd29yay4gVGhlIGZvbGxvd2luZyBzdWItc2VjdGlvbnMgZGV2ZWxvcCB0aGVpciBmb3JtdWxhdGlvbnMsIGNvbnRyYXN0cyB0aGVpciB0aGVvcmV0aWNhbCBhbmQgcHJhY3RpY2FsIGF0dHJpYnV0ZXMsIGFuZCBwcm92aWRlIGd1aWRhbmNlIGZvciBjaG9vc2luZyBhbW9uZyB0aGVtIGluIHN0YXRpc3RpY2FsIG1vZGVsaW5nLg0KDQoNCg0KIyMgV2FsZCBUZXN0DQoNCioqRm9ybXVsYXRpb24qKiBUZXN0cyB0aGUgZGlzdGFuY2UgYmV0d2VlbiB0aGUgKip1bmNvbnN0cmFpbmVkIE1MRSoqIGFuZCB0aGUgKipoeXBvdGhlc2l6ZWQgdmFsdWUqKi4gSXQgbWVhc3VyZXMgKipnZW9tZXRyaWMgZGlzcGxhY2VtZW50KiogZnJvbSAkSF8wJCBpbiBwYXJhbWV0ZXIgc3BhY2UuIFRvIG1ha2UgaXQgc2ltcGxlLCBsZXQncyAkXGJvbGRzeW1ib2x7XHRoZXRhfSA9IChcdGhldGFfMSwgXHRoZXRhXzIpJCBiZSB0aGUgdmVjdG9yIG9mIHRoZSBwYXJhbWV0ZXJzIG9mIGEgZGlzdHJpYnV0aW9uLiBDb25zaWRlciBoeXBvdGhlc2lzIA0KDQokJA0KSF8wOiBcYm9sZHN5bWJvbHtcdGhldGF9ID0gXGJvbGRzeW1ib2x7XHRoZXRhfV8wLCBccXVhZCBcdGV4dHtpLmUufVxxdWFkIFxiZWdpbntwbWF0cml4fQ0KXHRoZXRhXzEgIFxcDQpcdGhldGFfMiANClxlbmR7cG1hdHJpeH0NCj0NClxiZWdpbntwbWF0cml4fQ0KXHRoZXRhX3sxMH0gIFxcDQpcdGhldGFfezIwfSANClxlbmR7cG1hdHJpeH0uDQokJA0KDQpUaGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSAqKmh5cG90aGVzaXplZCB2YWx1ZSoqIGFuZCB0aGUgKip1bnJlc3RyaWN0ZWQgTUxFKiogaXMgZ2l2ZW4gYnkNCg0KJCQNCkQgPSBcaGF0e1xib2xkc3ltYm9se1x0aGV0YX19IC0gXGJvbGRzeW1ib2x7XHRoZXRhfV8wID0gXGJlZ2lue3BtYXRyaXh9DQpcaGF0e1x0aGV0YX1fMSAtXHRoZXRhX3sxMH0gIFxcDQpcaGF0e1x0aGV0YX1fMiAtXHRoZXRhX3syMH0NClxlbmR7cG1hdHJpeH0NCiQkDQoNCg0KKipUZXN0IFN0YXRpc3RpYyoqDQoNCldpdGggdGhlIGFib3ZlIG5vdGF0aW9ucywgdGhlIFdhbGQgdGVzdCBzdGF0aXN0aWMgaXMgZ2l2ZW4gYnkNCg0KJCQNClcgPSBcaGF0e0R9XntUfSBcLCBcbGVmdFsgXHdpZGVoYXR7XHRleHR7dmFyfShcaGF0e1xib2xkc3ltYm9se1x0aGV0YX19KX1ccmlnaHRdXnstMX0gXCwgXGhhdHtEfSAgPSBcaGF0e0R9XntUfSBcLFx0ZXh0e0l9X24oXGhhdHtcYm9sZHN5bWJvbHtcdGhldGF9fSkgXCwgXGhhdHtEfSANCiQkDQoNCk1vcmUgZXhwbGljaXRseSwgd2UgaGF2ZQ0KDQokJA0KVyA9IA0KXGJlZ2lue3BtYXRyaXh9IA0KXGhhdHtcdGhldGF9XzEgLSBcdGhldGFfezEwfSAmIFxoYXR7XHRoZXRhfV8yIC0gXHRoZXRhX3syMH0NClxlbmR7cG1hdHJpeH0NClxiZWdpbntwbWF0cml4fQ0KXHRleHR7dmFyfShcaGF0e1x0aGV0YX1fMSkgJiBcdGV4dHtjb3Z9KFxoYXR7XHRoZXRhfV8xLCBcaGF0e1x0aGV0YX1fMikgXFwNClx0ZXh0e2Nvdn0oXGhhdHtcdGhldGF9XzEsIFxoYXR7XHRoZXRhfV8yKSAmIFx0ZXh0e3Zhcn0oXGhhdHtcdGhldGF9XzIpDQpcZW5ke3BtYXRyaXh9XnstMX0NClxiZWdpbntwbWF0cml4fQ0KXGhhdHtcdGhldGF9XzEgLSBcdGhldGFfezEwfSBcXA0KXGhhdHtcdGhldGF9XzIgLSBcdGhldGFfezIwfQ0KXGVuZHtwbWF0cml4fS4NCiQkDQoNCg0KDQpGb3IgdGVzdGluZyBzaW5nbGUgcGFyYW1ldGVyIGNhc2UgJEhfMDogXGJvbGRzeW1ib2x7XHRoZXRhfV8xID0gXGJvbGRzeW1ib2x7XHRoZXRhfV97MTB9JA0KDQoNCiQkDQpXID0gKFxoYXR7XHRoZXRhfSAtIFx0aGV0YV8wKVtcdGV4dHt2YXJ9KFxoYXR7XHRoZXRhfV8xKV1eey0xfShcaGF0e1x0aGV0YX0gLSBcdGhldGFfMCkgPSBcZnJhY3soXGhhdHtcdGhldGF9IC0gXHRoZXRhXzApXjJ9e1x0ZXh0e3Zhcn0oXGhhdHtcdGhldGF9XzEpfQ0KJCQNCg0KDQoNCioqQXN5bXB0b3RpYyBEaXN0cmlidXRpb24qKjogJFcgXHhyaWdodGFycm93e2R9IFxjaGleMl9xJCB1bmRlciAkSF8wJCwgIHdoZXJlICRxJCBpcyB0aGUgbnVtYmVyIG9mIHBhcmFtZXRlcnMgc3BlY2lmaWVkIHVuZGVyIHRoZSBudWxsIGh5cG90aGVzaXMuDQoNCkluIHRoZSB0d28tcGFyYW1ldGVyIGFuZCBvbmUtcGFyYW1ldGVyIGNhc2VzIGRlc2NyaWJlZCBhYm92ZSwgdGhlIGRlZ3JlZXMgb2YgZnJlZWRvbSBvZiB0aGUgJFxjaGleMiQgdGVzdCBhcmUgJHEgPSAyJCBhbmQgJHE9MSQsIHJlc3BlY3RpdmVseS4NCg0KDQoNCioqQXNzdW1wdGlvbnMqKjogV2FsZCB0ZXN0IHJlcXVpcmVzIG9ubHkgdGhlIHVuY29uc3RyYWluZWQgTUxFIChhcyB3ZWxsIGFzIEluZm9ybWF0aW9uIG1hdHJpeCB0byBkZXJpdmUgdGhlIGNvdmFyaWFuY2UgbWF0cml4IG9mIHRoZSBNTEUpIGFuZCBpcyBzZW5zaXRpdmUgdG8gcGFyYW1ldGVyaXphdGlvbi4NCg0KDQoNCiMjIFNjb3JlIFRlc3QgKFJhbydzIFNjb3JlIFRlc3QpDQoNClJhbydzIHNjb3JlIGlzIGFsc28ga25vd24gYXMgdGhlICoqTGFncmFuZ2UgbXVsdGlwbGllciB0ZXN0KiouDQoNCioqRm9ybXVsYXRpb24qKjogVGVzdHMgd2hldGhlciB0aGUgc2NvcmUgYXQgdGhlIG51bGwgaHlwb3RoZXNpcyBpcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIHplcm8uIEl0IG1lYXN1cmVzIGxvY2FsIGdyYWRpZW50IGF0ICRIXzAkIGluIGxpa2VsaWhvb2Qgc3BhY2UuDQoNCioqVGVzdCBTdGF0aXN0aWMqKjoNCg0KJCQNClMgPSBVKFx0aWxkZXtcYm9sZHN5bWJvbHtcdGhldGF9fSleVCBJX25eey0xfShcdGlsZGV7XGJvbGRzeW1ib2x7XHRoZXRhfX0pIFUoXHRpbGRle1xib2xkc3ltYm9se1x0aGV0YX19KQ0KJCQNCndoZXJlICRcdGlsZGV7XGJvbGRzeW1ib2x7XHRoZXRhfX0kIGlzIHRoZSBNTEUgdW5kZXIgJEhfMCQgKGNvbnN0cmFpbmVkIE1MRSkuDQoNCioqQXN5bXB0b3RpYyBEaXN0cmlidXRpb24qKjogJFMgXHhyaWdodGFycm93e2R9IFxjaGleMl9xJCB1bmRlciAkSF8wJC4NCg0KKipBc3N1bXB0aW9ucyoqOiBSZXF1aXJlcyBvbmx5IHRoZSBjb25zdHJhaW5lZCBNTEUuIEludmFyaWFudCB0byByZXBhcmFtZXRlcml6YXRpb24uDQoNCg0KIyMgTGlrZWxpaG9vZCBSYXRpbyBUZXN0DQoNCioqRm9ybXVsYXRpb24qKjogQ29tcGFyZXMgdGhlIG1heGltaXplZCBsb2ctbGlrZWxpaG9vZCB1bmRlciAkSF8wJCBhbmQgJEhfMSQuIEl0IG1lYXN1cmVzIGluZm9ybWF0aW9uIGxvc3Mgd2hlbiBpbXBvc2luZyAkSF8wJC4NCg0KKipUZXN0IFN0YXRpc3RpYyoqOg0KDQokJA0KXExhbWJkYSA9IC0yW1xlbGwoXHRpbGRle1xib2xkc3ltYm9se1x0aGV0YX19KSAtIFxlbGwoXGhhdHtcYm9sZHN5bWJvbHtcdGhldGF9fSldID0gMltcZWxsKFxoYXR7XGJvbGRzeW1ib2x7XHRoZXRhfX0pIC0gXGVsbChcdGlsZGV7XGJvbGRzeW1ib2x7XHRoZXRhfX0pXQ0KJCQNCg0KKipBc3ltcHRvdGljIERpc3RyaWJ1dGlvbioqOiAkXExhbWJkYSBceHJpZ2h0YXJyb3d7ZH0gXGNoaV4yX3EkIHVuZGVyICRIXzAkLg0KDQoqKkFzc3VtcHRpb25zKio6IFJlcXVpcmVzIGJvdGggY29uc3RyYWluZWQgYW5kIHVuY29uc3RyYWluZWQgTUxFcy4gSW52YXJpYW50IHRvIHJlcGFyYW1ldGVyaXphdGlvbi4NCg0KXA0KDQoNCg0KIyBQcmFjdGljYWwgRXhhbXBsZXM6IFNpbmdsZSBQYXJhbWV0ZXINCg0KVG8gY29uY3JldGVseSBkZW1vbnN0cmF0ZSB0aGUgc2ltaWxhcml0aWVzIGFuZCBkaWZmZXJlbmNlcyBhbW9uZyB0aGUgdGhyZWUgbGlrZWxpaG9vZC1iYXNlZCB0ZXN0cywgd2Ugbm93IHR1cm4gdG8gcHJhY3RpY2FsIGltcGxlbWVudGF0aW9uIGluIFIuIFdoaWxlIHRoZXNlIHRlc3RzIG9mdGVuIHlpZWxkIHNpbWlsYXIgY29uY2x1c2lvbnMgd2l0aCBsYXJnZSBzYW1wbGVzLCB0aGVpciBkaXN0aW5jdGlvbnMgYmVjb21lIHBhcnRpY3VsYXJseSBpbnN0cnVjdGl2ZSB3aGVuIGV4YW1pbmluZyBzaW1wbGUgeWV0IGZ1bmRhbWVudGFsIGRpc3RyaWJ1dGlvbnMuIA0KDQpUaHJvdWdoIGhhbmRzLW9uIGV4YW1wbGVzIHVzaW5nIFBvaXNzb24gYW5kIG5vcm1hbCBkaXN0cmlidXRpb25zLCB3ZSB3aWxsIHN5c3RlbWF0aWNhbGx5IGFwcGx5IHRoZSBMaWtlbGlob29kIFJhdGlvLCBXYWxkLCBhbmQgU2NvcmUgdGVzdHMgdG8gaWRlbnRpY2FsIGh5cG90aGVzZXMuIFRoaXMgY29tcGFyYXRpdmUgYXBwcm9hY2ggd2lsbCBpbGx1bWluYXRlIGhvdyBlYWNoIHRlc3Qgc3RhdGlzdGljIGlzIGNhbGN1bGF0ZWQsIHNob3djYXNlIHNjZW5hcmlvcyB3aGVyZSB0aGVpciByZXN1bHRzIGRpdmVyZ2UgbWVhbmluZ2Z1bGx5LCBhbmQgcHJvdmlkZSByZXVzYWJsZSBjb2RlIHRlbXBsYXRlcyB0aGF0IHJldmVhbCB0aGUgY29tcHV0YXRpb25hbCBtYWNoaW5lcnkgdW5kZXJseWluZyBjb21tb24gc3RhdGlzdGljYWwgcHJvY2VkdXJlcy4gDQoNCjxmb250IGNvbG9yID0gImJsdWUiPioqVW5saWtlIHQtdGVzdHMgYW5kIHotdGVzdHMgd2hpY2ggaGF2ZSBjbG9zZWQtZm9ybSBmb3JtdWxhcywgbGlrZWxpaG9vZC1iYXNlZCBjaGktc3F1YXJlZCB0ZXN0cyByZXF1aXJlIGV4cGxpY2l0IGRlcml2YXRpb24gb2YgdGhlIGxpa2VsaWhvb2QgZnVuY3Rpb24sIHBhcmFtZXRlciBlc3RpbWF0aW9uIHVuZGVyIG51bGwvYWx0ZXJuYXRpdmUsIGFuZCBjYXJlZnVsIGNvbnN0cnVjdGlvbiBvZiB0aGUgdGVzdCBzdGF0aXN0aWNzLiBUaGlzIGlzIHdoeSB0aGV5J3JlIG1vcmUgZmxleGlibGUgYnV0IHJlcXVpcmUgbW9yZSBwcmVwYXJhdGlvbi4qKjwvZm9udD4gVGhlIGtleSBwcmVwYXJhdGlvbiBzdGVwcyByZXF1aXJlZA0KDQoqIERlcml2ZSBsb2ctbGlrZWxpaG9vZCBmdW5jdGlvbiAkXGVsbChcdGhldGE7IHgpJA0KKiBEZXJpdmUgc2NvcmUgZnVuY3Rpb24gJFUoXHRoZXRhKSA9IFxwYXJ0aWFsIFxlbGwvXHBhcnRpYWwgXHRoZXRhJA0KKiBEZXJpdmUgRmlzaGVyIEluZm9ybWF0aW9uICRJX24oXHRoZXRhKSA9IC1FW1xwYXJ0aWFsXjIgXGVsbC9ccGFydGlhbCBcdGhldGFeMl0kDQoqIEZpbmQgTUxFcyB1bmRlciBib3RoICRIXzAkIGFuZCAkSF8xJA0KKiBDb21wdXRlIHN0YW5kYXJkIGVycm9ycyBmcm9tIGludmVyc2UgRmlzaGVyIEluZm9ybWF0aW9uDQoqIENvbnN0cnVjdCB0ZXN0IHN0YXRpc3RpY3MgdXNpbmcgYXBwcm9wcmlhdGUgZm9ybXVsYXMNCg0KPGZvbnQgY29sb3IgPSAicmVkIj4qKk5vdGUgdGhhdCBsaWtlbGlob29kLWJhc2VkIGluZmVyZW5jZXMgcmVseSBvbiBsYXJnZS1zYW1wbGUgYXN5bXB0b3RpYyB0aGVvcnkuIEZvciB0aGUgcHVycG9zZSBvZiBjbGVhcmx5IGlsbHVzdHJhdGluZyB0aGUgcHJvY2VkdXJlLCB0aGUgZXhhbXBsZXMgaW4gdGhlIGZvbGxvd2luZyBzdWJzZWN0aW9ucyB3aWxsIHVzZSBzbWFsbCB0b3kgZGF0YXNldHMuKio8L2ZvbnQ+DQoNCg0KIyMgRXhhbXBsZSAxOiBQb2lzc29uIERpc3RyaWJ1dGlvbg0KDQoqKlByb2JsZW0qKjogVGVzdCAkSF8wOiBcbGFtYmRhID0gMiQgdnMgJEhfMTogXGxhbWJkYSBcbmVxIDIkIGZvciAkWF8xLCBcZG90cywgWF9uIFxzaW0gXHRleHR7UG9pc3Nvbn0oXGxhbWJkYSkkLiANCg0KKipPYnNlcnZlZCBkYXRhKio6IDMsIDEsIDQsIDIsIDMuDQoNCioqTWFudWFsIFNvbHV0aW9uKio6DQoNCiogKipMaWtlbGlob29kKio6ICRMKFxsYW1iZGEpID0gXHByb2Rfe2k9MX1ebiBcZnJhY3tlXnstXGxhbWJkYX0gXGxhbWJkYV57eF9pfX17eF9pIX0kDQogICAgDQoqICoqTG9nLWxpa2VsaWhvb2QqKjogJFxlbGwoXGxhbWJkYSkgPSAtblxsYW1iZGEgKyAoXHN1bSB4X2kpXGxvZ1xsYW1iZGEgLSBcc3VtIFxsb2coeF9pISkkDQogICAgDQoqICoqTUxFKio6ICRcaGF0e1xsYW1iZGF9ID0gXGJhcnt4fSA9IFxmcmFjezMrMSs0KzIrM317NX0gPSAyLjYkDQogICAgDQoqICoqU2NvcmUgZnVuY3Rpb24qKjogJFUoXGxhbWJkYSkgPSBcZnJhY3tkXGVsbH17ZFxsYW1iZGF9ID0gLW4gKyBcZnJhY3tcc3VtIHhfaX17XGxhbWJkYX0kDQogICAgDQoqICoqSW5mb3JtYXRpb24qKjogJElfbihcbGFtYmRhKSA9IFxmcmFje259e1xsYW1iZGF9JCAoZXhwZWN0ZWQpLCAkSl9uKFxsYW1iZGEpID0gXGZyYWN7XHN1bSB4X2l9e1xsYW1iZGFeMn0kIChvYnNlcnZlZCkNCg0KDQoqKldhbGQgVGVzdCoqDQoNCiQkDQpXID0gKFxoYXR7XGxhbWJkYX0gLSBcbGFtYmRhXzApXjIgXGhhdHtJfV9uKFxoYXR7XGxhbWJkYX0pID0gKDIuNiAtIDIpXjIgXHRpbWVzIFxmcmFjezV9ezIuNn0gPSAwLjM2IFx0aW1lcyAxLjkyMyA9IDAuNjkyDQokJA0KVXNpbmcgb2JzZXJ2ZWQgaW5mb3JtYXRpb246ICRXID0gKDAuNileMiBcdGltZXMgXGZyYWN7MTN9ezIuNl4yfSA9IDAuMzYgXHRpbWVzIDEuOTIzID0gMC42OTIkDQoNCioqU2NvcmUgVGVzdCoqDQoNClNjb3JlIGF0ICRcbGFtYmRhXzA9MiQ6ICRVKDIpID0gLTUgKyBcZnJhY3sxM317Mn0gPSAxLjUkDQoNCiQkDQpJKDIpID0gXGZyYWN7NX17Mn0gPSAyLjUNCiQkDQoNCiQkDQpTID0gVSgyKV4yIElfbl57LTF9KDIpID0gKDEuNSleMiBcdGltZXMgXGZyYWN7MX17Mi41fSA9IDIuMjUgXHRpbWVzIDAuNCA9IDAuOQ0KJCQNCg0KKipMaWtlbGlob29kIFJhdGlvIFRlc3QqKg0KDQokJA0KXGVsbChcaGF0e1xsYW1iZGF9KSA9IC01KDIuNikgKyAxM1xsb2coMi42KSAtIFxzdW0gXGxvZyh4X2khKSA9IC0xMyArIDEzKDAuOTU1NSkgLSBcbG9nKDE3MjgpIFxhcHByb3ggLTguMDMzNQ0KJCQNCg0KJCQNClxlbGwoXGxhbWJkYV8wKSA9IC01KDIpICsgMTNcbG9nKDIpIC0gXHN1bSBcbG9nKHhfaSEpID0gLTEwICsgMTMoMC42OTMxKSAtIDcuNDU1IFxhcHByb3ggLTguNDQ0Nw0KJCQNCg0KJCQNClxMYW1iZGEgPSAyWy04LjAzMzUgLSAoLTguNDQ0NyldID0gMigwLjQxMTIpID0gMC44MjI0DQokJA0KDQoqKkNvbmNsdXNpb24qKiBBbGwgdGVzdCBzdGF0aXN0aWNzIGFyZSBhcHByb3hpbWF0ZWx5IGJldHdlZW4gMC43IGFuZCAwLjkuICBTaW5jZSBhbGwgdGhyZWUgdGVzdCBzdGF0aXN0aWNzIGFyZSBsZXNzIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlICRcY2hpXjJfezEsMC4wNX0gPSAzLjg0MSQsIHdlIGZhaWwgdG8gcmVqZWN0ICRIXzAkLg0KDQoNCioqUiBWZXJpZmljYXRpb24qKg0KDQpgYGB7cn0NCiMgUG9pc3NvbiBleGFtcGxlDQp4IDwtIGMoMywgMSwgNCwgMiwgMykNCm4gPC0gbGVuZ3RoKHgpDQoNCiMgTUxFDQpsYW1iZGFfbWxlIDwtIG1lYW4oeCkNCg0KIyBXYWxkIHRlc3QNCnNlX3dhbGQgPC0gc3FydChsYW1iZGFfbWxlL24pDQpXIDwtICgobGFtYmRhX21sZSAtIDIpL3NlX3dhbGQpXjINCg0KIyBTY29yZSB0ZXN0DQpVIDwtIC1uICsgc3VtKHgpLzINCkkgPC0gbi8yDQpTIDwtIFVeMi9JDQoNCiMgTGlrZWxpaG9vZCByYXRpbyB0ZXN0DQpsbF9tbGUgPC0gc3VtKGRwb2lzKHgsIGxhbWJkYV9tbGUsIGxvZyA9IFRSVUUpKQ0KbGxfbnVsbCA8LSBzdW0oZHBvaXMoeCwgMiwgbG9nID0gVFJVRSkpDQpMUiA8LSAyKihsbF9tbGUgLSBsbF9udWxsKQ0KDQpjYXQoIiAgV2FsZDoiLCBXLCAicC12YWx1ZToiLCAxLXBjaGlzcShXLCAxKSwgIlxuIiwNCiAgICAiU2NvcmU6IiwgUywgInAtdmFsdWU6IiwgMS1wY2hpc3EoUywgMSksICJcbiIsDQogICAgIiAgIExSOiIsIExSLCAicC12YWx1ZToiLCAxLXBjaGlzcShMUiwgMSksICJcbiIpDQpgYGANCg0KDQojIyBFeGFtcGxlIDI6IE5vcm1hbCBEaXN0cmlidXRpb24gTWVhbiBUZXN0DQoNCioqUHJvYmxlbSoqIFRlc3QgJEhfMDogXG11ID0gMTAkIHZzICRIXzE6IFxtdSBcbmVxIDEwJCBmb3IgJFhfaSBcc2ltIE4oXG11LCBcc2lnbWFeMikkLCB3aGVyZSAkXHNpZ21hXjIgPSAwLjEkLiANCg0KKipEYXRhKio6IDEwLjIsIDkuOCwgMTAuMCwgMTAuMiwgOS45Lg0KDQoqKk1hbnVhbCBTb2x1dGlvbioqDQoNCiogKipMaWtlbGlob29kKio6ICRMKFxtdSkgPSAoMlxwaVxzaWdtYV4yKV57LW4vMn0gXGV4cFxsZWZ0XHstXGZyYWN7MX17MlxzaWdtYV4yfSBcc3VtX3tpPTF9Xm4gKHhfaSAtIFxtdSleMlxyaWdodFx9JC4NCg0KKiAqKkxvZy1saWtlbGlob29kKio6ICRcZWxsKFxtdSkgPSBcbG9nIEwoXG11KSA9IC1cZnJhY3tufXsyfVxsb2coMlxwaVxzaWdtYV4yKSAtIFxmcmFjezF9ezJcc2lnbWFeMn0gXHN1bV97aT0xfV5uICh4X2kgLSBcbXUpXjIkDQoNCiogKipTY29yZSBFcXVhdGlvbioqOiAkUyhcbXUpID0gXGZyYWN7XHBhcnRpYWwgXGVsbChcbXUpfXtccGFydGlhbCBcbXV9ID0gXGZyYWN7MX17XHNpZ21hXjJ9IFxzdW1fe2k9MX1ebiAoeF9pIC0gXG11KSQNCg0KKiAqKk1MRSoqICRcaGF0e1xtdX0gPSBcYmFye3h9ID0gXGZyYWN7MX17bn0gXHN1bV97aT0xfV5uIHhfaSA9IFxmcmFjezEwLjIrOS44KzEwLjArMTAuMis5Ljl9ezV9ID0gMTAuMDIkDQogICAgDQoqICoqSW5mb3JtYXRpb24qKiAkSShcbXUpID0gLVxmcmFje1xwYXJ0aWFsXjIgXGVsbChcbXUpfXtccGFydGlhbCBcbXVeMn0gID0gXGZyYWN7bn17XHNpZ21hXjJ9ID0gXGZyYWN7NX17MC4xfSA9IDUwJA0KDQoNCldpdGggdGhlIGFib3ZlIG1hbnVhbCB3b3JrLCB3ZSBuZXh0IGRlZmluZSB0aGUgdGhyZWUgdGVzdCBzdGF0aXN0aWM6DQoNCg0KKipXYWxkIFRlc3QqKg0KDQokJA0KVyA9IChcaGF0e1xtdX0gLSBcbXVfMCleMiBJKFxoYXR7XG11fSkgPSAoMC4wMileMiBcdGltZXMgNTAgPSAwLjAwMDQgXHRpbWVzIDUwID0gMC4wMg0KJCQNCg0KKipTY29yZSBUZXN0KioNCg0KJCQNClUoXG11KSA9IFxmcmFje259e1xzaWdtYV4yfShcYmFye3h9IC0gXG11KQ0KJCQNCg0KQXQgJFxtdV8wPTEwJDogJFUoMTApID0gNTAgXHRpbWVzICgxMC4wMiAtIDEwKSA9IDEkDQoNCiQkDQpTID0gVSgxMCleMiBJXnstMX0oMTApID0gMV4yIFx0aW1lcyBcZnJhY3sxfXs1MH0gPSAwLjAyDQokJA0KDQoqKkxpa2VsaWhvb2QgUmF0aW8gVGVzdCoqDQoNCiQkDQpcZWxsKFxtdSkgPSAtXGZyYWN7bn17Mn1cbG9nKDJccGlcc2lnbWFeMikgLSBcZnJhY3sxfXsyXHNpZ21hXjJ9XHN1bSh4X2kgLSBcbXUpXjINCiQkDQoNCiQkDQpcZWxsKFxtdV8wKSA9IC1cZnJhY3tufXsyfVxsb2coMlxwaVxzaWdtYV4yKSAtIFxmcmFjezF9ezJcc2lnbWFeMn1cc3VtKHhfaSAtIFxtdV8wKV4yDQokJA0KDQoNCiQkDQpcZWxsKFxoYXR7XG11fSkgLSBcZWxsKFxtdV8wKSA9IC1cZnJhY3sxfXsyXHNpZ21hXjJ9W1xzdW0oeF9pIC0gXGhhdHtcbXV9KV4yIC0gXHN1bSh4X2kgLSBcbXVfMCleMl0NCiQkDQoNCiQkDQo9IC1cZnJhY3sxfXswLjJ9WzAuMTMgLSAwLjEyOF0gPSAtNSBcdGltZXMgMC4wMDIgPSAtMC4wMQ0KJCQNCg0KJCQNClxMYW1iZGEgPSAyIFx0aW1lcyAwLjAxID0gMC4wMi4NCiQkDQoNClwNCg0KKipSIFZlcmlmaWNhdGlvbioqDQoNCmBgYHtyfQ0KIyBOb3JtYWwgZXhhbXBsZQ0KeCA8LSBjKDEwLjIsIDkuOCwgMTAuMCwgMTAuMiwgOS45KQ0KbiA8LSBsZW5ndGgoeCkNCnNpZ21hMiA8LSAwLjENCm11MCA8LSAxMA0KDQptdV9tbGUgPC0gbWVhbih4KQ0KDQojIFdhbGQgdGVzdA0KVyA8LSAobXVfbWxlIC0gbXUwKV4yICogKG4vc2lnbWEyKSAgICMgV2FsZCB0ZXN0IHN0YXRpc3RpYw0KDQojIFNjb3JlIHRlc3QNClUgPC0gKG4vc2lnbWEyKSAqIChtdV9tbGUgLSBtdTApDQpJIDwtIG4vc2lnbWEyDQpTIDwtIFVeMi9JICAgICMgUmFvIHRlc3Qgc3RhdGlzdGljDQoNCiMgTGlrZWxpaG9vZCByYXRpbyB0ZXN0DQpsbF9tbGUgPC0gc3VtKGRub3JtKHgsIG11X21sZSwgc3FydChzaWdtYTIpLCBsb2cgPSBUUlVFKSkgICMgbG9nID0gVFJVRSB5aWVsZHMgbG9nLWxpa2VsaWhvb2QNCmxsX251bGwgPC0gc3VtKGRub3JtKHgsIG11MCwgc3FydChzaWdtYTIpLCBsb2cgPSBUUlVFKSkNCkxSIDwtIDIqKGxsX21sZSAtIGxsX251bGwpICAgICMgbG9nLWxpa2VsaWhvb2QgcmF0aW8gdGVzdCBzdGF0aXN0aWMNCg0KY2F0KCIgIFdhbGQ6IiwgVywgInAtdmFsdWU6IiwgMS1wY2hpc3EoVywgMSksICJcbiIsDQogICAgIlNjb3JlOiIsIFMsICJwLXZhbHVlOiIsIDEtcGNoaXNxKFMsIDEpLCAiXG4iLA0KICAgICIgICBMUjoiLCBMUiwgInAtdmFsdWU6IiwgMS1wY2hpc3EoTFIsIDEpLCAiXG4iKQ0KYGBgDQoNClwNCg0KIyBQcmFjdGljYWwgRXhhbXBsZTogTXVsdGlwbGUgUGFyYW1ldGVycw0KDQpJbiB0aGUgc2luZ2xlLXBhcmFtZXRlciBjYXNlLCB0aGUgRmlzaGVyIGluZm9ybWF0aW9uIG51bWJlciBpcyByZWxhdGl2ZWx5IHN0cmFpZ2h0Zm9yd2FyZCB0byBkZXJpdmUuIEZvciBtdWx0aS1wYXJhbWV0ZXIgY2FzZXMsIGhvd2V2ZXIsIHdlIG5lZWQgdG8gb2J0YWluIHRoZSBGaXNoZXIgaW5mb3JtYXRpb24gbWF0cml4IGluIG9yZGVyIHRvIGNvbmR1Y3QgYm90aCB0aGUgV2FsZCBhbmQgc2NvcmUgdGVzdHMuIFRoaXMgc2VjdGlvbiB1c2VzIHRoZSBXZWlidWxsIGRpc3RyaWJ1dGlvbiBhcyBhbiBleGFtcGxlIHRvIGlsbHVzdHJhdGUgdGhlIHByb2NlZHVyZSBmb3IgdGhlIHRocmVlIGNoaS1zcXVhcmUgdGVzdHMuDQoNCiMjIENvbXBvbmVudHMgZm9yIHRoZSBUaHJlZSAkXGNoaV4yJCBUZXN0cw0KDQpJbiB0aGlzIHN1YnNlY3Rpb24sIHdlIHVzZSB0aGUgZ2FtbWEgZGlzdHJpYnV0aW9uIGFzIGFuIGV4YW1wbGUgdG8gaWxsdXN0cmF0ZSBob3cgdG8gdGVzdCB0aGUgc2lnbmlmaWNhbmNlIG9mIHBhcmFtZXRlcnMuIFNpbmNlIHRoZSBnYW1tYSBkaXN0cmlidXRpb24gaXMgY29tbW9ubHkgZXhwcmVzc2VkIGluIHR3byBkaXN0aW5jdCBmb3JtdWxhdGlvbnMsIHdlIGFkb3B0IHRoZSBmb2xsb3dpbmcgcGFyYW1ldGVyaXphdGlvbi4NCg0KVGhlIGdhbW1hIGRpc3RyaWJ1dGlvbiB3aXRoIHNoYXBlIHBhcmFtZXRlciAkXGFscGhhID4gMCQgYW5kIHJhdGUgcGFyYW1ldGVyICRcYmV0YSA+IDAkIGhhcyBwcm9iYWJpbGl0eSBkZW5zaXR5IGZ1bmN0aW9uOg0KDQokJA0KZih4OyBcYWxwaGEsIFxiZXRhKSA9IFxmcmFje1xiZXRhXntcYWxwaGF9fXtcR2FtbWEoXGFscGhhKX0geF57XGFscGhhLTF9IGVeey1cYmV0YSB4fSwgXHF1YWQgeCA+IDANCiQkDQoNClRoZSBjYXNlIHdoZXJlIHRoZSBzaGFwZSBwYXJhbWV0ZXIgJFxhbHBoYSA9IDEkIHJlZHVjZXMgdGhlIGdhbW1hIHRvIGFuIGV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbi4gVGh1cywgdGVzdGluZyB0aGlzIG51bGwgaHlwb3RoZXNpcyBpbmRpY2F0ZXMgd2hldGhlciB0aGUgZ2FtbWEgZGlzdHJpYnV0aW9uIHByb3ZpZGVzIGEgc2lnbmlmaWNhbnRseSBiZXR0ZXIgZml0IG9yIGxlYWRzIHRvIG92ZXJmaXR0aW5nIGZvciB0aGUgZ2l2ZW4gZGF0YS4NCg0KQXNzdW1lICRce3hfMSwgeF8yLCBcY2RvdHMsIHhfblx9IFx4cmlnaHRhcnJvd3tpLmkuZH0gXHRleHR7Z2FtbWF9KFxhbHBoYSwgXGJldGEpJC4gJFxwc2koXGFscGhhKSQgZGVub3RlcyB0aGUgKipkaWdhbW1hIGZ1bmN0aW9uKioNCg0KJCQNClxwc2koeikgPSBcZnJhY3tkfXtken0gXGxuIFxHYW1tYSh6KSA9IFxmcmFje1xHYW1tYScoeil9e1xHYW1tYSh6KX0uDQokJA0KDQoqKlIgZnVuY3Rpb25zKiogYGRpZ2FtbWEoeilgLCBgdHJpZ2FtbWEoeilgLCBgdGV0cmFnYW1tYSh6KWAgZXZhbHVhdGUgJFxwc2koeCksIFxwc2leXHByaW1lICh6KSQgYW5kICRccHNpXntccHJpbWVccHJpbWV9KHopJCwgcmVzcGVjdGl2ZWx5Lg0KDQoNClRoZSBvYmplY3RpdmUgaXMgdG8gdGVzdCAkSF8wOiBcYWxwaGEgPSAxJC4gVGhlIG1ham9yIGNvbXBvbmVudHMgcmVxdWlyZWQgZm9yIHRlc3RpbmcgdGhlIGh5cG90aGVzaXMgYXJlIGdpdmVuIGJlbG93LiAgDQoNCioqTG9nLWxpa2VsaWhvb2QqKg0KDQokJA0KXGVsbChcYWxwaGEsIFxiZXRhKSA9IG5cYWxwaGFcbG9nXGJldGEgLSBuXGxvZ1xHYW1tYShcYWxwaGEpICsgKFxhbHBoYS0xKVxzdW1fe2k9MX1ebiBcbG9nIHhfaSAtIFxiZXRhXHN1bV97aT0xfV5uIHhfaQ0KJCQNCg0KKipTY29yZSBFcXVhdGlvbnMqKg0KDQokJA0KXGZyYWN7XHBhcnRpYWxcZWxsfXtccGFydGlhbFxhbHBoYX0gPSBuXGxvZ1xiZXRhIC0gblxwc2koXGFscGhhKSArIFxzdW1fe2k9MX1ebiBcbG9nIHhfaSA9IDANCiQkDQoNCiQkDQpcZnJhY3tccGFydGlhbFxlbGx9e1xwYXJ0aWFsXGJldGF9ID0gXGZyYWN7blxhbHBoYX17XGJldGF9IC0gXHN1bV97aT0xfV5uIHhfaSA9IDANCiQkDQoNCioqTWF4aW11bSBMaWtlbGlob29kIEVzdGltYXRpb24qKg0KDQpUaGUgbWF4aW11bSBsaWtlbGlob29kIGVzdGltYXRlcyBvZiAkXGFscGhhJCBhbmQgJFxiZXRhJCwgZGVub3RlZCBieSAkXGhhdHtcYWxwaGF9JCBhbmQgJFxoYXR7XGJldGF9JCwgYXJlIHRoZSBzb2x1dGlvbnMgdG8gdGhlIGFib3ZlICoqc3lzdGVtKiogb2Ygc2NvcmUgZXF1YXRpb25zLg0KDQpcDQoNCioqSW5mb3JtYXRpb24gTWF0cml4KioNCg0KJFxtYXRoY2Fse0l9X24oMiwyKSQgaXMgdGhlICgyLDIpIGVsZW1lbnQgb2YgdGhlICoqRmlzaGVyIGluZm9ybWF0aW9uIG1hdHJpeCoqIG9mICRcYWxwaGEkIGFuZCAkXGJldGEkIGJhc2VkIG9uIGVudGlyZSBzYW1wbGUgd2l0aCBzaXplICRuJDoNCg0KJCQNClxtYXRoY2Fse0l9X24oXGFscGhhLCBcYmV0YSkgPSAtIEVcYmVnaW57cG1hdHJpeH0gXGZyYWN7XHBhcnRpYWxeMlxlbGx9e1xwYXJ0aWFsIFxhbHBoYV4yfSAmIFxmcmFje1xwYXJ0aWFsXjJcZWxsfXtccGFydGlhbFxhbHBoYVxwYXJ0aWFsXGJldGF9IFxcIFxmcmFje1xwYXJ0aWFsXjJcZWxsfXtccGFydGlhbFxiZXRhXHBhcnRpYWxcYWxwaGF9JiBcZnJhY3tccGFydGlhbF4yXGVsbH17XHBhcnRpYWxcYmV0YV4yfSBcZW5ke3BtYXRyaXh9ID0gLVxiZWdpbntwbWF0cml4fSBuXHBzaScoXGFscGhhKSAmIFxmcmFje259e1xiZXRhfSBcXCBcZnJhY3tufXtcYmV0YX0gJiBcZnJhY3tuXGFscGhhfXtcYmV0YV4yfSBcZW5ke3BtYXRyaXh9DQokJA0KDQoNCioqUmVtYXJrKio6IEZvciB0aGUgbGlrZWxpaG9vZCByYXRpbyB0ZXN0LCB3ZSBtdXN0IG9idGFpbiBib3RoIHRoZSByZXN0cmljdGVkIGFuZCB1bnJlc3RyaWN0ZWQgbWF4aW11bSBsaWtlbGlob29kIGVzdGltYXRlcyAoTUxFcykuIFRoZSByZXN0cmljdGVkIE1MRSBpcyBkZXJpdmVkIHVuZGVyIHRoZSBudWxsIGh5cG90aGVzaXMgJEhfMDogXGFscGhhID0gMSQgKGkuZS4sICRcYWxwaGEkIGZpeGVkIHRvIGEgY29uc3RhbnQpLCB3aGlsZSB0aGUgdW5yZXN0cmljdGVkIE1MRSB0cmVhdHMgYm90aCAkXGFscGhhJCBhbmQgJFxiZXRhJCBhcyB1bmtub3duIHBhcmFtZXRlcnMuIEluIGdlbmVyYWwsIHRoZXNlIE1MRXMgbXVzdCBiZSBvYnRhaW5lZCB1c2luZyBudW1lcmljYWwgYXBwcm94aW1hdGlvbiBtZXRob2RzLg0KDQoNCg0KIyMgTnVtZXJpY2FsIEltcGxlbWVudGF0aW9uDQoNClRoZSBkYXRhc2V0IHVzZWQgaW4gdGhpcyBleGFtcGxlIGNvbnRhaW5zIG1lYXN1cmVtZW50cyBvZiBtaWNyb3R1YnVsZSBjYXRhc3Ryb3BoZSB0aW1lcyAodGhlIHRpbWUgdW50aWwgYSBtaWNyb3R1YnVsZSBzdG9wcyBncm93aW5nKS4gSW4gdGhlaXIgQ2VsbCBwYXBlciAoMjAxMSksIEdhcmRuZXIsIFphbmljLCBhbmQgY29sbGVhZ3VlcyAoR2FyZG5lciwgWmFuaWMsIGV0IGFsLiAoMjAxMSkuIENlbGwsIDE0Nyg1KSwgMTA5Mi0xMTAzLikgZXhwbGljaXRseSBtb2RlbGVkIHRoZXNlIGNhdGFzdHJvcGhlIHRpbWVzIHVzaW5nIGEgKipnYW1tYSBkaXN0cmlidXRpb24qKi4gRm9yIGlsbHVzdHJhdGl2ZSBwdXJwb3NlLCB3ZSBvbmx5IHVzZSBjb21wbGV0ZSB0aW1lcyBpbiB0aGlzIGV4YW1wbGUuDQoNCldlIGZpcnN0IGxvYWQgdGhlIGRhdGEgaW50byBSIGFuZCB0aGVuIGZvbGxvdyB0aGUgc3RlcHMgYWJvdmUgdG8gcGVyZm9ybSB0aGUgdGhyZWUgbGlrZWxpaG9vZC1iYXNlZCAkXGNoaV4yJCB0ZXN0cy4NCg0KYGBge3J9DQp0aW1lMmV2ZW50IDwtIHJlYWQudGFibGUoImh0dHBzOi8vcGVuZ2RzY2kuZ2l0aHViLmlvL1NUQTUwNi93MTEvVGltZTJDYXRhc3Ryb3BoZS50eHQiKQ0KY29sbmFtZXModGltZTJldmVudCkgPC0gInRpbWUiDQp4IDwtIHRpbWUyZXZlbnQkdGltZQ0KYGBgDQoNCioqTG9nbGlrZWxpaG9vZCBmdW5jdGlvbioqIA0KDQpUaGUgZm9sbG93aW5nIFIgZnVuY3Rpb24gZXZhbHVhdGUgdGhlIGxvZ2xpa2VsaWhvb2QgZnVuY3Rpb24gYW5kIHdpbGwgYmUgdXNlZCB0byBmaW5kIHRoZSB1bnJlc3RyaWN0ZWQgTUxFIG9mICRcYWxwaGEkIGFuZCAkXGJldGEkLiANCg0KYGBge3J9DQojIGxvZ2xpa2VsaWhvb2QgZnVuY3Rpb24NCmxvZ19saWtlbGlob29kIDwtIGZ1bmN0aW9uKHBhcmFtKSB7DQogIGFscGhhIDwtIHBhcmFtWzFdIA0KICBiZXRhIDwtIHBhcmFtWzJdDQogIG4gPC0gbGVuZ3RoKHgpDQogIHN1bV94IDwtIHN1bSh4KQ0KICBzdW1fbG9neCA8LSBzdW0obG9nKHgpKQ0KICAjIw0KICBsbCA8LSBuICogYWxwaGEgKiBsb2coYmV0YSkgLSBuICogbG9nKGdhbW1hKGFscGhhKSkgKyANCiAgICAgICAgIChhbHBoYSAtIDEpICogc3VtX2xvZ3ggLSBiZXRhICogc3VtKHgpDQogIGxsDQp9DQpgYGANCg0KKipTY29yZSBFcXVhdGlvbnMqKjogVGhlIGZvbGxvd2luZyBSIGZ1bmN0aW9uIHJldHVybnMgYSB2ZWN0b3Igc2NvcmUgZnVuY3Rpb25zLCBjb21wdXRlZCBmcm9tIHRoZSBkYXRhIHZhbHVlcyBhbmQgcGFyYW1ldGVyIGVzdGltYXRlcy4NCg0KYGBge3J9DQojIFNjb3JlIGVxdWF0aW9ucyAoc2hvdWxkIGJlIHplcm8gYXQgc29sdXRpb24pDQpzY29yZV9lcXUgPC1mdW5jdGlvbihwYXIpew0KICAgIGFscGhhIDwtIHBhclsxXQ0KICAgIGJldGEgPC0gcGFyWzJdDQogICAgIyMNCiAgICBuIDwtIGxlbmd0aCh4KQ0KICAgIHN1bV94IDwtIHN1bSh4KQ0KICAgIHN1bV9sb2d4IDwtIHN1bShsb2coeCkpDQogICAgIyMNCiAgICBzY29yZV9hbHBoYSA8LSBuICogbG9nKGJldGEpIC0gbiAqIGRpZ2FtbWEoYWxwaGEpICsgc3VtX2xvZ3gNCiAgICBzY29yZV9iZXRhIDwtIG4gKiBhbHBoYSAvIGJldGEgLSBzdW1feA0KICAgIGMoc2NvcmVfYWxwaGEsIHNjb3JlX2JldGEpDQogIH0NCmBgYA0KDQoqKkZpc2hlciBJbmZvcm1hdGlvbiBNYXRyaXgqKiBpcyBjb2RlZCBpbiB0aGUgZm9sbG93aW5nDQoNCmBgYHtyfQ0KRmlzaGVySW5mbyA8LSBmdW5jdGlvbihwYXIpew0KICAgICMgRmlzaGVyIGluZm9ybWF0aW9uIG1hdHJpeCAobmVnYXRpdmUgZXhwZWN0ZWQgSGVzc2lhbikNCiAgICAjIFVzZWQgZm9yIE5ld3Rvbi1SYXBoc29uIHVwZGF0ZQ0KICAgICMgSXQgY29udGFpbnMgb25seSBwYXJhbWV0ZXJzDQogICAgYWxwaGEgPC0gcGFyWzFdDQogICAgYmV0YSA8LSBwYXJbMl0NCiAgICANCiAgICAjIEZpc2hlciBJbmZvIGNlbGwNCiAgICBJXzExIDwtIG4gKiB0cmlnYW1tYShhbHBoYSkNCiAgICBJXzEyIDwtIC1uIC8gYmV0YQ0KICAgIElfMjIgPC0gbiAqIGFscGhhIC8gYmV0YV4yDQogICAgDQogICAgIyBJbmZvcm1hdGlvbiBtYXRyaXgNCiAgICBGaXNoZXIgPC0gbWF0cml4KGMoSV8xMSwgSV8xMiwgSV8xMiwgSV8yMiksIG5yb3cgPSAyLCBieXJvdyA9IFRSVUUpDQogICAgRmlzaGVyICAgDQp9DQpgYGANCg0KDQojIyBNYXhpbXVtIExpa2VsaWhvb2QgRXN0aW1hdGlvbg0KDQpJbnN0ZWFkIG9mIHJlbHlpbmcgb24gc3BlY2lhbCBidWlsdC1pbiBSIGZ1bmN0aW9ucyB0aGF0IGNvbXB1dGUgbWF4aW11bSBsaWtlbGlob29kIGVzdGltYXRlcyAoTUxFcykgZm9yIHNwZWNpZmljIGRpc3RyaWJ1dGlvbiBmYW1pbGllcywgd2UgaW50cm9kdWNlIGEgZ2VuZXJhbCBwdXJwb3NlIG9wdGltaXphdGlvbiBmdW5jdGlvbiBgb3B0aW0oKWAgZm9yIG9idGFpbmluZyBNTEVzIGZvciBhcmJpdHJhcnkgZGlzdHJpYnV0aW9ucy4gU3BlY2lmaWNhbGx5LCB3ZSB3aWxsIGRlcml2ZSB0aGUgTUxFcyBvZiB0aGUgcGFyYW1ldGVycyAkXGFscGhhJA0KIGFuZCAkXGJldGEkLCBhbG9uZyB3aXRoIHRoZSBjb3JyZXNwb25kaW5nIEZpc2hlciBpbmZvcm1hdGlvbiBtYXRyaXgsIHdoaWNoIHdpbGwgYmUgdXNlZCBpbiB0aGUgU2NvcmUgYW5kIFdhbGQgdGVzdHMuDQoNCmBvcHRpbSgpYCBpcyBhIHdyYXBwZXIgZnVuY3Rpb24gdGhhdCBwcm92aWRlcyBhY2Nlc3MgdG8gc2V2ZXJhbCBvcHRpbWl6YXRpb24gYWxnb3JpdGhtcy4gVGhlIHNwZWNpZmljIG51bWVyaWNhbCBtZXRob2QgaW52b2tlZCBpbnRlcm5hbGx5IGRlcGVuZHMgb24gdGhlIGluZm9ybWF0aW9uIHN1cHBsaWVkIHRvIHRoZSBmdW5jdGlvbi4gSW4gcHJhY3RpY2UsIGEgcG9wdWxhciB2YXJpYW50IG9mIHRoZSBOZXd0b27igJNSYXBoc29uIGFsZ29yaXRobSBrbm93biBhcyB0aGUgQnJveWRlbuKAk0ZsZXRjaGVy4oCTR29sZGZhcmLigJNTaGFubm8gKEJGR1MpIGFsZ29yaXRobSBpcyBmcmVxdWVudGx5IGVtcGxveWVkLiBCRkdTIHJlcXVpcmVzIHRoZSBncmFkaWVudCAoc2NvcmUgdmVjdG9yKSB0byBlZmZpY2llbnRseSBndWlkZSB0aGUgc2VhcmNoIHRvd2FyZCB0aGUgb3B0aW1hbCBzb2x1dGlvbi4gVGhlIGZvbGxvd2luZyBSIGNvZGUgaWxsdXN0cmF0ZXMgaG93IHRvIHVzZSB0aGUgQkZHUyBtZXRob2QgdmlhIGBvcHRpbSgpYC4NCg0KDQpgYGB7cn0NCiB4IDwtIHRpbWUyZXZlbnQkdGltZQ0KIG4gPSBsZW5ndGgoeCkNCiAjIGluaXRpYWwgdmFsdWVzDQojIyMNCiByZXN1bHQgPC0gb3B0aW0oDQogICAgICAgICAgcGFyID0gYygxMDAsMC4xKSwgDQogICAgICAgICAgI25lZWQgdG8gcHJvdmlkZSBpbml0aWFsIHZhbHVlcyB0byBzdGFydCB0aGUgaXRlcmF0aW9uLg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBDaG9vc2luZyBhcHByb3ByaWF0ZSBpbml0aWFsIHZhbHVlcyBpcyBjcml0aWNhbC4NCiAgICAgICAgICBmbiA9IGxvZ19saWtlbGlob29kLCAgICAgICMgQ2F1dGlvbjogbmVlZCBuZWdhdGl2ZSBsb2ctbGlrZWxpaG9vZA0KICAgICAgICAgIGdyID0gc2NvcmVfZXF1LCAgICAgICAgICAgIyBhbHNvIG5lZSBuZWdhdGl2ZSBzY29yZQ0KICAgICAgICAgIG1ldGhvZCA9ICJCRkdTIiwgICAgICAgICAgIyBjYWxsaW5nIEJGR1MgYWxnb3JpdGhtDQogICAgICAgICAgaGVzc2lhbiA9IFRSVUUsICAgICAgICAgICAjIHJldHVybiBIZXNzaWFuIG1hdHJpeA0KICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KCAgICAgICAgICAgIyBzb21lIGNvbnRyb2xzIGluIG51bWVyaWNhbCBpdGVyYXRpb24NCiAgICAgICAgICAgICAgICBmbnNjYWxlID0gLTEsICAgICAgICMgdHVybiB0aGUgbWluaW1pemF0aW9uIHRvIG1heGltaXphdGlvbiBwcm9ibGVtDQogICAgICAgICAgICAgICAgbWF4aXQgPSAxMDAwLCAgICAgICAjIHN0b3BwaW5nIHJ1bGUgMTogY2FwIG51bWJlciBvZiBpdGVyYXRpb25zDQogICAgICAgICAgICAgICAgcmVsdG9sID0gMWUtOCwgICAgICAjIHN0b3BwaW5nIHJ1bGU6IHByZWNpc2lvbiBjb250cm9sDQogICAgICAgICAgICAgICAgUkVQT1JUID0gMTAgICAgICAgICAjIFRoZSBhbGdvcml0aG0gd2lsbCBwcmludCBwcm9ncmVzcyB1cGRhdGVzIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBldmVyeSAxMCBpdGVyYXRpb25zDQogICAgICAgICAgKQ0KICApDQogcmVzdWx0DQpgYGANCg0KRG91YmxlIGNoZWNrIHdpdGggdGhlIGhlc3NpYW4gbWF0cml4IHVzaW5nIHRoZSBkZXJpdmVkIGZvcm11bGENCg0KYGBge3J9DQpGaXNoZXIgPC0gRmlzaGVySW5mbyhyZXN1bHQkcGFyKQ0KRmlzaGVyDQpgYGANCg0KV2hpY2ggaXMgY29uc2lzdGVudCB3aXRoIHRoZSAqKmhlc3NpYW4gbWF0cml4KiogaW4gdGhlIG91dHB1dCBvZiBgb3B0aW0oKWAuDQoNCg0KVGhlIHZhcmlhbmNlIGFuZCBjb3ZhcmlhbmNlIG1hdHJpeCBjYW4gYmUgYXBwcm94aW1hdGVkIGJ5IGludmVydGluZyB0aGUgKipGaXNoZXIgSW5mb3JtYXRpb24gTWF0cml4Kiogb3IgdGhlIGludmVyc2Ugb2YgdGhlIG5lZ2F0aXZlIEhlc3NpYW4gbWF0cml4IHJldHVybmVkIGZyb20gYG9wdGltKClgLg0KDQoNCmBgYHtyfQ0KdmFyY292IDwtIHNvbHZlKC1yZXN1bHQkaGVzc2lhbikgICAjIHNvbHZlKCkgaXMgYSBtYXRyaXggaW52ZXJzaW9uIGZ1bmN0aW9uDQp2YXJjb3YNCmBgYA0KDQpUaGF0IGlzLCAkXHRleHR7dmFyfShcYWxwaGEpID0gNC40Mlx0aW1lcyAxMF57LTJ9JCBhbmQgJFx0ZXh0e3Zhcn0oXGJldGEpID0gMi43Mlx0aW1lcyAxMF57LTd9JC4NCg0KDQojIyBUd28gJFxjaGleMiQgVGVzdHMgDQoNClRoZSB0aHJlZSAkXGNoaV4yJCB0ZXN0cyBhcmUgZ2l2ZW4gcmVzcGVjdGl2ZWx5IGluIHRoZSBmb2xsb3dpbmcuDQoNCiMjIyBMaWtlbGlob29kIFJhdGlvIFRlc3QNCg0KV2UgaGF2ZSBmb3VuZCB0aGUgdW4tcmVzdHJpY3RpdmUgTUxFcyBvZiAkXGFscGhhJCBhbmQgJFxiZXRhJDoNCg0KYGBge3J9DQpNTEUgPC0gcmVzdWx0JHBhcg0KTUxFDQpgYGANCg0KV2Ugbm93IGZpbmQgcmVzdHJpY3RpdmUgTUxFIG9mICRcYmV0YSQgIHVuZGVyICRIXzA6IFxhbHBoYSA9IDEkLiBUaGUgb3B0aW1pemF0aW9uIHByb2JsZW1zIGJlY29tZXMgc2luZ2xlIHBhcmFtZXRlciBwcm9ibGVtLg0KDQoNCmBgYHtyfQ0KIyMNCmxvZ2xpayA8LSBmdW5jdGlvbihiZXRhKSBuKmxvZyhiZXRhKS1uIC1iZXRhKnN1bSh4KQ0KIyMNCnNjb3JlIDwtIGZ1bmN0aW9uKGJldGEpIG4vYmV0YSAtIHN1bSh4KQ0KIyMNCiB4IDwtIHRpbWUyZXZlbnQkdGltZQ0KIG4gPSBsZW5ndGgoeCkNCiByZXN1bHQwIDwtIG9wdGltKA0KICAgICAgICAgIHBhciA9IDAuMDUsICAgICAgICAgICAgICMgbmVlZCB0byBwcm92aWRlIGluaXRpYWwgdmFsdWVzIHRvIHN0YXJ0IHRoZSBpdGVyYXRpb24uDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIENob29zaW5nIGFwcHJvcHJpYXRlIGluaXRpYWwgdmFsdWVzIGlzIGNyaXRpY2FsLg0KICAgICAgICAgIGZuID0gbG9nbGlrLCAgICAgICAgICAgICAgIyBDYXV0aW9uOiBuZWVkIG5lZ2F0aXZlIGxvZy1saWtlbGlob29kDQogICAgICAgICAgZ3IgPSBzY29yZSwgICAgICAgICAgICAgICAjIGFsc28gbmVlIG5lZ2F0aXZlIHNjb3JlDQogICAgICAgICAgbWV0aG9kID0gIkJGR1MiLCAgICAgICAgICAjIGNhbGxpbmcgQkZHUyBhbGdvcml0aG0NCiAgICAgICAgICBoZXNzaWFuID0gVFJVRSwgICAgICAgICAgICMgcmV0dXJuIEhlc3NpYW4gbWF0cml4DQogICAgICAgICAgY29udHJvbCA9IGxpc3QoICAgICAgICAgICAjIHNvbWUgY29udHJvbHMgaW4gbnVtZXJpY2FsIGl0ZXJhdGlvbg0KICAgICAgICAgICAgICAgIGZuc2NhbGUgPSAtMSwgICAgICAgIyB0dXJuIHRoZSBtaW5pbWl6YXRpb24gdG8gbWF4aW1pemF0aW9uIHByb2JsZW0NCiAgICAgICAgICAgICAgICBtYXhpdCA9IDEwMDAsICAgICAgICMgc3RvcHBpbmcgcnVsZSAxOiBjYXAgbnVtYmVyIG9mIGl0ZXJhdGlvbnMNCiAgICAgICAgICAgICAgICByZWx0b2wgPSAxZS04LCAgICAgICMgc3RvcHBpbmcgcnVsZTogcHJlY2lzaW9uIGNvbnRyb2wNCiAgICAgICAgICAgICAgICBSRVBPUlQgPSAxMCAgICAgICAgICMgVGhlIGFsZ29yaXRobSB3aWxsIHByaW50IHByb2dyZXNzIHVwZGF0ZXMgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGV2ZXJ5IDEwIGl0ZXJhdGlvbnMNCiAgICAgICAgICApDQogICkNCiByZXN1bHQwDQpgYGANCg0KDQpUaGF0IGlzIHRoZSByZXN0cmljdGl2ZSBNTEUgb2YgJFxiZXRhJCwgZGVub3RlZCBieSAkXGhhdHtcYmV0YX09MC4wMDIyNjkwNjckLg0KDQpUaGUgbGlrZWxpaG9vZCByYXRpbyB0ZXN0IHN0YXRpc3RpYyBpcw0KDQokJA0KTFIgPSDiiJIyW1xlbGwoXGhhdHtcYWxwaGF9LCBcaGF0e1xiZXRhfSniiJJcZWxsKDEsXGhhdHtcYmV0YX0pXSBcdG8gXGNoaV4yXzEuDQokJA0KDQpUaGUgUiBjb2RlIHRoYXQgZXZhbHVhdGVzIHRoZSBhYm92ZSB0ZXN0IHN0YXRpc3RpYyBpcyBnaXZlbiBieQ0KDQpgYGB7cn0NCiB4IDwtIHRpbWUyZXZlbnQkdGltZQ0KIG4gPSBsZW5ndGgoeCkNCiAjIw0KIExSID0gLTIqKGxvZ2xpayhyZXN1bHQwJHBhcikgLSBsb2dfbGlrZWxpaG9vZChyZXN1bHQkcGFyKSkNCiBMUg0KYGBgDQoNCg0KU2luY2UgdGhlIGNoaS1zcXVhcmUgdGVzdCBpcyBhbHdheXMgcmlnaHQtdGFpbGVkLCB0aGUgcC12YWx1ZSBiYXNlZCBvbiB0aGUgdGVzdCBzdGF0aXN0aWMgYWJvdmUgaXMgZ2l2ZW4gYnkgJHAgPSBQKFxjaGleMl8xID4gTFIpJC4gVGhlIHAtdmFsdWUgY2FuIGJlIG9idGFpbmVkIHVzaW5nIHRoZSBmb2xsb3dpbmcgUiBjb2RlLg0KDQpgYGB7cn0NCnB2YWwgPC0gMSAtIHBjaGlzcShMUiwgZGYgPSAxKQ0KcHZhbA0KYGBgDQoNClRoZSBwLXZhbHVlIGlzIG5lYXJseSB6ZXJvLCBsZWFkaW5nIHRvIHRoZSByZWplY3Rpb24gb2YgdGhlIG51bGwgaHlwb3RoZXNpcyAkSF8wOiBcYWxwaGEgPSAxJC4NCg0KDQojIyMgV2FsZCAgJFxjaGleMiQgIFRlc3QNCg0KVGhlIFdhbGQgJFxjaGleMiQgdGVzdCBzdGF0aXN0aWNzIGZvciB0aGUgbnVsbCBoeXBvdGhlc2lzICRIXzA6IFxhbHBoYSA9IDEkIGlzIGdpdmVuIGJ5DQoNCiQkDQpXX3tcdGV4dHtXYWxkfX0gPSBbXGZyYWN7XGhhdHtcYWxwaGF9IC0gMX17XHRleHR7c2V9KFxoYXR7XGFscGhhfSl9XV4yID0gXGZyYWN7KFxoYXR7XGFscGhhfS0xKV4yfXtcdGV4dHt2YXJ9KFxoYXR7XGFscGhhfSl9IFx0byBcY2hpXjJfMQ0KJCQNCg0Kd2hlcmUgJFx0ZXh0e1Zhcn0oXGhhdHtcYWxwaGF9KSQgaXMgdGhlIGRpYWdvbmFsIGVsZW1lbnQgb2YgdGhlIGludmVyc2Ugb2YgdGhlIG9ic2VydmVkIEZpc2hlciBpbmZvcm1hdGlvbiBtYXRyaXggKGkuZS4sIHRoZSB2YXJpYW5jZeKAk2NvdmFyaWFuY2UgbWF0cml4KS4gVGhpcyBtZWFucyB0aGF0IHRoZSBGaXNoZXIgaW5mb3JtYXRpb24gbWF0cml4IGlzIHJlcXVpcmVkIGZvciB0aGUgV2FsZCB0ZXN0Lg0KDQoNCk5leHQsIHdlIGRlZmluZSB0aGUgdGVzdCBzdGF0aXN0aWMgYW5kIGNhbGN1bGF0ZSB0aGUgcC12YWx1ZSB1c2luZyB0aGUgZm9sbG93aW5nIFIgY29kZQ0KDQpgYGB7cn0NCmFscGhhLmhhdCAgPC0gcmVzdWx0JHBhclsxXSAgICAgIyBiYXNlZCBvbiB0aGUgdW5yZXN0cmljdGVkIGxpa2VsaWhvb2QgZXN0aW1hdGlvbg0Kc2UuYWxwaGEgPC0gc3FydCh2YXJjb3ZbMSwgMV0pICAjIHRoZSBzcXVhcmUgcm9vdCBvZiB0aGUgdG9wLWxlZnQgZGlhZ29uYWwgdmFsdWUNClcgPC0gKGFscGhhLmhhdCAtIDEpXjIvKHNlLmFscGhhKV4yICAgIyBXYWxkIHRlc3Qgc3RhdGlzdGljDQojIw0KcHZhbC5XIDwtIDEgLSBwY2hpc3EoVywgZGYgPSAxKQ0KYyhXID0gVywgcHZhbC5XID0gcHZhbC5XKQ0KYGBgDQoNClRoZSBwLXZhbHVlIGlzIGFsc28gbmVhciAwIGltcGx5aW5nIHRoZSByZWplY3Rpb24gb2YgdGhlIG51bGwgaHlwb3RoZXNpcy4NCg0KDQpcDQoNCiMgUGVyZm9ybWFuY2UgQ29tcGFyaXNvbg0KDQpBdCB0aGUgaGVhcnQgb2YgbW9kZXJuIHN0YXRpc3RpY2FsIGluZmVyZW5jZSBsaWVzIGEgcG93ZXJmdWwgdHJpbzogdGhlIExpa2VsaWhvb2QgUmF0aW8sIFdhbGQsIGFuZCBTY29yZSB0ZXN0cy4gRWFjaCBwcm92aWRlcyBhIGRpc3RpbmN0IGxlbnMgZm9yIHRlc3RpbmcgaHlwb3RoZXNlcywgdHJhbnNmb3JtaW5nIHRoZSBzYW1lIGxpa2VsaWhvb2QgZnVuY3Rpb24gaW50byBhIGNoaS1zcXVhcmVkIHN0YXRpc3RpYyB0aHJvdWdoIGRpZmZlcmVudCBsb2dpY2FsIGFuZCBnZW9tZXRyaWNhbCBwcmluY2lwbGVzLiBUaGVpciBhc3ltcHRvdGljIGVxdWl2YWxlbmNlIHByb3ZpZGVzIGEgcmVhc3N1cmluZyB0aGVvcmV0aWNhbCBmb3VuZGF0aW9uLCB5ZXQgdGhlaXIgZmluaXRlLXNhbXBsZSBkaXZlcmdlbmNlIHJldmVhbHMgYSByaWNoIGxhbmRzY2FwZSBvZiBzdGF0aXN0aWNhbCB0cmFkZS1vZmZzLCB3aGVyZSB0aGUgY2hvaWNlIG9mIHRlc3QgYmFsYW5jZXMgY29uc2lkZXJhdGlvbnMgb2YgYWNjdXJhY3ksIGNvbnZlbmllbmNlLCBpbnZhcmlhbmNlLCBhbmQgY29tcHV0YXRpb25hbCBidXJkZW4uDQoNCg0KKipDb3JlIFBlcmZvcm1hbmNlIENoYXJhY3RlcmlzdGljcyoqDQoNCiogKipMaWtlbGlob29kIFJhdGlvIFRlc3QgKExSVCkqKiAtIGJlc3Qgb3ZlcmFsbCBwZXJmb3JtYW5jZSBpbiBtb3N0IHNpdHVhdGlvbnMNCiAgKyAqKkFjY3VyYWN5Kio6IE1vc3QgcmVsaWFibGUgaW4gZmluaXRlIHNhbXBsZXMsIGNsb3Nlc3QgdG8gbm9taW5hbCBUeXBlIEkgZXJyb3IgcmF0ZXMNCiAgKyAqKlJvYnVzdG5lc3MqKjogSW52YXJpYW50IHRvIHBhcmFtZXRlciB0cmFuc2Zvcm1hdGlvbnMgKHVuaXF1ZSBhZHZhbnRhZ2UpDQogICsgKipDb25zZXJ2YXRpc20qKjogU2xpZ2h0bHkgY29uc2VydmF0aXZlIGluIHZlcnkgc21hbGwgc2FtcGxlcw0KICArICoqQ29tcHV0YXRpb24qKjogTW9zdCBpbnRlbnNpdmUgKHJlcXVpcmVzIGZpdHRpbmcgYm90aCBtb2RlbHMpDQoNCg0KKiAqKldhbGQgVGVzdCoqIC0gZmFzdGVzdCBidXQgbGVhc3QgcmVsaWFibGUgaW4gbm9uLWlkZWFsIGNvbmRpdGlvbnMNCiAgKyAqKkFjY3VyYWN5Kio6IENhbiBiZSBwb29yIGluIHNtYWxsIHNhbXBsZXMsIGVzcGVjaWFsbHkgd2l0aDoNCiAgICAtIFNrZXdlZCBsaWtlbGlob29kcw0KICAgIC0gUGFyYW1ldGVycyBuZWFyIGJvdW5kYXJpZXMgKHZhcmlhbmNlcywgcHJvYmFiaWxpdGllcyBuZWFyIDAvMSkNCiAgICAtIE5vbmxpbmVhciBwYXJhbWV0ZXJzDQogICsgKipCaWFzKio6IE9mdGVuIGFudGktY29uc2VydmF0aXZlIChpbmZsYXRlcyBUeXBlIEkgZXJyb3IpDQogICsgKipDb21wdXRhdGlvbioqOiBGYXN0ZXN0IChvbmx5IG5lZWRzIGZ1bGwgbW9kZWwpDQoNCiogKipTY29yZSBUZXN0IChSYW8pKiotIGVmZmljaWVudCBjb21wcm9taXNlIHdpdGggc3BlY2lmaWMgc3RyZW5ndGhzDQogICsgKipBY2N1cmFjeSoqOiBHb29kIHdoZW4gbnVsbCBoeXBvdGhlc2lzIGlzIHRydWUsIGJ1dCBjYW4gYmUgaW5jb25zaXN0ZW50IHdoZW4gYWx0ZXJuYXRpdmUgaXMgdHJ1ZQ0KICArICoqUG93ZXIqKjogU29tZXRpbWVzIGxlc3MgcG93ZXJmdWwgdGhhbiBMUlQgaW4gc21hbGwgc2FtcGxlcw0KICArICoqQ29tcHV0YXRpb24qKjogTW9kZXJhdGUgKG9ubHkgbmVlZHMgbnVsbCBtb2RlbCkNCiAgKyAqKlNwZWNpYWwgc3RyZW5ndGgqKjogQmVzdCBmb3IgYm91bmRhcnkgdGVzdGluZyBhbmQgaW5pdGlhbCBtb2RlbCBidWlsZGluZw0KDQoNCioqR2VuZXJhbCBSZWNvbW1lbmRhdGlvbnMqKg0KDQoqIFVzZSB0aGUgTFJUIHdoZW46DQogICsgQ29tcHV0YXRpb25hbCBjb3N0IGlzIG5vdCBhIGNvbmNlcm4uDQogICsgU2FtcGxlIHNpemUgaXMgc21hbGwgdG8gbW9kZXJhdGUuDQogICsgd2hlbiBjb21wYXJpbmcgbmVzdGVkIG1vZGVscyBvZiBnZW5lcmFsIHR5cGVzIChHTE1zLCBtaXhlZCBtb2RlbHMsIGV0Yy4pLg0KDQoqIFVzZSB0aGUgV2FsZCBUZXN0IHdoZW46DQogICsgb25seSBoYXZpbmcgdGhlIHVucmVzdHJpY3RlZCBtb2RlbCBvdXRwdXQgKGUuZy4sIGZyb20gYSBzdGFuZGFyZCByZWdyZXNzaW9uIHN1bW1hcnkpLg0KICArIERvaW5nIHF1aWNrIGFwcHJveGltYXRlIGluZmVyZW5jZSBvciBjb25zdHJ1Y3RpbmcgY29uZmlkZW5jZSBpbnRlcnZhbHMuDQogICsgVGhlIHNhbXBsZSBzaXplIGlzIGxhcmdlIGFuZCB0aGUgbGlrZWxpaG9vZCBpcyB3ZWxsLWJlaGF2ZWQgKCRcYXBwcm94JCBxdWFkcmF0aWMpLg0KICArICoqQ2F1dGlvbioqOiBDYW4gYmUgbWlzbGVhZGluZyBmb3IgcGFyYW1ldGVycyBsaWtlIG9kZHMgcmF0aW9zIChhbHdheXMgZXhwb25lbnRpYXRlIGZpcnN0LCB0aGVuIGZvcm0gV2FsZCBDSSBvbiBsb2cgc2NhbGUpLg0KDQoqIFVzZSB0aGUgU2NvcmUgVGVzdCB3aGVuOg0KICArIFRoZSBudWxsIG1vZGVsIGlzIHNpbXBsZXIgdG8gZml0IChlLmcuLCB0ZXN0aW5nIGZvciBhbiBhZGRpdGlvbmFsIHJlZ3Jlc3NvciBpbiBhIGxhcmdlIGRhdGEgc2V0OyBvbmx5IGZpdCB0aGUgcmVkdWNlZCBtb2RlbCkuDQogICsgSW4gbW9kZWwgY2hlY2tpbmcgYW5kIGRpYWdub3N0aWNzIChlLmcuLCByZXNpZHVhbHMgdGVzdHMpLg0KICArIFdoZW4gdGhlIE1MRSB1bmRlciB0aGUgYWx0ZXJuYXRpdmUgaXMgaGFyZCB0byBvYnRhaW4gb3IgYXQgYSBib3VuZGFyeS4NCg0KDQoqKkxvZ2ljYWwgUGFyYWRveGVzIGFuZCBSZXNvbHV0aW9ucyoqDQoNCiogKipQYXJhZG94IDEqKjogIldhbGQgY2FuIHJlamVjdCB3aGVuIExSVCBkb2Vzbid0Ig0KICArICoqT2NjdXJzIHdoZW4qKjogTGlrZWxpaG9vZCBpcyBoaWdobHkgbm9uLXF1YWRyYXRpYw0KICArICoqTG9naWNhbCBleHBsYW5hdGlvbioqOiBXYWxkIGFzc3VtZXMgc3ltbWV0cmljIENJIGJhc2VkIG9uIGN1cnZhdHVyZSBhdCBNTEU7IExSVCB1c2VzIGFjdHVhbCBsaWtlbGlob29kIHNoYXBlDQogICsgKipSZXNvbHV0aW9uKio6IFRydXN0IExSVOKAlGl0IHJlc3BlY3RzIHRoZSB0cnVlIGxpa2VsaWhvb2QgZ2VvbWV0cnkNCg0KKiAqKlBhcmFkb3ggMioqOiAiU2NvcmUgdGVzdCBtb3JlIHBvd2VyZnVsIHRoYW4gTFJUIg0KICArICoqT2NjdXJzIHdoZW4qKjogUGFyYW1ldGVyIGF0IGJvdW5kYXJ5LCBzbWFsbCBzYW1wbGVzDQogICsgKipMb2dpY2FsIGV4cGxhbmF0aW9uKio6IFNjb3JlIHVzZXMgZXhhY3QgbnVsbCBkaXN0cmlidXRpb247IExSVCB1c2VzIGFzeW1wdG90aWMgJFxjaGleMiQgYXBwcm94aW1hdGlvbg0KICArICoqUmVzb2x1dGlvbioqOiBVc2UgZXhhY3QgZGlzdHJpYnV0aW9ucyBvciBjb3JyZWN0ZWQgTFJUICg1MDo1MCBtaXh0dXJlICRcY2hpXjIkKQ0KDQoqICoqUGFyYWRveCAzKio6ICJUZXN0cyBkaXNhZ3JlZSBhc3ltcHRvdGljYWxseSINCiAgKyAqKkxvZ2ljYWwgaW1wbGljYXRpb24qKjogTGlrZWx5IG1vZGVsIG1pc3NwZWNpZmljYXRpb24gb3IgY29tcHV0YXRpb25hbCBlcnJvcg0KICArICoqUmVzb2x1dGlvbioqOiBDaGVjayBtb2RlbCBhc3N1bXB0aW9ucyBhbmQgbnVtZXJpY2FsIHN0YWJpbGl0eQ0KDQoNCg0KDQoNCg==