/* Ċ Ġ* ĠCopyright Ġ( c ) ĠFacebook , ĠInc . Ġand Ġits Ġaffiliates . Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ Ċ package Ġcom . facebook . l ith o Ċ Ċ import Ġandroid . view . View . Measure Spec . EX ACT LY Ċ import Ġcom . facebook . l ith o . config . Components Configuration Ċ import Ġcom . facebook . l ith o . testing . Background Layout Looper Rule Ċ import Ġcom . facebook . l ith o . testing . L ith o View Rule Ċ import Ġcom . facebook . l ith o . testing . test runner . L ith o TestRunner Ċ import Ġcom . facebook . l ith o . widget . Text Ċ import Ġjava . util . concurrent . Count DownLatch Ċ import Ġjava . util . concurrent . atomic . Atomic Integer Ċ import Ġjava . util . concurrent . atomic . Atomic Reference Ċ import Ġorg . assertj . core . api . Assertions . assertThat Ċ import Ġorg . junit . Rule Ċ import Ġorg . junit . Test Ċ import Ġorg . junit . runner . RunWith Ċ Ċ /** ĠUnit Ġtests Ġfor Ġ[ useState ]. Ġ*/ Ċ @ RunWith ( L ith o TestRunner :: class ) Ċ class ĠK State Test Ġ{ ĊĊĠ Ġ@ Rule Ġ@ Jvm Field Ġval Ġl ith o View Rule Ġ= ĠL ith o View Rule () ĊĠ Ġ@ Rule Ġ@ Jvm Field Ġval Ġbackground Layout Looper Rule Ġ= ĠBackground Layout Looper Rule () ĊĊĠ Ġprivate Ġfun Ġ< T > ĠD sl Scope . use Custom State ( value : ĠT ): ĠState < T > Ġ{ ĊĠĠĠ Ġval Ġstate Ġby ĠuseState Ġ{ Ġvalue Ġ} ĊĠĠĠ Ġreturn Ġstate ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun ĠuseState _ update State _ state Is Updated () Ġ{ ĊĠĠĠ Ġlateinit Ġvar Ġstate Ref : ĠAtomic Reference < State < String >> ĊĠĠĠ Ġlateinit Ġvar Ġrow : ĠRow ĊĊĠĠĠ Ġval Ġroot Ġ= ĠK Component Ġ{ ĊĠĠĠĠĠ Ġval Ġstate Ġby ĠuseState Ġ{ Ġ" hello " Ġ} ĊĠĠĠĠĠ Ġstate Ref Ġ= ĠAtomic Reference ( state ) ĊĊĠĠĠĠĠ ĠClick able ( onClick Ġ= Ġ{ Ġupdate State Ġ{ Ġstate . value Ġ= Ġ" world " Ġ} Ġ}) Ġ{ ĊĠĠĠĠĠĠĠ Ġrow Ġ= ĠRow () ĊĠĠĠĠĠĠĠ Ġrow ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġl ith o View Rule . set Root ( root ) ĊĠĠĠ Ġl ith o View Rule . attach To Window (). measure (). layout () ĊĊĠĠĠ ĠassertThat ( state Ref . get (). value ). isEqualTo (" hello ") ĊĊĠĠĠ Ġ// ĠSim ulate Ġclicking Ġby Ġdispatch ing Ġa Ġclick Ġevent . ĊĠĠĠ ĠEvent Dispatcher Utils . dispatch OnClick ( row . common Props !!. click Handler , Ġl ith o View Rule . l ith o View ) ĊĠĠĠ Ġbackground Layout Looper Rule . run To EndOf Tasks Sync () ĊĊĠĠĠ ĠassertThat ( state Ref . get (). value ). described As (" String Ġstate Ġis Ġupdated "). isEqualTo (" world ") ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun ĠuseState On Hooks _ update State _ state Is Updated () Ġ{ ĊĠĠĠ ĠComponents Configuration . is Hooks Impl Enabled Ġ= Ġtrue ĊĊĠĠĠ ĠuseState _ update State _ state Is Updated () ĊĊĠĠĠ ĠComponents Configuration . is Hooks Impl Enabled Ġ= Ġfalse ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun ĠuseState On Hooks _ update Two States With Same PropertyName _ both States Are Updated In dependent ly () Ġ{ ĊĠĠĠ ĠComponents Configuration . is Hooks Impl Enabled Ġ= Ġtrue ĊĊĠĠĠ Ġlateinit Ġvar Ġstate 1 Ref : ĠAtomic Reference < State < String >> ĊĠĠĠ Ġlateinit Ġvar Ġstate 2 Ref : ĠAtomic Reference < State < Int >> ĊĠĠĠ Ġlateinit Ġvar Ġrow : ĠRow ĊĊĠĠĠ Ġval Ġroot Ġ= ĠK Component Ġ{ ĊĠĠĠĠĠ Ġval Ġstate 1 Ġ= Ġuse Custom State (" hello ") ĊĠĠĠĠĠ Ġval Ġstate 2 Ġ= Ġuse Custom State ( 2 0 ) ĊĊĠĠĠĠĠ Ġstate 1 Ref Ġ= ĠAtomic Reference ( state 1 ) ĊĠĠĠĠĠ Ġstate 2 Ref Ġ= ĠAtomic Reference ( state 2 ) ĊĊĠĠĠĠĠ ĠClick able ( ĊĠĠĠĠĠĠĠĠĠ ĠonClick Ġ= Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġupdate State Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstate 1 . value Ġ= Ġ" world " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstate 2 . value ++ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ}) Ġ{ ĊĠĠĠĠĠĠĠ Ġrow Ġ= ĠRow () ĊĠĠĠĠĠĠĠ Ġrow ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġl ith o View Rule . set Root ( root ) ĊĠĠĠ Ġl ith o View Rule . attach To Window (). measure (). layout () ĊĊĠĠĠ ĠassertThat ( state 1 Ref . get (). value ). isEqualTo (" hello ") ĊĠĠĠ ĠassertThat ( state 2 Ref . get (). value ). isEqualTo ( 2 0 ) ĊĊĠĠĠ Ġ// ĠSim ulate Ġclicking Ġby Ġdispatch ing Ġa Ġclick Ġevent . ĊĠĠĠ ĠEvent Dispatcher Utils . dispatch OnClick ( row . common Props !!. click Handler , Ġl ith o View Rule . l ith o View ) ĊĠĠĠ Ġbackground Layout Looper Rule . run To EndOf Tasks Sync () ĊĊĠĠĠ ĠassertThat ( state 1 Ref . get (). value ). described As (" String Ġstate Ġis Ġupdated "). isEqualTo (" world ") ĊĠĠĠ ĠassertThat ( state 2 Ref . get (). value ). described As (" Int Ġstate Ġis Ġupdated "). isEqualTo ( 2 1 ) ĊĊĠĠĠ ĠComponents Configuration . is Hooks Impl Enabled Ġ= Ġfalse ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun ĠuseState _ calculate Layout In Two Threads Concurrent ly _ state IsInitialized Only Once () Ġ{ ĊĠĠĠ Ġval Ġinit Counter Ġ= ĠAtomicInteger ( 0 ) ĊĠĠĠ Ġval Ġcount DownLatch Ġ= ĠCount DownLatch ( 2 ) ĊĠĠĠ Ġval Ġfirst Count DownLatch Ġ= ĠCount DownLatch ( 1 ) ĊĠĠĠ Ġval Ġsecond Count DownLatch Ġ= ĠCount DownLatch ( 1 ) ĊĊĠĠĠ Ġval Ġthread 1 Ġ= ĠThread Ġ{ ĊĠĠĠĠĠ Ġl ith o View Rule . set Root And Size Spec ( ĊĠĠĠĠĠĠĠĠĠ ĠCount DownLatch Component ( first Count DownLatch , Ġsecond Count DownLatch , Ġinit Counter ), ĊĠĠĠĠĠĠĠĠĠ ĠSize Spec . make Size Spec ( 1 0 0 , ĠEX ACT LY ), ĊĠĠĠĠĠĠĠĠĠ ĠSize Spec . make Size Spec ( 1 0 0 , ĠEX ACT LY )) ĊĠĠĠĠĠ Ġcount DownLatch . count Down () ĊĠĠĠ Ġ} ĊĠĠĠ Ġval Ġthread 2 Ġ= ĠThread Ġ{ ĊĠĠĠĠĠ Ġfirst Count DownLatch . await () ĊĊĠĠĠĠĠ Ġl ith o View Rule . set Root And Size Spec ( ĊĠĠĠĠĠĠĠĠĠ ĠCount DownLatch Component ( second Count DownLatch , Ġnull , Ġinit Counter ), ĊĠĠĠĠĠĠĠĠĠ ĠSize Spec . make Size Spec ( 2 0 0 , ĠEX ACT LY ), ĊĠĠĠĠĠĠĠĠĠ ĠSize Spec . make Size Spec ( 2 0 0 , ĠEX ACT LY )) ĊĠĠĠĠĠ Ġcount DownLatch . count Down () ĊĠĠĠ Ġ} ĊĠĠĠ Ġthread 1 . start () ĊĠĠĠ Ġthread 2 . start () ĊĠĠĠ Ġcount DownLatch . await () ĊĊĠĠĠ ĠassertThat ( init Counter . get ()). described As (" init Counter Ġis Ġinitialized Ġonly Ġonce "). isEqualTo ( 1 ) ĊĠĠĠ Ġval Ġcomponent Tree Ġ= Ġl ith o View Rule . component Tree ĊĠĠĠ ĠassertThat ( component Tree . initialState Container . m Initial Hook States ) ĊĠĠĠĠĠĠĠ Ġ. described As (" Initial Ġhook Ġstate Ġcontainer Ġis Ġempty ") ĊĠĠĠĠĠĠĠ Ġ. isEmpty () ĊĠĠĠ ĠassertThat ( component Tree . initialState Container . m Pending State Handlers ) ĊĠĠĠĠĠĠĠ Ġ. described As (" No Ġpending ĠState Handlers ") ĊĠĠĠĠĠĠĠ Ġ. isEmpty () ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun ĠuseState On Hooks _ calculate Component In Two Threads Concurrent ly _ state IsInitialized Only Once () Ġ{ ĊĠĠĠ ĠComponents Configuration . is Hooks Impl Enabled Ġ= Ġtrue ĊĊĠĠĠ Ġval Ġinit Counter Ġ= ĠAtomicInteger ( 0 ) ĊĠĠĠ Ġval Ġcount DownLatch Ġ= ĠCount DownLatch ( 2 ) ĊĠĠĠ Ġval Ġfirst Count DownLatch Ġ= ĠCount DownLatch ( 1 ) ĊĠĠĠ Ġval Ġsecond Count DownLatch Ġ= ĠCount DownLatch ( 1 ) ĊĊĠĠĠ Ġval Ġthread 1 Ġ= ĠThread Ġ{ ĊĠĠĠĠĠ Ġl ith o View Rule . set Root And Size Spec ( ĊĠĠĠĠĠĠĠĠĠ ĠCount DownLatch Component ( first Count DownLatch , Ġsecond Count DownLatch , Ġinit Counter ), ĊĠĠĠĠĠĠĠĠĠ ĠSize Spec . make Size Spec ( 1 0 0 , ĠEX ACT LY ), ĊĠĠĠĠĠĠĠĠĠ ĠSize Spec . make Size Spec ( 1 0 0 , ĠEX ACT LY )) ĊĠĠĠĠĠ Ġcount DownLatch . count Down () ĊĠĠĠ Ġ} ĊĠĠĠ Ġval Ġthread 2 Ġ= ĠThread Ġ{ ĊĠĠĠĠĠ Ġfirst Count DownLatch . await () ĊĊĠĠĠĠĠ Ġl ith o View Rule . set Root And Size Spec ( ĊĠĠĠĠĠĠĠĠĠ ĠCount DownLatch Component ( second Count DownLatch , Ġnull , Ġinit Counter ), ĊĠĠĠĠĠĠĠĠĠ ĠSize Spec . make Size Spec ( 2 0 0 , ĠEX ACT LY ), ĊĠĠĠĠĠĠĠĠĠ ĠSize Spec . make Size Spec ( 2 0 0 , ĠEX ACT LY )) ĊĠĠĠĠĠ Ġcount DownLatch . count Down () ĊĠĠĠ Ġ} ĊĠĠĠ Ġthread 1 . start () ĊĠĠĠ Ġthread 2 . start () ĊĠĠĠ Ġcount DownLatch . await () ĊĊĠĠĠ ĠassertThat ( init Counter . get ()). described As (" init Counter Ġis Ġinitialized Ġonly Ġonce "). isEqualTo ( 1 ) ĊĠĠĠ Ġval Ġcomponent Tree Ġ= Ġl ith o View Rule . component Tree ĊĠĠĠ ĠassertThat ( component Tree . initialState Container . m Initial Hook States ) ĊĠĠĠĠĠĠĠ Ġ. described As (" Initial Ġhook Ġstate Ġcontainer Ġis Ġempty ") ĊĠĠĠĠĠĠĠ Ġ. isEmpty () ĊĠĠĠ ĠassertThat ( component Tree . initialState Container . m Pending Hooks Handlers ) ĊĠĠĠĠĠĠĠ Ġ. described As (" No Ġpending ĠHooks Handlers ") ĊĠĠĠĠĠĠĠ Ġ. isEmpty () ĊĊĠĠĠ ĠComponents Configuration . is Hooks Impl Enabled Ġ= Ġfalse ĊĠ Ġ} ĊĊĠ Ġprivate Ġclass ĠCount DownLatch Component ( ĊĠĠĠĠĠ Ġcount DownLatch : ĠCount DownLatch , ĊĠĠĠĠĠ Ġawait able : ĠCount DownLatch ?, ĊĠĠĠĠĠ Ġinit Counter : ĠAtomicInteger ĊĠ Ġ) Ġ: ĊĠĠĠĠĠ ĠK Component ({ ĊĠĠĠĠĠĠĠ Ġcount DownLatch . count Down () ĊĠĠĠĠĠĠĠ Ġawait able ?. await () ĊĊĠĠĠĠĠĠĠ Ġval Ġstate Ġby ĠuseState Ġ{ Ġinit Counter . increment AndGet () Ġ} ĊĠĠĠĠĠĠĠ ĠText (" state Value Ġis Ġ${ state . value }") ĊĠĠĠĠĠ Ġ}) Ċ } Ċ