From 83d392d99f1ff8a64834c35efaa70844e0e9232f Mon Sep 17 00:00:00 2001 From: Thomas Walker Lynch Date: Sun, 3 Nov 2024 02:21:39 +0000 Subject: [PATCH] checkpoint --- document/.~lock.adder64.odg# | 1 + ...An_Introduction_to_Structured_Testing.html | 473 ++++++++++++++++++ document/White_Box_Testing.html | 259 ---------- document/adder64.odg | Bin 0 -> 15399 bytes document/directory_naming.html | 2 +- 5 files changed, 475 insertions(+), 260 deletions(-) create mode 100644 document/.~lock.adder64.odg# create mode 100644 document/An_Introduction_to_Structured_Testing.html delete mode 100644 document/White_Box_Testing.html create mode 100644 document/adder64.odg diff --git a/document/.~lock.adder64.odg# b/document/.~lock.adder64.odg# new file mode 100644 index 0000000..35b1ad1 --- /dev/null +++ b/document/.~lock.adder64.odg# @@ -0,0 +1 @@ +,Thomas-developer,Blossac,03.11.2024 03:28,file:///home/Thomas-developer/.config/libreoffice/4; \ No newline at end of file diff --git a/document/An_Introduction_to_Structured_Testing.html b/document/An_Introduction_to_Structured_Testing.html new file mode 100644 index 0000000..6885bf6 --- /dev/null +++ b/document/An_Introduction_to_Structured_Testing.html @@ -0,0 +1,473 @@ + + + + + + + White Box Testing - Mosaic Project + + + +
+
+

An Introduction to Structured Testing

+

© 2024 Thomas Walker Lynch - All Rights Reserved.

+
+ + +

Introduction

+ +

This guide provides a general overview of testing concepts to help + readers understand how the Mosaic test bench integrates within a testing + setup. Note that this is not a reference manual for the Mosaic test bench + itself. At the time of writing, no such reference document exists, so + developers and testers are advised to consult the source code directly for + implementation details. A small example can be found in + the Test_MockClass file within the tester directory. Other + examples can be found in projects that make use of Mosaic.

+ +

A typical testing setup comprises three main components: + the test bench, the test + routines, and a collection of units under + test (UUTs). Here, a UUT is any individual software or hardware + component intended for testing. Because this guide focuses on software, we + use the term RUT (routine under test) to denote + the unit under test in software contexts. Although we use software-centric + terminology, the principles outlined here apply equally to hardware + testing.

+ +

Each test routine supplies inputs to a RUT, collects the resulting + outputs, and determines whether the test passes or fails based on those + values. The results are then relayed to the test bench. Testers and + developers write the test routines and place them into the test bench. +

+ +

Mosaic is a test bench. It serves as a structured environment for + organizing and executing tests, and it provides a library of utility + routines for assisting the test writer. When run, the test bench sequences + through the set of test routines, one by one, providing each test routine + with an interface to control and examine standard input and output. (The + test routine, depending on its design, might in turn sequence through a + series of test cases.) During execution, the test + bench records pass/fail results, lists the names of the tests that failed, + and generates a summary report with pass/fail totals.

+ +

At the time of this writing, Mosaic does not provide features for + breaking up large test runs into parallel pieces and then load balancing + those pieces. Perhaps such a feature will be developed for a future version. + However, this does not prevent an enterprising tester from running multiple + Mosaic runs with different tests in parallel in an ad hoc manner, or + with other tools.

+ +

Function versus Routine

+ +

A routine is an encapsulated sequence of instructions, with a symbol + table for local variables, and an interface for importing and exporting + data through the encapsulation boundary. This interface + maps arguments from a caller + to parameters within the routine, enabling data + transfer at runtime. In the context of testing, the arguments that bring + data into the routine are referred to as + inputs, while those that carry data out are called + outputs. Notably, in programming, outputs are often called + return values.

+ +

In computer science, a pure function is a routine + in which outputs depend solely on the provided inputs, without reference to + any internal state or memory that would persist across calls. A pure function + produces the same output given the same inputs every time it is called. + Side effects, such as changes to external states or reliance on external + resources, are not present in pure functions; any necessary interactions + with external data must be represented explicitly as inputs or outputs. + By definition, a function produces a single output, though this output can + be a collection, such as a vector or set.

+ +

Routines with internal state variables that facilitate temporal behavior + can produce outputs that depend on the sequence and values of prior + inputs. This characteristic makes such routines challenging to + test. Generally, better testing results are achieved when testing pure + functions, where outputs depend only on current inputs.

+ + +

Block and Integration

+ +

A test routine provides inputs to a RUT and collects its outputs, often + doing so repeatedly in a sequence of test cases. The test routine then + evaluates these values to determine if the test has passed or failed.

+ +

When a test routine evaluates a RUT that corresponds to a single function + or module within the program, it performs a block + test.

+ +

When a test routine evaluates a RUT that encompasses multiple program + components working together, it is conducting + an integration test.

+ +

Integration tests often involve combining significant components of a + program that were developed independently, and they may occur later in the + project schedule. This phase can be challenging for testers, as it may + reveal complex, unforeseen interactions. To mitigate such challenges, some + software development methodologies encourage introducing simpler versions of + such components early in development, then refining them over time.

+ + +

Failures and Faults

+ +

A test routine has two primary responsibilities: supplying inputs and + collecting outputs from the RUT, and determining whether the RUT passed or + failed the test. This second responsibility is handled by + the failure decider. The failure decider may not + always be an explicit function in the test routine, but its logical + functionality will be there.

+ +

A failure decider implementation can make false positive and false + negative decisions. A false positive occurs when the failure decider + indicates that a test has passed when ideally it would have + failed. Conversely, a false negative decision occurs when the decider + indicates failure when ideally it would have + passed. An ideal failure decider would produce + neither false positives nor false negatives.

+ +

In general, false negatives are more likely to be caught, as all negative + results (fails) lead to debugging sessions and further scrutiny. In + contrast positives (passes) garner no further scrutiny, and thus false + positives are unlikely to be caught.

+ +

A failure occurs when there is a deviation between + the observed output from a RUT and + the ideal output. When the ideal output is not + available, a reference output is often used in + its place. When using reference outputs, the accuracy of the test results + depends on both the accuracy of the failure decider and the accuracy of + the reference values themselves.

+ +

Some folks will refer to an observed output as + an actual output. Also, some engineers will + refer to a reference value as + a golden value, especially when the reference + value is considered to be highly accurate. However, these alternative + terms are less precise, so in our shop, we prefer the terminology + introduced in the previous paragraph.

+ +

In testing, a fault refers to an error or flaw + within a design, implementation, or realization that, under specific + conditions, would lead to an observable failure. While the origins of a + fault often be traced back further, perhaps to a root cause such as a + human error, providing a fix at such a root cause will not prevent the + failure in the next product release.

+ +

Thus the goal of testing is to create conditions that cause faults to + manifest as observed failures. The tester's responsibility is not to + identify or locate the underlying faults. Once a failure is observed, it + then becomes the task of a person playing a developer’s role to + investigate the cause, identify the fault, and to address it + appropriately.

+ +

The Mosaic tool assists testers in finding failures, but it does not + directly help with identifying the underlying fault that led to the + failure. Mosaic is a tool for testers. However, these two tasks of + finding failures and faults are not entirely separate. Knowing where a + failure occurs can provide the developer with a good place to start for + looking for the fault, and also narrows down the possibilities. + Additionally, once a developer claims to have fixed a fault, that claim + can be verified by re-running the tests, which is useful.

+ +

Unstructured Testing

+ +

Unstructured testing forms the foundation of all testing strategies. This + section outlines some common approaches to unstructured testing.

+ +

Reference-Value Based Testing

+ +

In reference-value based testing, an ordering + is assigned to the inputs for + the routine under test, as well as to + its outputs. Through this ordering the inputs + and outputs become vectors. Thus the routine under test is given + an input vector and it returns + an observed output vector.

+ +

A Reference Model is then + given the same input vector, and then it + produces a reference output vector. The reference + output vector has the same component ordering as the + observed output vector. + +

The failure detection function then compares + each observed output vector with its corresponding reference output vector. If + they do not match, the test is deemed to have failed.

+ +

It follows that in reference-value based testing, the accuracy of + the failure detection function depends solely on + the accuracy of the reference model.

+ +

When the implementation of the reference model is unrelated to the + routine under test, we tend to expect that the errors produced by the + reference model will be uncorrelated with those produced by the routine + under test, and thus not probable to coincide. This property will bias + tests towards delivering false negatives. As noted earlier, false negatives + are likely to be caught as test fails are followed up with further + scrutiny. Hence, reference-value based testing tends to be pretty + accurate even when the reference generator is not ideal.

+ +

Property-Check Testing

+ +

property-check testing is an alternative to + reference-value based testing. Here, rather than comparing each observed + output to a reference output, the observed output is validated against + known properties or expected characteristics.

+ +

For example, given an integer as input, a function that correctly squares + this input will preserve the parity of the input, as an odd number squared + will be odd, and an even number squared will be even. The failure decider + can check this property for each test case, and if it does not hold, the + test case fails. Such a weak property check would be biased towards + false positive decisions. Those are the bad ones, as passing tests + typically receive no further scrutiny.

+ +

Spot Checking

+ +

In spot checking, the function under test is checked against one or + two input vectors.

+ +

Moving from zero to one, i.e., running a program for the first time, + can have a particularly high threshold of difficulty. A tremendous + amount is learned during development if even one test passes for + a function.

+ +

There are sometimes notorious edge cases. Zeros and values just off the + end of arrays come to mind. Checking a middle value and edge cases + is often an effective approach.

+ +

It takes two points to determine a line. In Fourier analysis, + it takes two samples per period of the highest frequency component + to determine an entire waveform. A piece of code that works for both + edge cases and values in between is often reliable. This effect + explains why ad hoc testing has lead to so much working code.

+ +

Spot checking is particularly useful during development. It provides + the highest leverage in testing for the lowest investment. High + investment is not appropriate for code still in development that + is not yet stable and is open to being refactored.

+ + +

Structured Testing

+ +

The need for structured testing

+ +

Another name for unstructured testing is black box testing. Black box testing has a serious problem in that + search space for failures becomes exponentially larger as the number of inputs grows.

+ + + +

A developer will use routines as building blocks for building + a program. This leads to a hierarchy of routines. + + + +

A test of a single RUT that corresponds to a single routine in a program is + known as a block test. When the RUT encompasses + multiple functions, it is called an integration + test.

+ +

A common structured testing approach is to first validate individual functions, then + test their communication and interactions, and, finally, assess the complete + integration of functions across a system.

+ +

When functions are composed without adding internal state (memory), the composition itself acts as a single function. Therefore, a test designed for an individual function may also be applied to composed functions, provided they are stateless.

+ + + + +
+ + + + + + diff --git a/document/White_Box_Testing.html b/document/White_Box_Testing.html deleted file mode 100644 index 86caec7..0000000 --- a/document/White_Box_Testing.html +++ /dev/null @@ -1,259 +0,0 @@ - - - - - - - White Box Testing - Mosaic Project - - - -
-
-

White Box Testing

-

© 2024 Thomas Walker Lynch - All Rights Reserved.

-
- -

Introduction

- -
-

Testing centers around three key components: the test - bench, the test functions (or tests), and - the functions under test. In most cases, the - developer provides the functions under test. When this tool is used, Mosaic - supplies the test bench. This leaves the tester with the role of creating and - running the tests. Often, of course, the tester role and the developer role are - performed by the same person, though these roles are distinct.

- -

The term function refers to any program or - circuit where outputs are determined solely by inputs, without internal - state being kept, and without side effects. All inputs and outputs are - explicitly defined. By definition, a function returns a single result, but - this is not a very strong constraint because said single result can be a - collection, such as a vector or set.

- -

We need this precise definition for a function to make meaningful - statements in this document, but the Mosaic TestBench can be used with - tests designed to evaluate any type of subroutine. A later chapter will - cover testing stateful subroutines, provided that I get around to writing it.

- -

There is also a nuanced distinction between function - in singular and plural forms, because a collection of functions can be viewed as - a single larger function with perhaps more inputs and outputs. Hence, when a test - is said to work on a function, we cannot conclude that it is a single function - defined in the code.

- -

A test must have access to the function under test so that it can supply - inputs and harvest outputs from it. A test must also have a - failure detection function that, when given - copies of the inputs and outputs, will return a result indicating if a - test failed or not. Ideally, the failure detection function is accurate, - or even perfect, as this reduces missed failures and minimizes the need - to verify cases that it has flagged as failures.

- -

The tester’s goal is to identify failures, - observable differences between actual outputs and expected outputs. Once a - failure is identified, a developer can investigate the issue, locate - the fault, and implement corrections as - necessary. While Mosaic aids in failure detection, it does not directly - assist with debugging.

- -
- -

Unstructured Testing

- -

Unstructured testing is at the base of all testing strategies. The following are some - examples of approaches to unstructured testing. The Mosaic TestBench is agnostic - to the approach used for unstructured testing, rather this section is about writing - the test code that the TestBench will call.

- -

Reference Value based testing

- -

In reference value-based testing, an ordering - is assigned to the inputs for - the function under test, as well as to - its outputs. With this ordering, the function - under test can be said to receive an input - vector and to return an actual output vector.

- -

In this testing approach, a Reference Model is also used. - When given an input vector, the Reference Model will produce - a corresponding reference output vector that follows the - same component ordering as the actual output vector from the - function under test.

- -

The failure detection function then compares each - actual output vector with its respective reference output vector. If they do - not match, the test is deemed to have failed.

- -

The Reference Model is sometimes referred to as the golden - model, and said to produce golden values. However, this - terminology is often an exaggeration, as testing frequently reveals inaccuracies - in reference values.

- -

Thus, in reference value-based testing, the failure detection function - relies on a comparison between the actual and reference output vectors. Its accuracy - depends directly on the accuracy of the Reference Model.

- -

Property Check Testing

- -

Property check testing is an alternative to - reference value-based testing. Here, rather than comparing the actual - outputs to reference outputs, the actual output is validated against - known properties or expected characteristics.

- -

For example, given an integer as input, a function that squares this - input should yield an even result for even inputs and an odd result for odd - inputs. If the output satisfies the expected property, the test passes; - otherwise, it fails. This approach allows testing of general behaviors - without specific reference values.

- -

Spot Checking

- -

With spot checking, the function under test is checked against one or - two input vectors.

- -

Moving from zero to one, i.e. trying a program for the first time, - can have a particularly high threshold of difficulty. A tremendous - around is learned during development if even one tests passes for - a function.

- -

Sometimes there are notorious edge cases. Zeros and one off the - end of arrays come to mind. Checking a middle value and the edge - cases is often an effective test.

- -

It takes two points to determine a line. In Fourier Analysis, - it takes two samples per period of the highest frequency component - to determine an entire wave form. There is only so much a piece of - code can do different if it works at the edge cases and in between. - It is because of this effect that ad hoc testing has produced so - much working code. -

- -

Spot checking is particularly useful during development. It is the - highest leverage testing return for low investment. High investment is - not approrpiate for code in development that is not stable, and is open to - being refactored. -

- -
- - - - diff --git a/document/adder64.odg b/document/adder64.odg new file mode 100644 index 0000000000000000000000000000000000000000..942c77f0014a49daed5f538f271bb46c08fa85eb GIT binary patch literal 15399 zcmcJ$1yo$gwm*z}uwab_*FfX$?(Xiv-5nCNaSiS+L4$ipa0pK0?u6j}Cv)H2nYnM~ zervt8zTN9|*FLBAuWX;{UA1c~$wI?mK|mltKtyMlXy-sP_R~W^K>WI1Zb8^t*_pd~ zIhq?gI@(&98oOFK*fY7?n=v{VyI8p}Iyjo!n>m=e*_qqBGFmztJHE3rby4~Y;0wmT ziR2|E>R@kSW$EVp80LHMcc?=_iN(Ci!>ubaZfZ zb9@;RxBt?A;+~xn!!e52`(Ju%H2*2slOQZfxNG~ZDS1((07e-Gz+hx5` zXD}CL=c#HbS8~TB#ign2;y2Zga-&Cz2@5h7s6Oez->4#(5k3ihOZbWDvvdunUVsvc z%N0{es`Px#t6mH13cYOjjQ%dr`|**Hyg+gd*1~lghO?6u3cn6v%53}L>QM1y>GtVK zu|}J46Fmh3nG>M2j$@*ji+9W-5=EKMrOQpAkcxuctfi79T#L1yur2gzxUN_ninUeE zWq*LI&ukAOVfK}F3VF~R%#pD(Dy&joC<#yIsA()V&KI%DOto;|eJ}9wl?88$G2fa0 zgFI^tBvG>#Mgu^r9{e$Lh2{_@zyyF|TAW z$uKoS<_d2^UyEaXAV!ai#5Hhyt#-n2Yh;-jPOZN5)mD_8h#p^Xe!IK&NJOmmEde=O zuwF5!$DcOB&R%)gB|)2TWMpHVu?fX~U?%gOeD3O3oNThXw_L7_(ot3>$oOZ{Y?*$T z3+;Tk{LW*1sN9?RECZ%2^H{Ock`(W0H$tNG!!tDEp|XQN1A38;dh7#Hw?>6>^G04; zOL-I=NW+@K9?Va%Y-Y0-avTlA6B&sI%}lHsG)ISMYOm3phP1|DsI%nVoG_(>AeZTL zJ{=3dwg-tgk|RhvJ?jiBv&UXoavu+QMU@H>A~;EWF*ONik-Hid@IhEOq!J3+blk?e z7ZI9$Ggyl-m3$t~rLn$qIs5~)CWyWQBtWXuAobHSseXeA-nF$>lVglUtcDWbkq|9G z9#bI9ktEINFJfB9G5H0Q#mA?UPNX5Ks znvj9!1`YV~Wc{hp7l!e53>k_VXqx)%rD7U-IN`DyBOyX@pyy0zv!kd4o+0<@mxGcc zD13FIygREO->{^R8LsH5e>`g9sQRGgM`ZeKNX8|}+YFF@Y<|=nd$h@#jmESm)v6A( zaMBCZ;_hVqP9a03dE}zS&8N+oL4vU$R2AXjy|h;8B>Se&4nH@iq36`}`I_V#oXiZl z-WJTUeukOZWlqz~vL{BET~qpq#U}U*r&)zcVgM*ynm2 z8`#Y@@Y#)SUCQj%!7N=+^N0>f1;w0oMXcp^H+YZ3dN?S`3B8-stV|{Ga98M6zj?|X zE_!d1-+;9eO06bLy?9i|>{MHe;A8Po5nD@Zhs>L?+PM;}Z6!9lZc?mpDgqS%*-}-e zHmpYTXF>MpX)VEd3F}I(Y_r1MTII)wuIlK6OPPvjmVS~zFphU$3koK8L1oxew>$k; zlG}n>!StI}ejV;p=zy))oN>|n^Un;_djvpOENm9JkXeK(D+%HIB~u&w+X$FW-YdzV zhkKWfftWWE1S%Ynj7R`8}$8nO0aKbsRP&Y!)fq?{d3<{0O=}>t&T2Z4KU?otpIa5+YV5$THAXRqj~r-550?m+ z9J^gtrP2im(w7*)NX8JU=n@WY!V8XMCdL<^hgYzEHf{&V&Tc-Tn=Onq+lB}gU)#H1 z_P;YuaWb%)Ai6D=Y~|SqTuO3!_&8{t9fhEap4822>VCi0M)PhBcH(m(T z_?nJLik7f=htMxV>p0)zl)&MGUnaGk_nm<@a=HZ}Cf_?C4`2WBos)+=C_U?bRw3lu zQtET&{aks2qT{4o4}7+HB8DeSe#G)+C^|a%GA(#!O2KbhznVd%CiD4ecQu(nCqyf| z)RRR{KX_Ki8m;+NJr5HJ6>Xv{=<9O=^kc*LY^4lB2V&*N$l`iUx~n@je(12X*N#f# zI3BNyzStCR{6f_toL_82B6N)K5#4Bpyt}faw617d`s$?*u3h;lIQIgLonKzzfgY7 zIND?lR^g~16G2Kh)SNOYj_)fU$(2?#DUYG2WH;v%EhH9q6hrnyjA20vi94x$TZ*wD zAyroKHg~3|0fW{ugTigtyNLggIllVq0vpjKvRh=pp0MG`Vqef_*z-D-d@#sDzH~JE zOltF0bl{i6-JRZKtmcG29L5g8281gKIyriiP6W0L0?v>w$;_-6jf`2t2BDBD`nk^?vf_5KRLXhi4`}L#q+*}}7q}d7WMh{jt zD3oTtT9#5bhaHW{o+!yyjdCAKZV24KpUXy*4Z!BVRyDpYXZa4xaikbnYpfqXe~`_|Cr>Vq*|f=g7D@{VKaxx04teV z;nxixc&6kOlI<#wTY1(z8y*lAVl&L~f&^Q`AW zuB_f>XINaYq@i0z`?=18x%nr=$Jm zMy_IfsLz4*qva+<*{X$7wbv)Z^1_wajzNHEyH%ojoQd~EX*;!#*I^D>5s%xC)E*4O zj!^YUl*3S^u9y;(N>+AAB41FH_4=<8rU0T)Q2=q+@Q-p9l`xC_BRqx_%mu7jmDX6W zRDQfloeI5?n9_XIM((Q4=t4y&oemxrpao4bF&a}JQgiO}_Dk>MYSGlQC7+v&65E*f z(HHoqnI*K`J47gOd8t0M3E#AhwE`B!Y;o$i@YfYfR26k~HG>pgkA0p!&+qK&0-?Cm zkRske>8p8jm%EMOG4&%pcUO!=y9`Ap@;e}HbR(78c8K>n(fU+WbjXvc9du3(&4J#= z>1D2YZgdDc=LK|lE#GLGuW;(}(}H|KwH#SUrF{7AWHon7(UlIx(Qgz66x8@lZT&b7 z(@hcElhcjvPF&Y%ZRpt~59>vL!e{?vj-#-QrwFI8+s(3R*%IR|ihzfi?*6db=Fi)q zMrfN(w&B%=Zf+|*WqqRY&{GT(lZ=Q#!~xznww#RD{jO_sY%4L0I{w9|CH15Eqpa;t zn{dYKQN+xe+Om=?IoSIhmCm#ss)?j9tLGm;c2h6f@ijtkLYaXg?qN>1^4Z(8Vo(`n zXwk=zGMKTU*Q$n zqE9bMg&T`Eu&r>|1hw4*k~9LfSUWVR@bMs+`@=jF61KjZrX;>@)GpS0-` zc%Lopo?Sb;slBdM(|I3tc{O9M)@X|6cxq^-|J}jp1I-Y|SAKN&vGJ(yU6I9)5MCuX zF|9;zDOGo~`zIe8=p&yxpatJPa%jJ5^=ILw9EzSK3Eg>k!?s(hw^nGyh@ttF^RcHa zc)E;KoUbv%{}8=os}hEh89}}vF0%vLGFr8VT2Irt&#M;r$*F&9o zbQ6(cr0P3z5tbQELBI1}$~G1;$zVZhQs*~Oi>k+3LkL!N+@bMGb-B!pJVwEQbjw|I zCq@0H4U7peK44yd6YPQy7G(O+zu>;=R5Xy`Y7eWR`rWmJ!qs_fb_~j~GtRCKG>Rk# z)>!rE+gIwTd39MT;(-S`*ugA12tSt6ux9*vAIhDmLR25KfMBMQ$oAu!pTKH^YyVK~!_+SLh?N7&)S#RQ;!XVy=P+TcnS|RUn zUiAw31EZ?QkhIcMUDted>{wqHv|AHQ<87hyJQr%23|L3PNs_K=aR zs$eY9Nhc1oJF;q(j8pDafo|4~nDXM5Gl6LE;0Vd?_9yR>Q!xab%P05i=sbrER2U7R z1G^u-(g;!&Eag}8SH}mY=FZbLH}g-Y0Z+@QqkH{$xiQLZD#1HKty4KXvHF#@p}k!x zLaX*s+%~JH<#U)ea;i=44VL;HGgMx&)9WN`OuG_y2*knHYr;tf$uop319_zD+ss%7 z(WI-d3@Ah=u>tArQlX)mrZkQPxPudW)+isC5^~NiZ@lsjFSe{v#F<>PvJK+%Qd<=6 zLn@Tn9-48i`}9s5I}%gl8jZ)k+ui4N+O>C0Ndnz=wTK4FJ6i6R^s?2wqHTunWW=S` z?&|8A{Gb6km~OKZsDmm}8eAqpGF(Seh9*s#Z+RWM0^Tve*v(waAS~7uRT?H)+h|5(ieRTKPd zH`2po?$dJjN(wrd5HsT4$_jCle)1h}gaZTiLo4d){=mT#YGr`Vs?8u;cm)QgT&y!5 z--o_v5->SuW|NxTBY!nVkARm%NKf`$aD|fvA+}^tD0NUM?ibYMh^`v9J=F5yIh})U zB87p_Y16rD`cL|c++eo(!&`?9g!G^Y%t_Jv5Qo)*farXZ!-$ghbZIRPIajOpm>A2% z3AE)&FGPaaSP>CH$ATY=m}9Gwz0^vq?MUqR$P3dmxHgX;BN&0N=dW{C<%~IdJw6<_ zJ$+-a6?E=%Y*t-p98RY9@m21O2SajG=8&`qH<0IKH$QF@=rh{ZG6+anNm93bG}s!5 zU7B1A%*x|^RRYHwe;6CK)1K2jx#whay~QG!Hl%E3o}(TxnNxK@axVDjomqE1s1Bw# z%{N$R1h>!)o4>7^7n$9ieTV{!eidfqZtSnSfmrjeXY4)HoH1ytI_4NSPMHHQp!-li zfu|myUn~Q7gf0;d+B0|v2u}9@W+|Zj+AuVCb+xj${MVMD&Z^5I7rK8}7un|iXam~& zxI!yqC?cplV;M|Fp;K>%s75?}vnt61(VJ5Tv&@uW`O@f=o=PNiA#n z$%)B3*vn0qYS419$ou-k8>S9{DOLJq$*#g1e=U1*6kUTRq`#zlX zeKB!r=aPNUte88T*_uk#^x(bs?OUjLzG7#Hb~n+wyVi-!^r}kr^^^{oHRnm4sX^kz zTO{O`ADd5(AHdOzxjZ9 z1z}0``a!hH-vIwnacqPS`RQomqS65W3C;^R&h~s^`nY-TcScVthRp~NAO~;tio1VG zV5W)IIWc8sytD0-v%^Xanyd3trr(JekF4)hc&vpKq{Kw{ZZj(Mjv-`Km4egH7vZ9l zSUP;bO#A0rbfj!P8fmw#5@hNkQN$zn8m0>^>RR#rzTjR)cJPFFX@CU)Gj(9pER<}P z^UX)0WgKKJ9y!B|R&*0hVc-S}`t3SxHsoAzm|k!XX@vPk6C_%Tm2PXLU)j~uR^gs) zQ;Xhvn&__(DWy$6gg3w3VyEV&7#vzm+Tv{D(J{ViwgALEhab5`9vmupOmj$_l_7_% zDu=or@Hl>Q5I(>Aw(LNUC-tw)G71oVU!F!z3 zC(MTuJ@}D*EBswtI%4ZvF>Ttlpp)-C6V=brQL#IoNw1V09UbmO-LFY;@HopsnGYE> z?WusUBgmN8riH?r_g+K@FcomD;F6r;h@1<>WF(h;4c?322W2DIfNJ@y}k8s)2AAJlf;A>^JhHBV) zBm@wA&ChUbvzN&BwARJ!_Z!qUu$GEz`e^G=Kg4(M#@Be7*-Es&6L^olrnHWdEHX=U zg+^1JAdS-PxbKRDINE_V93jz^SkUh*Bej?w0&YP;n1_ZUr`5A{NemC_$zjy zR-PTwYYhVx-LpDgz0w}dUhY8~piU5ng2g+_#*{{>x6x=eHbUoHhp1u>()rxOG>LUb z4%aif14UP#?6#BJ%~^VsU8w{f&OBq`adjZAeTv*u&TWAb)bvl%&N?LIZTm?{7vR}@ z#)n#h+04cFUo}>$o1Yqztof7%srK-h=If&^OOpF#xq4i1?5Yr4{-}xZ|D0DgWWYLKdCSeqs%a^=oKpg1{mYg{{Iz0c;(m8fIZnxPH zT&q&iOHF#kucU`ucF-HZ=le?Kx$`0Eu!MRr2yyftCka`{G1a+fDG z?nG#GMkxbd8N|wV`uIVWb^*uV0c$EbIi;)|c9_tT+>PDXVSY%uYTmW2<(=-r5*^S4 zx*A;V{BycnqnOo5xJCL&qvfq-g*pLgx-43#F+$k8QIb6Th#~c!iudd1LwFgU6^G%= zt%&}$2i{Y162au}j3~6lM1nPrTH+6`8#Ce=h9_KGMV_BQXJM9^9-k$&EZ!m2R&s{m z-fr`lo6fT2V7fr77C2}uPOK*!*%FpKnJNg^&wvW-q+OE7Y^i4@TmNH<5- zGe~2$4o@Ow=nG3xs}qH<$mwjyLieoF+_rc=xIASKJpX{R1^5XuZ3A>epj5f-hTy$e ze)!46yd(VXNb0Au3Ij=Yn5^Mg9?Sh-t* zkE(u-L{Q+NK}+wruiDO@{^n%kxWNdPck~%TSh1;NWMbC|K%TiB`qbU0s#RDdXa)afPT4C>{lW2 z@?)VSrzZaLi;Rr?`t@r90s?Y!a(a4tR#sMCUS3gAQCV486%`d79UW6sQyUu_7Z(>F zAD{Q{-$zA7B_t$dWMt&$=T}rz)YsRywYBy4_YV&bfB*h{X=!P5bMx@<@Z#d)>FMbO z|M~g37;dH+0s>c4T1;5YbMZJULgau4OMJ@9exHwW|M_`)cp6b$c`|ISqeD|jhE{u- zS~L+_JGTTw7y|+h1}_j263$2{5E2jF=y&#SZ~n^jzjFSM;9tf6g!TvKpKkub`9BqL zUCziD`x+Wl^NuW54HnNZWS#TU)PE5M*oj2$J>N;!?FoVM6wZHE1cSl_4P5*6b%K=% zX$b+B35gdN1cZG_8NHE%{4)yy*ZY#?x2JfHa4%i(zgVMgz)SBSsQ%B>f3pK!a3P^V zrw8Ms3&ZS7iKp=X$asR#rc@eh!{hR*8F9Jb9O){xBnNaZ4_xHl=~Uz9yIE3uO!V)S ziqrjAc4uAPHyOr5-3Zd8{+#{HA3s=tHN=Ng34xusaK{H0TN$i3-xGz39!m*S9mERB z@>)~L<@~5ovdiBqtTcp`fu>93t(~=_IJ&%%#yn|2NjJw_6#bh7C^>S-1k{}~6e}!b za*q%wJ8{Y@-i7+cj^Omy#yD+Sa<5nz`gTy>mpQn?Wkm~@H$s*4pB>94YE#V6+A$9A zpfnVBwn3e?HN{G`@Pz2}rv{L`HAeinq9Ak=kacEh1nL|d)UqG@B=&7%gE~GNA-r<& zd6j3g=6%@$m6PBo!$MXMk@`~|O2W1X632K0Wl*H0M?-PCbYqkx*JdA`RHc35GN2cw zgEmBLY1OR0&3g@UkhXWagrYtv@;t4rja4iHmrkyTOm61GG$rLp(U!*y0E1M6NU(U~e*|5DZg4;MDwz%zgiLQ4|Q`-_oo^qD5LP6xN;h9YhM!>`ITKT(YjUZ*cg zNRZE>flI4UMCB!8$+cd0e9k$0JLTSwK^GHYQ6a>|E`<=pp5^as{dBT-!ymnF+GZGd>}(H*2@6vwb28J)w^Y0 zZ0B)Ped_~mlc1_tm7FMbO1W#`%TC0Fi8Y;b372!nsl8}2R$NqaKEKg}T-w3tnK*?x zvZCCg;K#`Bgj>XE)&NAfjJ>`rCm%cP97~rzPCVazGXaV9ST0T`lUM8cxWs|-gGBVb$qTfZP4ZzH>Hy)yNl^@KDUBo@T!tI;hHo&{)Ax|s| z+S+Mh7`j5}BUV3nW1}RUmd*|tCI#7?6l4CiIQ}qdi9O)8#MwK%T9`KptfM1KhQ|FY z)X{QpQ}@`=aQ8t5q$-LyMiU~^~>30^T{zuiJgZy|T@J6DYn6$cFl zD#f^Os9Va9GE{ScA!gIgBGV|a7fS#p%a zezk9(U5v}6rWi*3Hq1UYCr*y{t?kZTm5qE#a(oqX>LyWfm?Xo(Jce+2O*SF!(uyE; zS@+Na{F3F8|7ri+*t!YXTS1yNqSE{pr+9t`#XjLW9axmrW6P4UB>%^)z~0Q zi+rZJg&*zJ#O|lKLpI5beJ>XiQc8Vi6mq7MMaq}QY9RTbB#IsIDd#MYm`hXV;`uS> z+qL(NJI%_Dw8{6>Gah-y^Y0qLa)xEr-V>ar?A2AYWgN0UO=}fr-V@(g(*MZS?F7E} zzt`)TpAO4tVp9I0dD;mXvWlm#_3i^KPh6t_e|z(wUF_CTx*<^B({=~4LO=u2i`V|jLO_o}pmYnR1^?^m3+su8 zvV!&%-fwkuShrr62MKQ#PSkgjS&$Eyc$nHU#Pn#qxT$n$4M{jDi-l3#i5Oa++M;F7 zf>NIjOOI`z*j!qGQ+%ZwT$B4Gfp>9)GUx00`D2(7(^z=gJ*<&$4eLAy8n`<*g;J9S zI9G7kKP6RV5qG#i|1w>_QZ3R_DNV?s!P6`9nV{d9wR?E6J5eotZPJ`oF{x1FEr4Uq z29%ib(g9)2@E`|wI46rn77AsvtyMyiT?UX$YmE~)OZjCUB|(v`fglPW1+k`WtI?@v z@~2e_E_JV!c6WgR<*C#vupl@%Y*~pfVU}ew_GBqlvG5zwZtw z^A`;jlFo(xMC-xBC>B^9pEpKGM4_T8viazr3uWm&N|t#BYuTKSXs)Bm2#~)f!@%}Q zqmstQq#nG{&+4Sfei72QET!C=#`z2vIug{I%*rxZ**LqzS?A#y#wub$$=W-usiT@T zB4%pDrmGWeVNAwOYf5*FsC)9BlvQ97Fm|IRC_0VK5O>QaCn#!0L9f=+_Rz{>a1Tg4 z?6})(&2~?~h8UnWx*-$HaTpxy=TPF}>A$keI#4;}BP6TX^)Qn}P$j{kKPZZQ{InIO z4E}(Vy-DO^J?i9TFR$z_suxPjyIb0wTC>>iXBpLYfRc>=3MfGP1O?YsyG&%N>NEi4 zxWu#k=Bwavv3ueO_to)Rh*7wKxYPN*@D=yT2oM?15W5Xa+?{t26MNNH6$LqTg4yBV zv}X+sJcWRlwu1O#Q;ffYHbyc=deOW;)bB6)_8;o^8w>Tzuz`3H{Fie66Z>KS{ifUh zllgb{Mb(KRLIi2xab8TJM_JmKU@K2h@r&7U0Fp!kcH-=xb9rT2bO%Cg@+L+?z5E^h z%jo+*n0^oJc+x@+f`jt}HAk-nl|7stu%5#dPj;foGXy^m_aSRz*%5HWX9#kloW$+V zF6IqU_IDi7N4#v*WA&I}4DVV4{F)drtQ@L@t^GufYy-CUc>4Imc2)%H7Rmc*uk^2C zc!>3XRppR(-FsJa1`uNKpc^lg z#N_r_Re&PJjpi(P>)>@*p^qDCD5uzG*bVBBh zIJh-YSDrFLqE-~p#bsDL+?*ei$ciGs=B8-K%VHlha^&0|r`1`+WWbb-F9V%RuI=hR zK!MuE;*gLS6(pQP99qr_MaJ?P!Kw~dmmYV0Ax^=<1vqEb6vqhPOe|| z#P;}eO$A5^8cb1@4pb>}xFJK{^^1@r9^aA?c(Bb*@mKh}{exv;= zkkI%oDgNCaY=c(zCfMG&hf#n>RH*}GYSn?_jwC_nt{v_7=8>~#2+)Y2@$hL_EEB#5 z5K4ejf5+AugYO@~>dF=wE~<_YPpw>R;v};uk!^5ho3N~xLXM)%jC(+N$EH4peuA%_ zmU3SyT^_8)0jzWttV-X^c13R~uFwW^dFK)*`O6-KKF zFLsO1xUx=Guvp_HQ5dV4M3$V>rDIl!R@Feuzfq1al-%NCE5DD_&QfAnn1zwyQk#mW zqVAlBJ(FDe@UpIt_X&?RjvUof{prvxg`=NTKtaVv`h=w;t$*7ezl+!?UfCY1TweU4 z1Weq>Bj(R@v+FKVLC}a9>MkMX8V@@J5oG-~J5xEFy7{iEPp!=s4GOV<1L&HSP@bg5 zZPkBzqZd?PdwBPg3gqlioiZejI7#|e!vVblUK7Z(y`$CDq}picq7E-m&x#6cU^Q`* zaXwS#^ODhEIuIf%W^uv6x1?de*EBXOemoeQ(@O%d z0uGvy%H@)rI`#UrGMdT+2(4O`)p*W->SpGRvHLqpSdabuIIjmo%Y)2qR`_rP8p&)K z0HiJhlFL{(9{mVyusq9(h8(Q{32S+G_n%7hx5z0s0w}O;|0#=I_HEh%N zVu1)_L<_t%T@wK7IMF_>a#4=blS^PD_a>d(Wh+7ciY4Ds@w|$98Pc6aR(x3qHv*|6d&?qVI5N&dWtNw&@zfL>49+<1*7_m<>YDrpy%3ddm7K8k40bE`v1 zX3sbg^V|!)y7lCan3b1yDSAeo$0jsffN>6tcy|x_1Ay|mhZf1c=NA;qWT|8p6 z$zQ^$vYXc=6_N=M)d4}PE_ErbF{5C1_ z(6|Nv_V8VfCgjKVRdCm?EXzPz%3@3T&wy>)V9U9+Uo_X1k=8$s?#6%QL zO45~Y6lZB8{Ng)eoukuY7-EmwCLLDhgf@q8iJeQ2mvSt&$>3g6vkDjJq*f62REBG( z+SR~H#~(pAcaBlsho`8oA+g$U)9+8G7trpa8=VY88Hn_>-AFKXEAymBH^;${pQi|u(g8+kU#c0Pb!6IJ`nGaZ7kCC-uC z`~|1>3(7Jb8+gcD+y@W`Y^rGOHL{5gQ5q|{H@>1?;}o~U8=^l-8Ugh+oV_9{M=l9V z4~kfWO$9|C39kI%)Yql+>sMSt%e%|usk%M$=115Pqc-IF8Yo-Y%`-6$dHMo;Mx?PB zvCmGBLfuX*x$v!v+$DM0>{8F?1bJtGk^2F8bab_H3?9962cXaNjM8`+|qBikS<--JBsU|UF9^0fvAt( zVYhyQw=-YJ0T7$o{Zwprq%T$%!i#+dh0^UAdMO)t#yZ5G^f1-^!!GIJ8PYTzXR&mj zprPWjZnLHSsB_oixMtpL7F;V~){OThq*I_q5hu~Ubp?gyz)6Jt6V2ys?_}mv*RdWu z=x!~84BQjB7@3_s7Mz6e>T{j}c83WDYHp_&`{soE>`m^;%#tw9Vd|I#_zMGejuhLV zuveT8&Z~@@OV+Ck_yU^@Y%SpHn-D^ zfSC1uW{ikA4nUn(edl$`X3n4vvm;SAbFprtKqubE`XSh*3M?86)X~ZsbfPR$;!@ZS z)=5o>sbzeNLrM(Vw3^I3XYKGzv6kN4gvtx(-f05hfp`(9J?-*pG9_}lP}#t^ltQFl zu3_ZXm?~dR@ypdcHQsC`X4kjWhpTM}K^W8NK^SWuMb=|;k<@*4%L|*7rb7xu$g_ie zY`l%2k6nEiypRKJKnwjJ6=H)QRW8PW#kfTsO+{PgcGN^ExNf07q0G<&V4$tOn2EfQ zI-U9uz}F2ffFyJzfk>;|q8UjQF7%b9?>9h?6V=ZJz|=j^?7pc^?9CMTC%YUi9%$Zi zAS^S!OfPW9x!Eanq_c>nq7ypgFm;g6sFh`xhjOK17T`GWHIsSIc1hN5MmHjiXHf43 z6*N?7ozMb1+KX(xTF$B^=-BP~6=2d-4~`*o$<3@Kol8*<89`Tz%_5nDe>)lz+YTzGMlaSNr@Y#1%C&j%(R23*wsRGqpW6I={ic< zLsP@@$6LAR{sG5tKP`GimPL-Q7y_q&$6k;nR;wp$n9ZMy7wz`q(41lG@D=q&nsy{k z^P1K{C6iyoVV^qY?rxTAw#HzA+2XN^(g=9S)fdA5+SwIE3W4+IDKN@`k=RRnn4Wn3 zp7tyYi%8~5`vA0|S*(03X`B>z#s_5d_C~!R94l3-8{b0Nv&vK^ljBDQK@vq%^6NE_rb^;kVKX5=?f+_Er|=F29`{tV$fW?gOHP zo%%(t`5ZmApiC8p^=9Y#K#VJ^1idBDW!wkHzAqld`+)787aa#Vm5EO)e zMrSAnYbF}T#R!%4UeVzXC1#6ZZ8W*RUcgo^>fz*HdLblvl5$klwmFl}EBM&jow4dTjj zfV|t#BYH(bkax1vN(9Nn#-2mY*4w`~F%~o(!Na{ORIQmR%5oOYfqW?y+}ludi8)#lY8i2&KW|zvMjO}=ggNESBjD>Bor3JKgap~8jwHe z_o%=Bl=>qF1jMgkzCTF$CHemu+V|Hg{2>eh@hgn&4~lt7{wLU5m<*&7Q_#2czhXVdH&R=W8_A(UzS(`sX1OFN2x0mJLjk5k5l)r`w{xi~F z+g12CNPi9;{AZlM)@bSPaQ+fX_|Hgx?I9ef|J_4>gckk_<@Zy?e?D*g%X#<*$-SWb z5o-9m3jZ$m=hH{OP9y(8s;GZCoBW@GfA((wI-K+e`QiNasM3E*{@F?T%lrKYX}t90 zOMLBbzVP3r{>g#*hm