ð¿/gÜìýžÞ¬zˆ{ÙD_/•�½$*æšuœ‚¹ÖT{è0/˜ˆ>!èdÉl�àñ8Ü ±Y�ú¢P/qtRô‰QCï|X”Îô,lpMÚBk%S©bø“Î”›*ñ™C/çæ Awe8ÌÈ/æÇÕÙ%GßyaMÔ.Yq®5›å�/Ü‰hœ{C·2'2HTF1ÞIPn÷Ú§ìä[±’Â£(*óš£ÒLµ»kó¹þ»ÀÍ!R±hºÛ¡Sü€Ãð}}\JìnR‰OLÈ-­Q±Õ?k~c#•çÅÖ+âx‚ëÙ«^‡ß­õ÷å%fLGÏ�×Ø&#PÚ‡Ü’ð÷ÖpÃw¢rafì”¡}®”÷ÏvF‘ÉÝ&†nËˆ§S¶p¬#I´Úaç�Ÿ1öÊ_‘¶Õ2r=:XQJe«sôÔk�ÝÈÆÍ>³‹¿<×OîŽØ«M¹²ßÄ·±J¦ÎˆéËðH}½]ò±Þ;G©üð®·'å–=E«q�s TT[/ˆòâý„HM™[…4…£ò¹	€©ø%Ôê'ê¬uzë) 6¶�oCù÷Ÿ5óP2·›×AÙ&!ñðBèBÄ
@KÄc´_o@ù‡§ ýŽÏ²òÔŠÕè¦,!lÁA¥åžbê¤p/’båèì�ø¯ºh¥¼€yô¨N²qµ­Ž:´ÌÌ9ž¨’ä’‚~°Š`àë9¶¡úªÆ¬
WA‡¿ßX‘|B±UÐZB¨ëHA¾‹ÊNŒôç½’ŸÑ¿õæB¥pôoÆ©QÄ�h
ã>~ež%òÅù…q³ñïvÅ«Kîæe?DÌ`…[Z‹y-D ýì…#g¤:«›ÐO±¤©”6�ŸT!°³’¡ÝòWŠ�T“˜o‘
âÝ‹5D„½ŒÆs?S
7(µ˜�÷b¬ôcn|ô·¢­ ÀÑ,rXë1×Þe‡3ÐÇƒ¿[Ü€öUemÞ!�sm®s ~¥âŠúƒcTAÈS¢îz�Ç ëHè«~HCç“lôj’kÕDViP™ˆí­3—åˆ­Íît•Q÷‚É—ÊÔN˜‡ª-²Ô °è9ÍŒÖ([J¬P×Ý Ù‹^€?oµDÎ´wtïL-9Ëzs€sºf¸‡£.>F?£ÃŠ²½óÎ{#}&«—T÷Ø;#�R�tèß«÷È_ý(þJ¬s¯çR.a�R£´|™&¦�.øR.Ž*¯†¥þòDLL†³’!�ï‘{¸{Xò³h¨Tï’ì”Q‚˜æZ´’k×Aê�FákŸQ†pZ�œñò¼B¤Áz/\-KFÓ$x ~°ã…Q½(8�Ô§ ¸ˆ42…§>GX§’d¡¬Cý]´¸ë3]¦OpÍž8Þ’'Rœï?-t_:Á7bž@?‰ùÖ=šHmÍkÐNÛ_ÊZ¯Pÿá¨IáÀ©œÏ5qM’mLõ�^< z4×iß	•oõ“øU
â{ŒTa£µ«;XÊ‰Å8ôÉÂCKIiœy"s²„ËºtÎB¯nÓiF:
P-Û	á¼l®{�T…ÓíÊyµ¸Uªðé#Ôÿ…¨üZ†-Ù°mŒ°æÑªšqn»C“~©:>¼Í%g”�L¤¡\‚ÆèVb´)&ÀULW¬ŸðÂ­y�kì"*”Ñ¼­›ÑhW«ò(ì·^><LÚ#çŸñÎ¿Æ“%qƒzŸãìT’1¼{„{F>Ó0Á¾÷V£T�4˜cnüõl’¬|'ÓxÔÝžÚS=Ê|ÓuFT‚î#¬ñXLh­¬Ø
�³Ä"yLBg3÷ÜÒ
{¿céY¦íø^(Ò$2‡æKjù#Þ-£¥�Éój<¬”�„»éq°v‰#œ5ùº‡ÚÖ‹.SXÝ�x§v¢×y?°7wº½nnááªŸeÇce·2Õµ4àÐRè.‡7ÞÃçË×‰×&KÝåý 7?õ‹Á¦D<Žò^âOútçâ ‚åk}ô®ß‡õDŽ‚BpY_«¸‘ìxüBnh¹5Î�M5¤¿TlÈŒðUÓî`@`ùYh³¤^ŸLñ†Yàpý¥ò»Û5mG�ì†·¸£áD5`Q¦Ìõ3©nwÌ™=^÷�(Ââº1âOútçâ ‚åk}ô®ß‡õDŽ‚BpY_«¸‘ì’\ÄÇ#7Râô£ž=ZÓä3Q«°šË·C·³ÃÇÝÊh¶ÿîÓ‘z™1($I7ŸpÈšÍ8éi<H[ÞC¡týøibl†ím�‡ì)fFÁ„ëH�´ü²�Lî¶{þ'ÍïàR«#®g•Á8.Œx·îç'¦$u××1N7†®v8p­ÂlgÄ{ª2Ü]ç¡ÎS'÷ÿ¾QáŸ93	oYÊ}ËlPê˜]!E„JÅþ Ž7$èç]aûÜ±*ÔJ�„2-EùÜ�Æ/“¼VêaV×u‘—b¿Ðð�ß0ð6N]ªª�:jšôP•'*ŒúÏC¯µ8$Ë’�p„+RË.‘Õæ€´êEá_ò�1è]…–ó‹aÚ�'zº0«÷È_ý(þJ¬s¯çR.aí4›—DSÁ>€{^§ 0�¢mp­Ås9T£üsABÙLtäF{Ý×Au•ÈyggŠÃÒŒ	³ïãp˜d‡ámF× åÍ’í Íøü!™´I]Ä&…å�’üÌ1‘sÄt*/*cÀ�ëvC]8ÁÞ^™#¢ÛR¸¶Uò¶·ä±ë\�Ò}¯ÊÑ¤®U)›v8¿ù–.zÙÈcmæŠÎÃàÌG”9–+O�f(Åñ¡Tjö4÷š¤`»™–¿0›„V/‡»Á‡ùl~³µ!ÄÚ?9Þ^ƒsmuðÜ„¿1å>·E@ôâÝûïNRaýŒOáPàŽ’.É'1uJ™::U»˜"4(DNoG(ïÏ�
9¹óø=wÊTöÒ½H”¤ð©†ƒáðžY:äÜÑ={ŽB1¶,‚Ø9 íñŽÃ©êÓ5Á9p9×‡P3o|¹DïDÑDãŸáƒ½œN^Bú™_AHe�ÌÝº;âfûùjàý ¨ÁÔvìtrj´íq+×uC¶*
í‘e2àj‚Þä]ùçT$TßEt'¡?�Ð2oT†RLÈ5ÙnMÀ¸ùÎ»I/zß�Ð2~•1�EÝ»ÊS	­4:lnv>©Ê.ÞÚ	ÓÏ›Vãó×,~ÔcÒˆ¿hGBfgxPå™sÉˆRÂjOCéç6¤MøR2åiU×µce=U&¦©*9¥M´§¿ïên-©ŸRiÏ
»?®CdÉ¼PÒr¯–—‹{Vé}e�²‘vš ÷Ñž#_ÐŒU^ŠhS@¬¬ØÛÉ},êHãF„÷^²„#ÿ,�?¿q*)€î•«€â[[zÕÊÇËv;-ðÔ�_G9²§jfêô¸°¡Qa/’+óæÁ�GðÍÿu‡UHÀ)­°c¥ÉÞxn%³ë”ÌéCK" ÿ¸â›$4ÏI‘¡$!Ÿhjÿ}Ái>HÁŠ:
C\m`»¸°;ó·ÙØòu¯žRãDòÒWüµ×´ˆ&á•I·éèXsç«'óÅ®	?ô1-¡P-ÞÈ8´c(c16*nŸ|mƒò“2öÝjOíÇ�úÊý/éŒ	*k�Ã²¸wÓ ¢�TÀ€{¼R8‹Öc)©óí±î�ã¨†�ŠZÃ,>xHqÜ^Ò—Ì…Í^j}ÚN£"ès_¯æo[]j¼ƒn!ã–.r
Ç7.â8ˆZæƒÓ™œ®ÓBZ„T…¥»¸Ðs“~œÚéëó¦©ˆ®[ã°Ïw>ë»±è c"ˆ¢Ñl Šô]Í¥PD§‘�%%:ø-VÎü h¥!uY'¼�„Ÿ€“Ù˜>De)4gì³Ò±Z”7ý¬¦T£Ð¨i&«É³n–ëvÆ'ôÏ­ð"Ú×Ý�+Ü‚üO÷ÜÈ…ÏDF…QÒe;?“Hv"<~�*5œŽWrÞ2`
è—oz+€Ežm5’*àÜ39c?pÇzµ³C@hë¨J{Ñ¸Y²¯Öñéñ°¨Á4þËcðÑÉ±Ê)6�‘!Eoy­$$D®D\0ï-Ó·‹ãrjgÝzc~J„¾Ê$+ÎtÉ°¸­[â°-áXväU÷VEƒáF“Ô×ÒA½hÂM¶ñ0`|ž–è·rý7HÓ’€ýŸ räÆ<*ŸÀ‰ ­½=ûwv0DßAâ†^S4ñ›Ä«Æªn�@¯*y^g™Oü’kÈS^òŽ²U8ùÊ[›Q!ÜÿŽª=ûŸ`^ YûÚhÏËÈ¤ëî³y�æÿ
‚�Ÿ„dýàYã�êš[âD•Þ8Mº� Ä¡Z¯öü,õÒÎLvX€Óg²ÖêKäô!feF˜a¹Ç•…Ø% +‚ õ+�TûƒÙÍ€¡S05Œë­\­�Â‰@ðÍ™µß¯,„÷�kÂ=w <.0TÚ°G•‡–UÒƒmûhMgsíaf ·½‘Ý0ë˜é»J¥ÈZ}
ü­X\¸ÈÇ…–H�;é<•ÝÄ|Ahè_ìò;¯ñ~•…+Í½’,ïš§ë>š2°ç§(Œ}ÿ¦ÐÉŒ=Üº7)JDþëË¶¯OÑû¨{gï¥ÞPÿr—œé pU`�@bÓ�ùD<‡»-^‘üÃE #Ù"ºÕ[ØÍØ÷U›FüïRPL\àZ™ãCŠŒãðj7#)Å‡ÁÇl}‘ô\ÁG{ÍŸQN5’¼˜›8ã¯&%Ê;ã�¸D•óW¥k]ô”ýš‡ãÁºqÚ6aj1…Šx�?¾»ÉXû*pëu°’ ]ôïƒ…1 á›[m%ÉÝ$’÷åf!º}ÒÓ-
Ä©žœ�6K[ä8ò®ÊÁô'fØ0Í]Zß4u‰£�œùŽšï#£›Aì(ûruC2¶ºà«S
µØ-—Û{~?7¿�$ÓÝ!o	‰è!‹‹=“Þû
k%;¹¼Ë­Fwã|£.È3Óó&Ê|†m½ó%WÂ'ä¨$¡7öpÍnÎ¸Aˆ/íàÓ™0ö}aß¿†aRw‡ŒœÊ”?ÂóW¢¦çlZ² m†zg�`_oq·&öà"%ý½7Å;#Ón§Ž¤A(](!ñ@IB¨ØqÖ?ê5…-)R·A<@^?2Y›4C—•Ý-Ïö™ž¨:rpp
¿‹õ<ˆÕgÀº-øðÎ\.—qÐ� :@It±6ÍÎ÷ó^q´õ%½/‹(Ö•	H«ÙcÑM5»³€¤�šs&�S4‘]–å›õºãÀ•¯-h/"¬æã¼Xaš) \Õ ÄU_£ÉÙ÷ÂÙ`&óf¶
:)ä¬‡Ú)�OúÖ„Ìü½Ü`É[!=U¿Rh¡  if sys.platform == "darwin":
        sys.path.append(os.path.abspath("test/lib"))
        import TestMac

        print(f"  Mac {platform.mac_ver()[0]} {platform.mac_ver()[2]}")
        print(f"  Xcode {TestMac.Xcode.Version()}")
    elif sys.platform == "win32":
        sys.path.append(os.path.abspath("pylib"))
        import gyp.MSVSVersion

        print("  Win %s %s\n" % platform.win32_ver()[0:2])
        print("  MSVS %s" % gyp.MSVSVersion.SelectVisualStudioVersion().Description())
    elif sys.platform in ("linux", "linux2"):
        print("  Linux %s" % " ".join(platform.linux_distribution()))
    print(f"  Python {platform.python_version()}")
    print(f"  PYTHONPATH={os.environ['PYTHONPATH']}")
    print()


class Runner:
    def __init__(self, formats, tests, gyp_options, verbose):
        self.formats = formats
        self.tests = tests
        self.verbose = verbose
        self.gyp_options = gyp_options
        self.failures = []
        self.num_tests = len(formats) * len(tests)
        num_digits = len(str(self.num_tests))
        self.fmt_str = "[%%%dd/%%%dd] (%%s) %%s" % (num_digits, num_digits)
        self.isatty = sys.stdout.isatty() and not self.verbose
        self.env = os.environ.copy()
        self.hpos = 0

    def run(self):
        run_start = time.time()

        i = 1
        for fmt in self.formats:
            for test in self.tests:
                self.run_test(test, fmt, i)
                i += 1

        if self.isatty:
            self.erase_current_line()

        self.took = time.time() - run_start

    def run_test(self, test, fmt, i):
        if self.isatty:
            self.erase_current_line()

        msg = self.fmt_str % (i, self.num_tests, fmt, test)
        self.print_(msg)

        start = time.time()
        cmd = [sys.executable, test] + self.gyp_options
        self.env["TESTGYP_FORMAT"] = fmt
        proc = subprocess.Popen(
            cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=self.env
        )
        proc.wait()
        took = time.time() - start

        stdout = proc.stdout.read().decode("utf8")
        if proc.returncode == 2:
            res = "skipped"
        elif proc.returncode:
            res = "failed"
            self.failures.append(f"({test}) {fmt}")
        else:
            res = "passed"
        res_msg = f" {res} {took:.3f}s"
        self.print_(res_msg)

        if stdout and not stdout.endswith(("PASSED\n", "NO RESULT\n")):
            print()
            print("\n".join(f"    {line}" for line in stdout.splitlines()))
        elif not self.isatty:
            print()

    def print_(self, msg):
        print(msg, end="")
        index = msg.rfind("\n")
        if index == -1:
            self.hpos += len(msg)
        else:
            self.hpos = len(msg) - index
        sys.stdout.flush()

    def erase_current_line(self):
        print("\b" * self.hpos + " " * self.hpos + "\b" * self.hpos, end="")
        sys.stdout.flush()
        self.hpos = 0

    def print_results(self):
        num_failures = len(self.failures)
        if num_failures:
            print()
            if num_failures == 1:
                print("Failed the following test:")
            else:
                print("Failed the following %d tests:" % num_failures)
            print("\t" + "\n\t".join(sorted(self.failures)))
            print()
        print(
            "Ran %d tests in %.3fs, %d failed."
            % (self.num_tests, self.took, num_failures)
        )
        print()


if __name__ == "__main__":
    sys.exit(main())
