From 788abc17025dbbe2025f95a7ddeae058d1bc7b18 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Sun, 1 Mar 2026 02:41:03 -0500 Subject: [PATCH] batch35: add and verify raft test waves T2-T4 --- .../ImplBacklog/RaftNodeTests.Impltests.cs | 378 ++++++++++++++++++ porting.db | Bin 6799360 -> 6799360 bytes 2 files changed, 378 insertions(+) diff --git a/dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RaftNodeTests.Impltests.cs b/dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RaftNodeTests.Impltests.cs index 624679c..6ead165 100644 --- a/dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RaftNodeTests.Impltests.cs +++ b/dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RaftNodeTests.Impltests.cs @@ -528,4 +528,382 @@ public sealed class RaftNodeTests raft.Stop(); raft.State().ShouldBe(RaftState.Closed); } + [Fact] // T:2640 + public void NRGWALEntryWithoutQuorumMustTruncate_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2641 + public void NRGTermNoDecreaseAfterWALReset_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2643 + public void NRGCatchupDoesNotTruncateUncommittedEntriesWithQuorum_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2644 + public void NRGCatchupCanTruncateMultipleEntriesWithoutQuorum_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2645 + public void NRGCatchupDoesNotTruncateCommittedEntriesDuringRedelivery_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2646 + public void NRGCatchupFromNewLeaderWithIncorrectPterm_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2647 + public void NRGDontRemoveSnapshotIfTruncateToApplied_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2648 + public void NRGSnapshotAndTruncateToApplied_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2649 + public void NRGIgnoreDoubleSnapshot_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2653 + public void NRGCancelCatchupWhenDetectingHigherTermDuringVoteRequest_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2655 + public void NRGTruncateDownToCommitted_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2656 + public void NRGTruncateDownToCommittedWhenTruncateFails_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2658 + public void NRGMemoryWALEmptiesSnapshotsDir_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2659 + public void NRGHealthCheckWaitForCatchup_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2660 + public void NRGHealthCheckWaitForDoubleCatchup_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2661 + public void NRGHealthCheckWaitForPendingCommitsWhenPaused_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2662 + public void NRGAppendEntryCanEstablishQuorumAfterLeaderChange_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2665 + public void NRGSignalLeadChangeFalseIfCampaignImmediately_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2666 + public void NRGCatchupDontCountTowardQuorum_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2668 + public void NRGRejectNewAppendEntryFromPreviousLeader_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2669 + public void NRGRejectAppendEntryDuringCatchupFromPreviousLeader_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2673 + public void NRGSnapshotRecovery_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2676 + public void NRGInitializeAndScaleUp_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2677 + public void NRGReplayOnSnapshotSameTerm_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2678 + public void NRGReplayOnSnapshotDifferentTerm_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2679 + public void NRGSizeAndApplied_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2680 + public void NRGIgnoreEntryAfterCanceledCatchup_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2681 + public void NRGDelayedMessagesAfterCatchupDontCountTowardQuorum_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2682 + public void NRGStepdownWithHighestTermDuringCatchup_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2683 + public void NRGTruncateOnStartup_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2684 + public void NRGLeaderCatchupHandling_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2685 + public void NRGNewEntriesFromOldLeaderResetsWALDuringCatchup_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2686 + public void NRGProcessed_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2688 + public void NRGDrainAndReplaySnapshot_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2691 + public void NRGParallelCatchupRollback_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2696 + public void NRGTruncateLogWithMisalignedSnapshotGap_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2697 + public void NRGTruncateLogWithMissingSnapshot_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2703 + public void NRGUncommittedMembershipChangeGetsTruncated_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2715 + public void NRGInstallSnapshotFromCheckpoint_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2716 + public void NRGInstallSnapshotForce_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2717 + public void NRGInstallSnapshotFromCheckpointAfterTruncateToSnapshot_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2719 + public void NRGReplayAddPeerKeepsClusterSize_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + } diff --git a/porting.db b/porting.db index c31df8b610937e017409328092441d6168e4a183..6284fa2475a576d64a012fcdb037659aa15f23ed 100644 GIT binary patch delta 4125 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 Org5aHnOBJ8@c#i3Pox$A delta 5913 zcmbW54Nw$Uwt%O5dV2c58-iCvz!4M>F|vxRe=!qdh^r{5_^+fPAd2Ec;+jN_pfQaY z1$EJ5{EwS;v)RPBKG#WEKA-Wq`E^;Jr3QaPNa7MB*p-*c8h`MenZ};!dR4D#m#H(w zch9}&o_lWJGq+Do&0cp6%BG(D2QC-8(&cjX+1zIY^}%ZWHJ$piPVXDYVO!`A7VBEJ z&wZ6?W|*vVdyBo!o@Gz5N7w`Gc6L20Gb2Bi8);O& zWfO(8%_bMpx<|x4L|SfBC(b@eXxQH9Ep<9X#vSUV*(O>QG4Y;&Q(&QR89eLRERWm0afWzItdTS+qRo090m#MHrTpuNULm$L8`RrKON(uQ5Ozi6p|f4AuF<{ zFgQID`46#cID#h~y2lJZZTQ`WpE3L%!_OLiui@tmKX3R2!!H_s$?(fZ{R-<(`x731 zc8RJe_fq_Rl&UH`2e%t0d@?V?J+&)Js){?d1^c*o@vex6XS0Bmp|42`q2M7@}&Ep{tWu( zhXj8m{Nwoj{2TlxzBY0jr6~@Y?4U^w$`4Z@zg0_e!_Z<{g7Jc;_{0feWoe0UI+Db3 zp4L#t8YO(=Xm^|rv7e_id^&{B96giS$*!UBi%cpDwEL6<-|?Eput!`4FzHo|up*ED zN9dD;hwRx1V;zykgzvnV);2#C8!{CmTyrR|c=v~uFjLT~Xzyh(`)L{AAE9!r@F}+j zlgl+hdyD2Ptwg+0)XvlV+ZI$vT2ysJZWQ+NEfKElam=>cLAxBZQ&{KP@hAleJCN*T zCA{J2xgB+OvJ$}MstzYZVOwO<5wm9l}2dxt`BlovjcvYMg;rSXz=hY6XaX3)z(5-UN zD-K%epcM|PUhcq`9rTie9KT`0GKcQh4q7T@L@enAhpx&&OK7Po{76;{6%OqpX;(y4 z7dmw14q6~}M$9;0jyy7Dj-K-zRO%q$I8BCUSxu=HisiJ3xr-eAbO${rkBR76=+MnY zPwd}zVGdIGd7AC;a+YIU^-KrOaL{xIO>@vx2NgJIihMW1QAd6h9QjemXIw6t4PL`& z`hceCoZuNw4PsPxfUDGg{x^n=axL8I(Jrx`H$88%tKkr(Jq{-+E%E>TiVa++w80F` zji*!c-a3M}@Pb$=`oCkuB=Knf+(;Jp*xTc~R8xy(}dlG74kP$sq8x{nf}Z#YBo z-H^h!(-@?%gO4GF9gIc_I~au&o>@Z*JE$VrxrF~Iatrwn8L6E<7TlPlbjY9Q&&YEl zJowzv+wsf8f9lYE;-HVwO4x&skis7PC6Fg;hv{0%)KH>OqEQ}0i3w0aKAn`qma}N!kyeGZ$HSm-6BR(X+|qkaigCo z15Q!CE-yD1l3YvieIZ#Fp?L0Uo)_MG4p-gM+*=7yI=L7HqjTj1oYY64{fbY71xrXW z%zeU_YFVhLBAcOjTwFM0(Xh7)*E#zIYl(88;RSMwhNKHULVaT4=rS_U3etqeO8D?q zg3Ec4^mN1iUCGIiznqj=i;Zqv1RaGW9==&l7Fdy}SwSX*lz}TN$V*+}33?r0{Z;!Doj{MO07+8*-8j} zzm8;EJ2bG46k0BwtRq7$E9`o*)@u8Y^<=!&MqVeoA*oL43jB@N$#l!W_zh$^6iW$R zip77O#6sr=;K{FW-5SUu*st{J zGJ2$eJlXXCY$8P>47y}(OEkbvGTMsA-*=MzU6HEUg=SCeCNsgmXPioJjfaFaBoT7< z;86(0_t0LV!kIm!zvZN7FL}{cJRO>-mfA;9x}(IR^gxM2>4_4Ll7Nzk(knpi^PPSc zYFCq$;NQ}n2|Uy0>%&?r#(;8g@U~BYgB^HIgU1DKclg#??uQN+YM%!4VT@{+KEv#7 zm`R42Y?yrvv#(*M7-p(rrWs~G!%R2K{)U-hm;(&+al;&Fn3;z83&R{_n1c;7%P@x+ zX0~De(lCb_<}kw?ZkQtsbEIKDVVI)~^GU<>8|G7nIodFvHq0@G`HW%a80NEvIo2?L zWtig(bG%{Z8s>zf=ERTx4yS4dbe*5OU*wIoVxQlf_d6Q?u)5Don0O`cm!So@`!^QA zQ%gt!bgm>`ICdqk%33@gfvMJ#PhHJ>6DIGE?y?s;8w0Q8sqpT#yijVA1NX1x)pR|} z?|+#$Iuwy@`^GiaHn!vi8e8)J(ry_Y_{pT6@T;ataxfuf)wVTFLYa&*1*HIGD#|pJ z=_oT$W}?hOnT;|BWiCn~%5#CXCcOv6FvndF0-j8|lcJV^FPbKSxIy$03UbfuanLrH zo(7}N>pfv+7M%cEsn!qnX3@Q1O@@{N=@)br+Ry1S3@z2vfI5W!K@iz&*8^H{v1x1^ zrwb_)5N*FHpZxFS5FKqL9VsaBKLXd^*0Kp76e;exe=|QiNFU z6YdA$jv(;&`3}A%_+BgA`24zt_6<@jPd)-#-4FMcK-_heXQJ8>-*;IP;y zyv6(|=6Vu68goO~7A*X6zF_Ikds$?ewahZBfQQ99(W>4xduVngY|7ALA?}=>1Gic+ z8g(gJC3sWuj(6f~T@Bnjr}w2GE~wdgORt1`Nt!}YaPYjI4VRNO6;`zC3Y7p#KP*_) zwd?V)yG>W%!MA!k@X2T;Wgd3gctL*y?o?>1=WqCa5)VyTbRQ_ZsHf9nE*xvqdt!N_ zJQXc`o{A-*zg^US4=Fd$%#AV}94N)MVTK!UT5?}MgC_Qy85IcOyX9>F z3@cKw<Mk6Ep;D4z>cPHT&l?aJ_wJET= z4IBQ5Ula|eTd~`{R$RtkzsBdIGYtpyLnDF8tNJFlVd{oiWSGT<`MhD47-s2Fa~`8H zcj*EbY-!Pdtd`Gm$J~YPeD`Q~mOI5A%f0Is==*d>aNDg-=k{=$xHa?+ZYehp-|-K- z-wM`b-P_o>VErWcKzK}6k`K7oS(Oy`a;&B3@?@;iX492&TBxehDVcP!r&DTmFQN;& z>MQR^yCnErS69QqsInR0KZvjGDeXnLU>Qq`D}rCMJBs3A!0jRh2B>9~@JF?*03JxF z_`V(6yh@pZF*(ywlpVPIwVp&nZU+wUfg`CDC|Anj;G;AxK9GMyXK6UzQIr6el(Kjj zal0rTcB|Nn1~UUsTIv7{{lhlggkx!%6o})?F1SGqI#AJGlmm5gSq@y2%hIV-n5dMc ULFKna&j+6D&_AROXk~}~7g0&aa{vGU