/* Ċ Ġ* ĠCopyright Ġ 2 0 1 9 ĠT enk iv , ĠInc . Ċ Ġ* Ċ Ġ* ĠPermission Ġis Ġhereby Ġgranted , Ġfree Ġof Ġcharge , Ġto Ġany Ġperson Ġobtaining Ġa Ġcopy Ġof Ġthis Ġsoftware Ġand Ġassociated Ċ Ġ* Ġdocumentation Ġfiles Ġ( the Ġ" Software "), Ġto Ġdeal Ġin Ġthe ĠSoftware Ġwithout Ġrestriction , Ġincluding Ġwithout Ġlimitation Ġthe Ċ Ġ* Ġrights Ġto Ġuse , Ġcopy , Ġmodify , Ġmerge , Ġpublish , Ġdistribute , Ġsublicense , Ġand / or Ġsell Ġcopies Ġof Ġthe ĠSoftware , Ġand Ġto Ċ Ġ* Ġpermit Ġpersons Ġto Ġwhom Ġthe ĠSoftware Ġis Ġfurnished Ġto Ġdo Ġso , Ġsubject Ġto Ġthe Ġfollowing Ġconditions : Ċ Ġ* Ċ Ġ* ĠThe Ġabove Ġcopyright Ġnotice Ġand Ġthis Ġpermission Ġnotice Ġshall Ġbe Ġincluded Ġin Ġall Ġcopies Ġor Ġsubstantial Ġportions Ġof Ġthe Ċ Ġ* ĠSoftware . Ċ Ġ* Ċ Ġ* ĠTHE ĠSOFTWARE ĠIS ĠPROVIDED Ġ" AS ĠIS ", ĠWITHOUT ĠWARRANTY ĠOF ĠANY ĠKIND , ĠEXPRESS ĠOR ĠIMPLIED , ĠINCLUDING ĠBUT ĠNOT ĠLIMITED ĠTO ĠTHE Ċ Ġ* ĠWARRANTIES ĠOF ĠMERCHANTABILITY , ĠFITNESS ĠFOR ĠA ĠPARTICULAR ĠPURPOSE ĠAND ĠNONINFRINGEMENT . ĠIN ĠNO ĠEVENT ĠSHALL ĠTHE ĠAUTHORS ĠOR Ċ Ġ* ĠCOPYRIGHT ĠHOLDERS ĠBE ĠLIABLE ĠFOR ĠANY ĠCLAIM , ĠDAMAGES ĠOR ĠOTHER ĠLIABILITY , ĠWHETHER ĠIN ĠAN ĠACTION ĠOF ĠCONTRACT , ĠTORT ĠOR Ċ Ġ* ĠOTHERWISE , ĠARISING ĠFROM , ĠOUT ĠOF ĠOR ĠIN ĠCONNECTION ĠWITH ĠTHE ĠSOFTWARE ĠOR ĠTHE ĠUSE ĠOR ĠOTHER ĠDEALINGS ĠIN ĠTHE ĠSOFTWARE . Ċ Ġ*/ Ċ Ċ package Ġorg . ten k iv . ku ant ify . fs . configuration Ċ Ċ import Ġio . mock k .* Ċ import Ġkotlinx . coroutines .* Ċ import Ġkotlinx . coroutines . channels .* Ċ import Ġmu .* Ċ import Ġorg . spe k framework . spe k 2 .* Ċ import Ġorg . spe k framework . spe k 2 . style . g her kin .* Ċ import Ġorg . ten k iv . ku ant ify . fs . hardware . device .* Ċ import Ġorg . ten k iv . ku ant ify . fs . networking . communication .* Ċ import Ġorg . ten k iv . ku ant ify . fs . networking . configuration .* Ċ import Ġorg . ten k iv . ku ant ify . networking . communication .* Ċ import Ġorg . ten k iv . ku ant ify . networking . configuration .* Ċ Ċ val Ġlogger Ġ= ĠKotlin Logging . logger Ġ{} Ċ Ċ object ĠRoute Config Builder Feature Ġ: ĠSpe k ({ ĊĠĠĠ Ġval Ġlocal Device Ġ= Ġmock k Class ( Local Device :: class ) ĊĠĠĠ Ġevery Ġ{ Ġlocal Device . coroutine Context Ġ} Ġreturns ĠGlobal Scope . coroutine Context ĊĊĠĠĠ Ġval Ġlocal Network Com municator Ġ= Ġmock k Class ( Local Network Com municator :: class ) ĊĠĠĠ Ġevery Ġ{ Ġlocal Network Com municator . device Ġ} Ġreturns Ġlocal Device ĊĊĠĠĠ Ġval Ġremote Device Ġ= Ġmock k Class ( FS Remote Device :: class ) ĊĠĠĠ Ġevery Ġ{ Ġremote Device . coroutine Context Ġ} Ġreturns ĠGlobal Scope . coroutine Context ĊĊĠĠĠ Ġval Ġremote Network Com municator Ġ= Ġmock k Class ( FS Remote Websocket Com municator :: class ) ĊĠĠĠ Ġevery Ġ{ Ġremote Network Com municator . device Ġ} Ġreturns Ġremote Device ĊĠĠĠ Ġevery Ġ{ Ġremote Network Com municator . communication Mode Ġ} Ġreturns ĠCommunication Mode . NON _ EXCL USIVE ĊĊĠĠĠ ĠFeature (" Combined Route Config ") Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġconfig With Local Device Ġby Ġmemoized Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCom bined Route Config ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlocal Network Com municator ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġconfig With Remote Device Ġby Ġmemoized Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCom bined Route Config ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġremote Network Com municator ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġbuilder Ġby Ġmemoized Ġ{ ĠCom bined Route Binding Builder < String >() Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġbuild : ĠCom bined Route Binding Builder < String >. () Ġ-> ĠUnit Ġ= Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġset Local Update Channel ( Channel ()) Ġwith Update Channel Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsend From Host () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsend From Remote () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġserialize Message Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġwith Serializer Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreceive Message On Either Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ ĠScenario (" creating Ġroute Ġbinding Ġbuilder ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠWhen (" creating Ġroute Ġbinding Ġbuilder Ġthat Ġsends Ġand Ġreceives Ġmessages Ġon Ġboth Ġsides ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder . build () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠThen (" builder Ġshould Ġhave Ġnon - null Ġmessage Ġserializer ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġassert ( builder . serialize Message Ġ!= Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠThen (" builder Ġsend Ġfrom Ġhost Ġshould Ġbe Ġtrue ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġassert ( builder . send From Host ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠThen (" builder Ġsend Ġfrom Ġremote Ġshould Ġbe Ġtrue ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġassert ( builder . send From Remote ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠThen (" builder Ġreceive Ġmessage Ġon Ġeither Ġshould Ġbe Ġnon - null ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġassert ( builder . with Serializer ?. receive Message On Either Ġ!= Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ ĠScenario (" adding Ġroute Ġbinding Ġto Ġlocal Ġdevice Ġconfig ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder . build () ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠWhen (" adding Ġbinding Ġto Ġconfig ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconfig With Local Device . base Route . route (" a ", Ġ" b ", Ġ" c ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbind (" d ", Ġrecursive Synchron izer Ġ= Ġfalse , Ġbuild Ġ= Ġbuild ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnetwork Binding Path Ġ= Ġ" a / b / c / d " ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠThen (" network Ġconfig Ġshould Ġcontain Ġbinding Ġfor Ġroute ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġassert ( config With Local Device . network Route Binding Map . contains ( network Binding Path )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠThen (" route Ġbinding Ġshould Ġbe Ġof Ġtype Ġstandard ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġassert ( config With Local Device . network Route Binding Map [ network Binding Path ] Ġis ĠStandard Route Binding ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ ĠScenario (" adding Ġroute Ġbinding Ġto Ġremote Ġdevice Ġconfig ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder . build () ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠWhen (" adding Ġrecursive Ġsynchron izer Ġto Ġconfig ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconfig With Remote Device . base Route . route (" a ", Ġ" b ", Ġ" c ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbind (" d ", Ġrecursive Synchron izer Ġ= Ġtrue , Ġbuild Ġ= Ġbuild ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnetwork Binding Path Ġ= Ġ" a / b / c / d " ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠThen (" network Ġconfig Ġshould Ġcontain Ġbinding Ġfor Ġroute ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġassert ( config With Remote Device . network Route Binding Map . contains ( network Binding Path )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠThen (" route Ġbinding Ġshould Ġbe Ġof Ġtype Ġrecursion Ġprevent ing ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġassert ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconfig With Remote Device . network Route Binding Map [ network Binding Path ] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠRe cur sion Prevent ing Route Binding ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġ} ĊĊĠĠĠ ĠFeature (" Side Route Config ") Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġconfig With Local Device Ġby Ġmemoized Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠSide Route Config ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnetwork Com municator Ġ= Ġlocal Network Com municator , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġserialized Ping Ġ= ĠFS Device . serialized Ping , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġformat Path Ġ= Ġ:: format Path Standard ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġconfig With Remote Device Ġby Ġmemoized Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠSide Route Config ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnetwork Com municator Ġ= Ġremote Network Com municator , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġserialized Ping Ġ= ĠFS Device . serialized Ping , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġformat Path Ġ= Ġ:: format Path Standard ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġbuilder Ġby Ġmemoized Ġ{ ĠSide Route Binding Builder < String , ĠString >() Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġbuild : ĠSide Route Binding Builder < String , ĠString >. () Ġ-> ĠUnit Ġ= Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġserialize Message Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġset Local Update Channel ( Channel ()) Ġwith Update Channel Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsend () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreceive Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ ĠScenario (" creating Ġroute Ġbinding Ġbuilder ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠWhen (" bu iling Ġroute Ġbinding Ġbuilder Ġthat Ġsends Ġand Ġreceives Ġmessages ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder . build () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠThen (" builder Ġshould Ġhave Ġnon - null Ġmessage Ġserializer ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġassert ( builder . serialize Message Ġ!= Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠThen (" builder Ġsend Ġshould Ġbe Ġtrue ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġassert ( builder . send ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠThen (" builder Ġreceive Ġshould Ġbe Ġnon - null ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġassert ( builder . receive Ġ!= Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĊĠĠĠĠĠĠĠ ĠScenario (" adding Ġroute Ġbinding Ġto Ġlocal Ġdevice Ġconfig ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder . build () ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠWhen (" adding Ġbinding Ġto Ġconfig ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconfig With Local Device . base Route . route (" a ", Ġ" b ", Ġ" c ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbind (" d ", Ġbuild Ġ= Ġbuild ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnetwork Binding Path Ġ= Ġ" a / b / c / d " ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠThen (" network Ġconfig Ġshould Ġcontain Ġbinding Ġfor Ġroute ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġassert ( config With Local Device . network Route Binding Map . contains ( network Binding Path )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠThen (" route Ġbinding Ġshould Ġbe Ġof Ġtype Ġstandard ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġassert ( config With Local Device . network Route Binding Map [ network Binding Path ] Ġis ĠStandard Route Binding ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ ĠScenario (" adding Ġroute Ġbinding Ġto Ġremote Ġdevice Ġconfig ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder . build () ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠWhen (" adding Ġrecursive Ġsynchron izer Ġto Ġconfig ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconfig With Remote Device . base Route . route (" a ", Ġ" b ", Ġ" c ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbind (" d ", Ġrecursive Synchron izer Ġ= Ġtrue , Ġbuild Ġ= Ġbuild ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnetwork Binding Path Ġ= Ġ" a / b / c / d " ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠThen (" network Ġconfig Ġshould Ġcontain Ġbinding Ġfor Ġroute ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġassert ( config With Remote Device . network Route Binding Map . contains ( network Binding Path )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠThen (" route Ġbinding Ġshould Ġbe Ġof Ġtype Ġrecursion Ġprevent ing ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġassert ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconfig With Remote Device . network Route Binding Map [ network Binding Path ] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠRe cur sion Prevent ing Route Binding ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġ} Ċ })