/* Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 2 0 ĠThe ĠAndroid ĠOpen ĠSource ĠProject Ċ Ġ* Ċ Ġ* Ġ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 . android . tools . idea . layout inspector . pipeline . app inspection Ċ Ċ import Ġcom . android . tools . app . inspection . App Inspection Ċ import Ġcom . android . tools . idea . app inspection . test . DEFAULT _ TEST _ IN SPE CTION _ STREAM Ċ import Ġcom . android . tools . idea . layout inspector . Layout Inspector Rule Ċ import Ġcom . android . tools . idea . layout inspector . MO DER N _ DEVICE Ċ import Ġcom . android . tools . idea . layout inspector . create Process Ċ import Ġcom . android . tools . idea . layout inspector . model . Android Window Ċ import Ġcom . android . tools . idea . layout inspector . pipeline . Inspector Client . Capability Ċ import Ġcom . android . tools . idea . layout inspector . pipeline . Inspector Client Settings Ċ import Ġcom . android . tools . idea . layout inspector . pipeline . adb . execute Shell Command Ċ import Ġcom . android . tools . idea . layout inspector . pipeline . app inspection . compose . IN COMPAT IBLE _ LIBRARY _ MESSAGE Ċ import Ġcom . android . tools . idea . layout inspector . pipeline . app inspection . compose . PRO GU AR DED _ LIBRARY _ MESSAGE Ċ import Ġcom . android . tools . idea . layout inspector . pipeline . app inspection . inspect ors . send Event Ċ import Ġcom . android . tools . idea . layout inspector . pipeline . app inspection . view . View Layout Inspector Client Ċ import Ġcom . android . tools . idea . layout inspector . ui . Inspector Banner Ċ import Ġcom . android . tools . idea . layout inspector . util . Reporting Count DownLatch Ċ import Ġcom . android . tools . idea . protobuf . ByteString Ċ import Ġcom . google . common . truth . Truth . assertThat Ċ import Ġkotlinx . coroutines . Comp letable Deferred Ċ import Ġkotlinx . coroutines . run Blocking Ċ import Ġorg . junit . Rule Ċ import Ġorg . junit . Test Ċ import Ġorg . junit . rules . Rule Chain Ċ import Ġjava . util . concurrent . Array BlockingQueue Ċ import Ġjava . util . concurrent . TimeUnit Ċ import Ġlayout inspector . compose . inspection . Layout Inspector Compose Protocol Ġas ĠCompose Protocol Ċ import Ġlayout inspector . view . inspection . Layout Inspector View Protocol Ġas ĠView Protocol Ċ Ċ private Ġval ĠMO DER N _ PROCESS Ġ= ĠMO DER N _ DEVICE . create Process ( stream Id Ġ= ĠDEFAULT _ TEST _ IN SPE CTION _ STREAM . stream Id ) Ċ Ċ /** ĠTimeout Ġused Ġin Ġthis Ġtest . ĠWhile Ġdebugging , Ġyou Ġmay Ġwant Ġextend Ġthe Ġtimeout Ġ*/ Ċ private Ġconst Ġval ĠTIME OUT Ġ= Ġ 1 L Ċ private Ġval ĠTIME OUT _ UNIT Ġ= ĠTimeUnit . SECONDS Ċ Ċ class ĠApp Inspection Inspector Client Test Ġ{ ĊĠ Ġprivate Ġval Ġinspection Rule Ġ= ĠApp Inspection Inspector Rule () ĊĠ Ġprivate Ġval Ġinspector Rule Ġ= ĠLayout Inspector Rule ( inspection Rule . create Inspector Client Provider ()) Ġ{ ĠlistOf ( MO DER N _ PROCESS . name ) Ġ} ĊĊĠ Ġ@ get : Rule ĊĠ Ġval Ġrule Chain Ġ= ĠRule Chain . outer Rule ( inspection Rule ). around ( inspector Rule ) ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġclient Can Connect Disconnect And Re connect () Ġ{ ĊĠĠĠ Ġinspector Rule . process Notifier . fire Connected ( MO DER N _ PROCESS ) ĊĠĠĠ ĠassertThat ( inspector Rule . inspector Client . isConnected ). isTrue () ĊĊĠĠĠ Ġinspector Rule . process Notifier . fire Disconnected ( MO DER N _ PROCESS ) ĊĠĠĠ ĠassertThat ( inspector Rule . inspector Client . isConnected ). isFalse () ĊĊĠĠĠ Ġinspector Rule . process Notifier . fire Connected ( MO DER N _ PROCESS ) ĊĠĠĠ ĠassertThat ( inspector Rule . inspector Client . isConnected ). isTrue () ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġinspector Starts Fetching Continuous ly On Connect If Live Mode () Ġ= Ġrun Blocking Ġ{ ĊĠĠĠ ĠIns pector Client Settings . is Capt uring Mode On Ġ= Ġtrue ĊĊĠĠĠ Ġval Ġstart Fetch Received Ġ= ĠComp letable Deferred < Unit >() ĊĠĠĠ Ġinspection Rule . view Inspector . listen When ({ Ġit . has Start Fetch Command () Ġ}) Ġ{ Ġcommand Ġ-> ĊĠĠĠĠĠ ĠassertThat ( command . start Fetch Command . continuous ). isTrue () ĊĠĠĠĠĠ Ġstart Fetch Received . complete ( Unit ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠInitial Ġfetch Ġaddition ally Ġtriggers Ġrequests Ġfor Ġcomp os ables ĊĠĠĠ Ġval Ġcompose Commands Ġ= ĠArray BlockingQueue < Compose Protocol . Command >( 1 ) ĊĠĠĠ Ġinspection Rule . compose Inspector . listen When ({ Ġtrue Ġ}) Ġ{ Ġcommand Ġ-> ĊĠĠĠĠĠ Ġcompose Commands . add ( command ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinspector Rule . process Notifier . fire Connected ( MO DER N _ PROCESS ) ĊĠĠĠ Ġstart Fetch Received . await () Ġ// ĠIf Ġhere , Ġwe Ġalready Ġsuccessfully Ġconnected Ġ( and Ġsent Ġan Ġinitial Ġcommand ) ĊĠĠĠ ĠassertThat ( inspector Rule . inspector Client ). isInstanceOf ( App Inspection Inspector Client :: class . java ) ĊĊĠĠĠ Ġ// ĠView ĠIns pector Ġlayout Ġevent Ġ-> ĠCompose ĠIns pector Ġget Ġcomp os ables Ġcommand ĊĠĠĠ Ġcompose Commands . take (). let Ġ{ Ġcommand Ġ-> ĊĠĠĠĠĠ ĠassertThat ( command . special ized Case ). isEqualTo ( Compose Protocol . Command . Special ized Case . GET _ COMP OS ABLE S _ COMMAND ) ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġinspector Requests Single Fetch If Snapshot Mode () Ġ= Ġrun Blocking Ġ{ ĊĠĠĠ ĠIns pector Client Settings . is Capt uring Mode On Ġ= Ġfalse ĊĊĠĠĠ Ġval Ġstart Fetch Received Ġ= ĠComp letable Deferred < Unit >() ĊĠĠĠ Ġinspection Rule . view Inspector . listen When ({ Ġit . has Start Fetch Command () Ġ}) Ġ{ Ġcommand Ġ-> ĊĠĠĠĠĠ ĠassertThat ( command . start Fetch Command . continuous ). isFalse () ĊĠĠĠĠĠ Ġstart Fetch Received . complete ( Unit ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠInitial Ġfetch Ġaddition ally Ġtriggers Ġrequests Ġfor Ġcomp os ables ĊĠĠĠ Ġval Ġcompose Commands Ġ= ĠArray BlockingQueue < Compose Protocol . Command >( 2 ) ĊĠĠĠ Ġinspection Rule . compose Inspector . listen When ({ Ġtrue Ġ}) Ġ{ Ġcommand Ġ-> ĊĠĠĠĠĠ Ġcompose Commands . add ( command ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinspector Rule . process Notifier . fire Connected ( MO DER N _ PROCESS ) ĊĠĠĠ Ġstart Fetch Received . await () Ġ// ĠIf Ġhere , Ġwe Ġalready Ġsuccessfully Ġconnected Ġ( and Ġsent Ġan Ġinitial Ġcommand ) ĊĠĠĠ ĠassertThat ( inspector Rule . inspector Client ). isInstanceOf ( App Inspection Inspector Client :: class . java ) ĊĊĠĠĠ Ġ// ĠView ĠIns pector Ġlayout Ġevent Ġ-> ĠCompose ĠIns pector Ġget Ġcomp os ables Ġcommand ĊĠĠĠ Ġcompose Commands . take (). let Ġ{ Ġcommand Ġ-> ĊĠĠĠĠĠ ĠassertThat ( command . special ized Case ). isEqualTo ( Compose Protocol . Command . Special ized Case . GET _ COMP OS ABLE S _ COMMAND ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġ// ĠView ĠIns pector Ġproperties Ġevent Ġ-> ĠCompose ĠIns pector Ġget Ġall Ġparameters ĊĠĠĠ Ġcompose Commands . take (). let Ġ{ Ġcommand Ġ-> ĊĠĠĠĠĠ ĠassertThat ( command . special ized Case ). isEqualTo ( Compose Protocol . Command . Special ized Case . GET _ ALL _ PARAMETERS _ COMMAND ) ĊĠĠĠ Ġ} ĊĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest View Debug Attributes Application Package Set And Reset () Ġ{ ĊĠĠĠ Ġinspector Rule . attach Device ( MO DER N _ DEVICE ) ĊĠĠĠ Ġinspector Rule . process Notifier . fire Connected ( MO DER N _ PROCESS ) ĊĠĠĠ ĠassertThat ( inspector Rule . adb Properties . debug View Attributes Application Package ). isEqualTo ( MO DER N _ PROCESS . name ) ĊĊĠĠĠ Ġ// ĠDis connect Ġdirectly Ġinstead Ġof Ġcalling Ġfire Disconnected Ġ- Ġotherwise , Ġwe Ġdon 't Ġhave Ġan Ġeasy Ġway Ġto Ġwait Ġfor Ġthe Ġdisconnect Ġto ĊĠĠĠ Ġ// Ġhappen Ġon Ġa Ġbackground Ġthread ĊĠĠĠ Ġinspector Rule . launcher . disconnect Active Client () ĊĠĠĠ ĠassertThat ( inspector Rule . adb Properties . debug View Attributes Application Package ). isNull () ĊĠĠĠ Ġ// ĠNo Ġother Ġattributes Ġwere Ġmodified ĊĠĠĠ ĠassertThat ( inspector Rule . adb Properties . debug View Attributes Changes Count ). isEqualTo ( 2 ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest View Debug Attributes Application Package Over ridden And Reset () Ġ{ ĊĠĠĠ Ġinspector Rule . attach Device ( MO DER N _ PROCESS . device ) ĊĠĠĠ Ġinspector Rule . adb Rule . bridge . execute Shell Command ( MO DER N _ PROCESS . device , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" settings Ġput Ġglobal Ġdebug _ view _ attributes _ application _ package Ġcom . example . another - app ") ĊĊĠĠĠ ĠassertThat ( inspector Rule . adb Properties . debug View Attributes Application Package ). isEqualTo (" com . example . another - app ") ĊĊĠĠĠ Ġinspector Rule . process Notifier . fire Connected ( MO DER N _ PROCESS ) ĊĠĠĠ ĠassertThat ( inspector Rule . adb Properties . debug View Attributes Application Package ). isEqualTo ( MO DER N _ PROCESS . name ) ĊĊĠĠĠ Ġinspector Rule . launcher . disconnect Active Client () ĊĠĠĠ ĠassertThat ( inspector Rule . adb Properties . debug View Attributes Application Package ). isNull () ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest View Debug Attributes Application Package Not Over ridden If Matching () Ġ{ ĊĠĠĠ Ġinspector Rule . attach Device ( MO DER N _ PROCESS . device ) ĊĠĠĠ Ġinspector Rule . adb Rule . bridge . execute Shell Command ( MO DER N _ PROCESS . device , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" settings Ġput Ġglobal Ġdebug _ view _ attributes _ application _ package Ġ${ MO DER N _ PROCESS . name }") ĊĊĠĠĠ ĠassertThat ( inspector Rule . adb Properties . debug View Attributes Application Package ). isEqualTo ( MO DER N _ PROCESS . name ) ĊĠĠĠ ĠassertThat ( inspector Rule . adb Properties . debug View Attributes Changes Count ). isEqualTo ( 1 ) ĊĊĠĠĠ Ġinspector Rule . process Notifier . fire Connected ( MO DER N _ PROCESS ) ĊĠĠĠ ĠassertThat ( inspector Rule . adb Properties . debug View Attributes Application Package ). isEqualTo ( MO DER N _ PROCESS . name ) ĊĠĠĠ ĠassertThat ( inspector Rule . adb Properties . debug View Attributes Changes Count ). isEqualTo ( 1 ) ĊĊĠĠĠ Ġinspector Rule . launcher . disconnect Active Client () ĊĠĠĠ ĠassertThat ( inspector Rule . adb Properties . debug View Attributes Application Package ). isEqualTo ( MO DER N _ PROCESS . name ) ĊĠĠĠ ĠassertThat ( inspector Rule . adb Properties . debug View Attributes Changes Count ). isEqualTo ( 1 ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġinspector S ends Stop Fetch Command () Ġ= Ġrun Blocking Ġ{ ĊĠĠĠ Ġval Ġstop Fetch Received Ġ= ĠComp letable Deferred < Unit >() ĊĠĠĠ Ġinspection Rule . view Inspector . listen When ({ Ġit . has Stop Fetch Command () Ġ}) Ġ{ ĊĠĠĠĠĠ Ġstop Fetch Received . complete ( Unit ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinspector Rule . process Notifier . fire Connected ( MO DER N _ PROCESS ) ĊĠĠĠ Ġinspector Rule . inspector Client . stop Fetching () ĊĠĠĠ Ġstop Fetch Received . await () ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġinspector F ires Error OnError Event () Ġ= Ġrun Blocking Ġ{ ĊĠĠĠ Ġval Ġstart Fetch Error Ġ= Ġ" Failed Ġto Ġstart Ġfetching Ġor Ġwhatever " ĊĊĠĠĠ Ġinspection Rule . view Inspector . intercept When ({ Ġit . has Start Fetch Command () Ġ}) Ġ{ ĊĠĠĠĠĠ Ġinspection Rule . view Inspector . connection . send Event Ġ{ ĊĠĠĠĠĠĠĠ Ġerror Event Builder . apply Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġmessage Ġ= Ġstart Fetch Error ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠ ĠView Protocol . Response . newBuilder (). set Start Fetch Response ( View Protocol . Start Fetch Response . getDefaultInstance ()). build () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġerror Ġ= ĠComp letable Deferred < String >() ĊĠĠĠ Ġinspector Rule . launcher . add Client Changed Listener Ġ{ Ġclient Ġ-> ĊĠĠĠĠĠ Ġclient . register Error Callback Ġ{ Ġerror . complete ( it ) Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinspector Rule . process Notifier . fire Connected ( MO DER N _ PROCESS ) ĊĠĠĠ ĠassertThat ( error . await ()). isEqualTo ( start Fetch Error ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġcompose Client Shows Message If Ol der Compose Ui Library () Ġ{ ĊĠĠĠ Ġinspection Rule . compose Inspector . create ResponseStatus Ġ= ĠApp Inspection . Create Inspector Response . Status . VERSION _ IN COMPAT IBLE ĊĠĠĠ Ġval Ġbanner Ġ= ĠIns pector Banner ( inspector Rule . project ) ĊĊĠĠĠ Ġinspector Rule . process Notifier . fire Connected ( MO DER N _ PROCESS ) ĊĊĠĠĠ ĠassertThat ( banner . text . text ). isEqualTo ( IN COMPAT IBLE _ LIBRARY _ MESSAGE ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġcompose Client Shows Message If Pro gu arded Compose Ui Library () Ġ{ ĊĠĠĠ Ġinspection Rule . compose Inspector . create ResponseStatus Ġ= ĠApp Inspection . Create Inspector Response . Status . APP _ PRO GU AR DED ĊĠĠĠ Ġval Ġbanner Ġ= ĠIns pector Banner ( inspector Rule . project ) ĊĊĠĠĠ Ġinspector Rule . process Notifier . fire Connected ( MO DER N _ PROCESS ) ĊĊĠĠĠ ĠassertThat ( banner . text . text ). isEqualTo ( PRO GU AR DED _ LIBRARY _ MESSAGE ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġinspector Tree Event Includes Update Screenshot Type Callback () Ġ{ ĊĠĠĠ Ġval Ġscreenshot Type Updated Ġ= ĠReporting Count DownLatch ( 1 ) ĊĠĠĠ Ġinspection Rule . view Inspector . listen When ({ Ġit . has Update Screenshot Type Command () Ġ}) Ġ{ Ġcommand Ġ-> ĊĠĠĠĠĠ ĠassertThat ( command . update Screenshot Type Command . type ). isEqualTo ( View Protocol . Screenshot . Type . BITMAP ) ĊĠĠĠĠĠ ĠassertThat ( command . update Screenshot Type Command . scale ). isEqualTo ( 1 . 0 f ) ĊĠĠĠĠĠ Ġscreenshot Type Updated . count Down () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinspector Rule . launcher . add Client Changed Listener Ġ{ Ġclient Ġ-> ĊĠĠĠĠĠ Ġclient . register Tree Event Callback Ġ{ Ġdata Ġ-> ĊĠĠĠĠĠĠĠ Ġ( client Ġas ĠApp Inspection Inspector Client ). update Screenshot Type ( Android Window . ImageType . BITMAP _ AS _ REQUEST ED ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinspector Rule . process Notifier . fire Connected ( MO DER N _ PROCESS ) ĊĠĠĠ Ġscreenshot Type Updated . await ( TIMEOUT , ĠTIME OUT _ UNIT ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġview Client Only Handles Most Recent Layout Event () Ġ{ ĊĠĠĠ Ġ// ĠThis Ġtest Ġwill Ġsend Ġtwo Ġbatches Ġof Ġlayout Ġevents , Ġto Ġverify Ġthat Ġwe Ġnot Ġonly Ġprocess Ġthe Ġlast Ġevent Ġof Ġa ĊĠĠĠ Ġ// Ġbatch , Ġbut Ġthat Ġonce Ġprocessed , Ġnew Ġevents Ġcan Ġbe Ġhandled Ġafterwards . ĊĠĠĠ Ġvar Ġhandling First Batch Ġ= Ġtrue ĊĊĠĠĠ Ġinspection Rule . view Inspector . intercept When ({ Ġit . has Start Fetch Command () Ġ}) Ġ{ ĊĠĠĠĠĠ Ġinspection Rule . view Inspector . connection . send Event Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠWe Ġmust Ġalways Ġsend Ġroots Ġat Ġleast Ġonce Ġbefore Ġthe Ġvery Ġfirst Ġlayout Ġevent ĊĠĠĠĠĠĠĠ Ġroots Event Builder . apply Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġadd Ids ( 1 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 .. 1 0 ) Ġ{ ĊĠĠĠĠĠĠĠ Ġinspection Rule . view Inspector . connection . send Event Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġlayout Event Builder . apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġroot View Builder . apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġid Ġ= Ġ 1 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġscreenshot Builder . apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbytes Ġ= ĠByte String . copyFrom ( byte ArrayOf ( i . to Byte ())) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠ ĠView Protocol . Response . newBuilder (). set Start Fetch Response ( View Protocol . Start Fetch Response . getDefaultInstance ()). build () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinspection Rule . view Inspector . intercept When ({ Ġit . has Stop Fetch Command () Ġ}) Ġ{ ĊĠĠĠĠĠ Ġ// ĠNote : ĠWe Ġdon 't Ġnormally Ġspam Ġa Ġbunch Ġof Ġlayout Ġevents Ġwhen Ġyou Ġstop Ġfetching , Ġbut Ġwe Ġdo Ġit ĊĠĠĠĠĠ Ġ// Ġhere Ġfor Ġconvenience , Ġas Ġstop Fetching Ġis Ġeasy Ġto Ġtrigger Ġin Ġthe Ġtest . ĊĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 1 1 .. 2 0 ) Ġ{ ĊĠĠĠĠĠĠĠ Ġinspection Rule . view Inspector . connection . send Event Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġlayout Event Builder . apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġroot View Builder . apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġid Ġ= Ġ 1 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġscreenshot Builder . apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbytes Ġ= ĠByte String . copyFrom ( byte ArrayOf ( i . to Byte ())) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠ ĠView Protocol . Response . newBuilder (). set Stop Fetch Response ( View Protocol . Stop Fetch Response . getDefaultInstance ()). build () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġtree Events Handled Ġ= ĠReporting Count DownLatch ( 1 ) ĊĠĠĠ Ġinspector Rule . launcher . add Client Changed Listener Ġ{ Ġclient Ġ-> ĊĠĠĠĠĠ Ġclient . register Tree Event Callback Ġ{ Ġdata Ġ-> ĊĠĠĠĠĠĠĠ Ġ( data Ġas ĠView Layout Inspector Client . Data ). view Event . let Ġ{ Ġview Event Ġ-> ĊĠĠĠĠĠĠĠĠĠ ĠassertThat ( view Event . root View . id ). isEqualTo ( 1 ) ĊĊĠĠĠĠĠĠĠĠĠ Ġif Ġ( handling First Batch ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġhandling First Batch Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertThat ( view Event . screenshot . bytes . byte At ( 0 )). isEqualTo ( 1 0 . to Byte ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclient . stop Fetching () Ġ// ĠT riggers Ġsecond Ġbatch Ġof Ġlayout Ġevents ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertThat ( view Event . screenshot . bytes . byte At ( 0 )). isEqualTo ( 2 0 . to Byte ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtree Events Handled . count Down () ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinspector Rule . process Notifier . fire Connected ( MO DER N _ PROCESS ) Ġ// ĠT riggers Ġfirst Ġbatch Ġof Ġlayout Ġevents ĊĠĠĠ Ġtree Events Handled . await ( TIMEOUT , ĠTIME OUT _ UNIT ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Capabilities Update Without Compose Nodes () Ġ{ ĊĠĠĠ Ġval Ġinspector State Ġ= ĠFake Inspector State ( inspection Rule . view Inspector , Ġinspection Rule . compose Inspector ) ĊĠĠĠ Ġinspector State . create Fake View Tree () ĊĊĠĠĠ Ġval Ġmodel Updated Latch Ġ= ĠReporting Count DownLatch ( 2 ) Ġ// ĠWe 'll Ġget Ġtwo Ġtree Ġlayout Ġevents Ġon Ġstart Ġfetch ĊĠĠĠ Ġinspector Rule . inspector Model . modification Listeners . add Ġ{ Ġ_, Ġ_, Ġ_ Ġ-> ĊĠĠĠĠĠ Ġmodel Updated Latch . count Down () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinspector Rule . process Notifier . fire Connected ( MO DER N _ PROCESS ) ĊĠĠĠ Ġmodel Updated Latch . await ( TIMEOUT , ĠTIME OUT _ UNIT ) ĊĠĠĠ ĠassertThat ( inspector Rule . inspector Client . capabilities ). contains None Of ( Capability . SUPPORT S _ COMP OSE , ĠCap ability . SUPPORT S _ SEM ANT ICS ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Capabilities Update With Compose Nodes () Ġ{ ĊĠĠĠ Ġval Ġinspector State Ġ= ĠFake Inspector State ( inspection Rule . view Inspector , Ġinspection Rule . compose Inspector ) ĊĠĠĠ Ġinspector State . create Fake View Tree () ĊĠĠĠ Ġinspector State . create Fake Compose Tree ( with Semantics Ġ= Ġfalse ) ĊĊĠĠĠ Ġval Ġmodel Updated Latch Ġ= ĠReporting Count DownLatch ( 2 ) Ġ// ĠWe 'll Ġget Ġtwo Ġtree Ġlayout Ġevents Ġon Ġstart Ġfetch ĊĠĠĠ Ġinspector Rule . inspector Model . modification Listeners . add Ġ{ Ġ_, Ġ_, Ġ_ Ġ-> ĊĠĠĠĠĠ Ġmodel Updated Latch . count Down () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinspector Rule . process Notifier . fire Connected ( MO DER N _ PROCESS ) ĊĠĠĠ Ġmodel Updated Latch . await ( TIMEOUT , ĠTIME OUT _ UNIT ) ĊĠĠĠ ĠassertThat ( inspector Rule . inspector Client . capabilities ). contains ( Capability . SUPPORT S _ COMP OSE ) ĊĠĠĠ ĠassertThat ( inspector Rule . inspector Client . capabilities ). does Not Contain ( Capability . SUPPORT S _ SEM ANT ICS ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Capabilities Update With Compose Nodes With Semantics () Ġ{ ĊĠĠĠ Ġval Ġinspector State Ġ= ĠFake Inspector State ( inspection Rule . view Inspector , Ġinspection Rule . compose Inspector ) ĊĠĠĠ Ġinspector State . create Fake View Tree () ĊĠĠĠ Ġinspector State . create Fake Compose Tree ( with Semantics Ġ= Ġtrue ) ĊĊĠĠĠ Ġval Ġmodel Updated Latch Ġ= ĠReporting Count DownLatch ( 2 ) Ġ// ĠWe 'll Ġget Ġtwo Ġtree Ġlayout Ġevents Ġon Ġstart Ġfetch ĊĠĠĠ Ġinspector Rule . inspector Model . modification Listeners . add Ġ{ Ġ_, Ġ_, Ġ_ Ġ-> ĊĠĠĠĠĠ Ġmodel Updated Latch . count Down () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinspector Rule . process Notifier . fire Connected ( MO DER N _ PROCESS ) ĊĠĠĠ Ġmodel Updated Latch . await ( TIMEOUT , ĠTIME OUT _ UNIT ) ĊĠĠĠ ĠassertThat ( inspector Rule . inspector Client . capabilities ). contains All Of ( Capability . SUPPORT S _ COMP OSE , ĠCap ability . SUPPORT S _ SEM ANT ICS ) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest TextView Under Compose Node () Ġ{ ĊĠĠĠ Ġval Ġinspector State Ġ= ĠFake Inspector State ( inspection Rule . view Inspector , Ġinspection Rule . compose Inspector ) ĊĠĠĠ Ġinspector State . create Fake View Tree () ĊĠĠĠ Ġinspector State . create Fake Compose Tree () ĊĠĠĠ Ġval Ġmodel Updated Latch Ġ= ĠReporting Count DownLatch ( 2 ) Ġ// ĠWe 'll Ġget Ġtwo Ġtree Ġlayout Ġevents Ġon Ġstart Ġfetch ĊĠĠĠ Ġinspector Rule . inspector Model . modification Listeners . add Ġ{ Ġ_, Ġ_, Ġ_ Ġ-> ĊĠĠĠĠĠ Ġmodel Updated Latch . count Down () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinspector Rule . process Notifier . fire Connected ( MO DER N _ PROCESS ) ĊĠĠĠ Ġmodel Updated Latch . await ( TIMEOUT , ĠTIME OUT _ UNIT ) ĊĊĠĠĠ Ġ// ĠVerify Ġthat Ġthe ĠMaterial TextView Ġfrom Ġthe Ġviews Ġwere Ġplaced Ġunder Ġthe ĠCompose View Node : Ġ" Compose Node " Ġwith Ġid Ġof Ġ- 7 ĊĠĠĠ Ġval Ġcompose Node Ġ= Ġinspector Rule . inspector Model [- 7 ] !! ĊĠĠĠ ĠassertThat ( compose Node . parent ?. qualified Name ). isEqualTo (" Android View ") ĊĠĠĠ ĠassertThat ( compose Node . qualified Name ). isEqualTo (" Compose Node ") ĊĠĠĠ ĠassertThat ( compose Node . children . single (). qualified Name ). isEqualTo (" com . google . android . material . text view . Material TextView ") ĊĊĠĠĠ Ġ// ĠAlso Ġverify Ġthat Ġthe ĠCompose View Ġdo Ġnot Ġcontain Ġthe ĠMaterial TextView Ġnor Ġthe ĠR ipple Container Ġin Ġits Ġchildren : ĊĠĠĠ Ġval Ġcompose View Ġ= Ġinspector Rule . inspector Model [ 6 ] !! ĊĠĠĠ ĠassertThat ( compose View . qualified Name ). isEqualTo (" android . view . Compose View ") ĊĠĠĠ ĠassertThat ( compose View . children . single (). qualified Name ). isEqualTo (" Surface ") ĊĠ Ġ} Ċ } Ċ