/* Ċ Ġ* ĠUnless Ġexplicitly Ġstated Ġotherwise Ġall Ġfiles Ġin Ġthis Ġrepository Ġare Ġlicensed Ġunder Ġthe ĠApache ĠLicense ĠVersion Ġ 2 . 0 . Ċ Ġ* ĠThis Ġproduct Ġincludes Ġsoftware Ġdeveloped Ġat ĠDat adog Ġ( https :// www . datadog hq . com /). Ċ Ġ* ĠCopyright Ġ 2 0 1 6 - Present ĠDat adog , ĠInc . Ċ Ġ*/ Ċ Ċ package Ġcom . datadog . tools . unit Ċ Ċ import Ġjava . lang . reflect . Field Ċ import Ġjava . lang . reflect . Invocation TargetException Ċ import Ġjava . lang . reflect . Method Ċ import Ġjava . lang . reflect . Modifier Ċ import Ġjava . util . LinkedList Ċ import Ġkotlin . reflect . jvm . is Accessible Ċ Ċ /** Ċ Ġ* ĠCreates Ġan Ġinstance Ġof Ġthe Ġgiven Ġclass Ġname . Ċ Ġ* Ġ@ param ĠclassName Ġthe Ġfull Ġname Ġof Ġthe Ġclass Ġto Ġinstantiate Ċ Ġ* Ġ@ param Ġparams Ġthe Ġparameters Ġto Ġprovide Ġthe Ġconstructor Ċ Ġ* Ġ@ return Ġthe Ġcreated Ġinstance Ċ Ġ*/ Ċ @ Suppress (" Spread Operator ") Ċ fun Ġcreate Instance ( ĊĠĠĠ ĠclassName : ĠString , ĊĠĠĠ Ġvar arg Ġparams : ĠAny ? Ċ ): ĠAny Ġ{ ĊĠĠĠ Ġreturn ĠClass . forName ( className ) ĊĠĠĠĠĠĠĠ Ġ. kotlin ĊĠĠĠĠĠĠĠ Ġ. construct ors . first () ĊĠĠĠĠĠĠĠ Ġ. apply Ġ{ Ġis Accessible Ġ= Ġtrue Ġ} ĊĠĠĠĠĠĠĠ Ġ. call (* params ) Ċ } Ċ Ċ /** Ċ Ġ* ĠSets Ġa Ġstatic Ġvalue Ġon Ġthe Ġtarget Ġclass . Ċ Ġ* Ġ@ param ĠfieldName Ġthe Ġname Ġof Ġthe Ġfield Ċ Ġ* Ġ@ param Ġfield Value Ġthe Ġvalue Ġto Ġset Ċ Ġ*/ Ċ @ Suppress (" Sw allowed Exception ") Ċ fun Ġ< T , ĠR > ĠClass < T >. set Static Value ( ĊĠĠĠ ĠfieldName : ĠString , ĊĠĠĠ Ġfield Value : ĠR Ċ ) Ġ{ ĊĠĠĠ Ġval Ġfield Ġ= Ġget Declared Field ( fieldName ) ĊĊĠĠĠ Ġ// Ġmake Ġit Ġaccessible ĊĠĠĠ Ġfield . is Accessible Ġ= Ġtrue ĊĊĠĠĠ Ġset FieldValue ( null , Ġfield , Ġfield Value ) Ċ } Ċ Ċ /** Ċ Ġ* ĠGets Ġthe Ġstatic Ġvalue Ġfrom Ġthe Ġtarget Ġclass . Ċ Ġ* Ġ@ param ĠclassName Ġthe Ġfull Ġname Ġof Ġthe Ġclass Ċ Ġ* Ġ@ param ĠfieldName Ġthe Ġname Ġof Ġthe Ġfield Ċ Ġ*/ Ċ inline Ġfun Ġ< re ified ĠR > ĠgetStatic Value ( ĊĠĠĠ ĠclassName : ĠString , ĊĠĠĠ ĠfieldName : ĠString Ċ ): ĠR Ġ{ ĊĠĠĠ Ġval Ġclazz Ġ= ĠClass . forName ( className ) ĊĠĠĠ Ġval Ġfield Ġ= Ġclazz . getDeclared Field ( fieldName ) ĊĠĠĠ Ġ// Ġmake Ġit Ġaccessible ĊĠĠĠ Ġfield . is Accessible Ġ= Ġtrue ĊĊĠĠĠ Ġreturn Ġfield . get ( null ) Ġas ĠR Ċ } Ċ Ċ /** Ċ Ġ* ĠGets Ġthe Ġstatic Ġvalue Ġfrom Ġthe Ġtarget Ġclass . Ċ Ġ* Ġ@ param ĠfieldName Ġthe Ġname Ġof Ġthe Ġfield Ċ Ġ*/ Ċ inline Ġfun Ġ< re ified ĠT , Ġre ified ĠR > ĠClass < T >. get Static Value ( fieldName : ĠString ): ĠR Ġ{ ĊĊĠĠĠ Ġval Ġfield Ġ= Ġget Declared Field ( fieldName ) ĊĊĠĠĠ Ġ// Ġmake Ġit Ġaccessible ĊĠĠĠ Ġfield . is Accessible Ġ= Ġtrue ĊĊĠĠĠ Ġreturn Ġfield . get ( null ) Ġas ĠR Ċ } Ċ Ċ /** Ċ Ġ* ĠSets Ġthe Ġfield Ġvalue Ġon Ġthe Ġtarget Ġinstance . Ċ Ġ* Ġ@ param ĠfieldName Ġthe Ġname Ġof Ġthe Ġfield Ċ Ġ* Ġ@ param Ġfield Value Ġthe Ġvalue Ġof Ġthe Ġfield Ċ Ġ*/ Ċ @ Suppress (" Sw allowed Exception ") Ċ fun Ġ< T > ĠAny . set FieldValue ( ĊĠĠĠ ĠfieldName : ĠString , ĊĠĠĠ Ġfield Value : ĠT Ċ ): ĠBoolean Ġ{ ĊĠĠĠ Ġvar Ġfield : ĠField ? Ġ= Ġnull ĊĠĠĠ Ġval Ġclasses To Search Ġ= ĠLinkedList < Class <* >>() ĊĠĠĠ Ġclasses To Search . add ( this . java Class ) ĊĠĠĠ Ġval Ġclasses Se ar ched Ġ= Ġmutable Set Of < Class <* >>() ĊĊĠĠĠ Ġwhile Ġ( field Ġ== Ġnull Ġ&& Ġclasses To Search . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġto Search In Ġ= Ġclasses To Search . remove () ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfield Ġ= Ġto Search In . getDeclared Field ( fieldName ) ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠNoSuch Field Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġdo Ġnothing ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġclasses Se ar ched . add ( to Search In ) ĊĠĠĠĠĠĠĠ Ġto Search In . super class ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! classes Se ar ched . contains ( it )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclasses To Search . add ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġif Ġ( field Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ Ġset FieldValue ( this , Ġfield , Ġfield Value ) ĊĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠ Ġfalse ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠGets Ġthe Ġfield Ġvalue Ġfrom Ġthe Ġtarget Ġinstance . Ċ Ġ* Ġ@ param ĠfieldName Ġthe Ġname Ġof Ġthe Ġfield Ċ Ġ*/ Ċ inline Ġfun Ġ< re ified ĠT , ĠR Ġ: ĠAny > ĠR . getField Value ( ĊĠĠĠ ĠfieldName : ĠString , ĊĠĠĠ Ġen closing Class : ĠClass < R > Ġ= Ġthis . java Class Ċ ): ĠT Ġ{ ĊĠĠĠ Ġval Ġfield Ġ= Ġen closing Class . getDeclared Field ( fieldName ) ĊĠĠĠ Ġfield . is Accessible Ġ= Ġtrue ĊĠĠĠ Ġreturn Ġfield . get ( this ) Ġas ĠT Ċ } Ċ Ċ /** Ċ Ġ* ĠInv okes Ġa Ġmethod Ġon Ġthe Ġtarget Ġinstance . Ċ Ġ* Ġ@ param ĠmethodName Ġthe Ġname Ġof Ġthe Ġmethod Ċ Ġ* Ġ@ param Ġparams Ġthe Ġparameters Ġto Ġprovide Ġthe Ġmethod Ċ Ġ* Ġ@ return Ġthe Ġresult Ġfrom Ġthe Ġinvoked Ġmethod Ċ Ġ*/ Ċ @ Suppress (" Spread Operator ", Ġ" UN CHECK ED _ CAST ", Ġ" Too Generic Exception Ca ught ") Ċ fun Ġ< T Ġ: ĠAny > ĠT . invoke Method ( ĊĠĠĠ ĠmethodName : ĠString , ĊĠĠĠ Ġvar arg Ġparams : ĠAny ? Ċ ): ĠAny ? Ġ{ ĊĠĠĠ Ġval Ġdeclaration Params Ġ= ĠArray < Class < *> ? >( params . size ) Ġ{ ĊĠĠĠĠĠĠĠ Ġparams [ it ]?. java Class ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġmethod Ġ= Ġget Declared Method Re cursively ( methodName , Ġtrue , Ġdeclaration Params ) ĊĠĠĠ Ġval Ġwas Accessible Ġ= Ġmethod . is Accessible ĊĊĠĠĠ Ġval Ġoutput : ĠAny ? ĊĠĠĠ Ġmethod . is Accessible Ġ= Ġtrue ĊĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠ Ġoutput Ġ= Ġif Ġ( params . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmethod . invoke ( this ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmethod . invoke ( this , Ġ* params ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ġcatch Ġ( e : ĠInvocation TargetException ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthrow Ġe . cause Ġ?: Ġe ĊĠĠĠ Ġ} Ġfinally Ġ{ ĊĠĠĠĠĠĠĠ Ġmethod . is Accessible Ġ= Ġwas Accessible ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġoutput Ċ } Ċ Ċ /** Ċ Ġ* ĠInv okes Ġa Ġmethod Ġon Ġthe Ġtarget Ġinstance , Ġwhere Ġone Ġor Ġmore Ġof Ġthe Ġparameters Ċ Ġ* Ġare Ġgener ics . Ċ Ġ* Ġ@ param ĠmethodName Ġthe Ġname Ġof Ġthe Ġmethod Ċ Ġ* Ġ@ param Ġparams Ġthe Ġparameters Ġto Ġprovide Ġthe Ġmethod Ċ Ġ* Ġ@ return Ġthe Ġresult Ġfrom Ġthe Ġinvoked Ġmethod Ċ Ġ*/ Ċ @ Suppress (" Spread Operator ", Ġ" UN CHECK ED _ CAST ") Ċ fun Ġ< T Ġ: ĠAny > ĠT . invoke Generic Method ( ĊĠĠĠ ĠmethodName : ĠString , ĊĠĠĠ Ġvar arg Ġparams : ĠAny Ċ ): ĠAny ? Ġ{ ĊĠĠĠ Ġval Ġdeclaration Params Ġ= ĠArray < Class < *> ? >( params . size ) Ġ{ ĊĠĠĠĠĠĠĠ Ġparams [ it ]. java Class ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġmethod Ġ= Ġget Declared Method Re cursively ( methodName , Ġfalse , Ġdeclaration Params ) ĊĠĠĠ Ġval Ġwas Accessible Ġ= Ġmethod . is Accessible ĊĊĠĠĠ Ġval Ġoutput : ĠAny ? ĊĠĠĠ Ġmethod . is Accessible Ġ= Ġtrue ĊĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠ Ġoutput Ġ= Ġif Ġ( params . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmethod . invoke ( this ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmethod . invoke ( this , Ġ* params ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ġcatch Ġ( e : ĠInvocation TargetException ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthrow Ġe . cause Ġ?: Ġe ĊĠĠĠ Ġ} Ġfinally Ġ{ ĊĠĠĠĠĠĠĠ Ġmethod . is Accessible Ġ= Ġwas Accessible ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġoutput Ċ } Ċ Ċ @ Suppress (" Too Generic Exception Ca ught ", Ġ" Sw allowed Exception ", Ġ" Spread Operator ", Ġ" Complex Method ") Ċ private Ġfun Ġ< T Ġ: ĠAny > ĠT . getDeclared Method Re cursively ( ĊĠĠĠ ĠmethodName : ĠString , ĊĠĠĠ Ġmatching Params : ĠBoolean , ĊĠĠĠ Ġdeclaration Params : ĠArray < Class < *> ?> Ċ ): ĠMethod Ġ{ ĊĠĠĠ Ġval Ġclasses To Search Ġ= Ġmutable ListOf < Class < *> >( this . java Class ) ĊĠĠĠ Ġval Ġclasses Se ar ched Ġ= Ġmutable ListOf < Class <* >>() ĊĠĠĠ Ġvar Ġmethod : ĠMethod ? ĊĠĠĠ Ġdo Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġlooking In Class Ġ= Ġclasses To Search . remove At ( 0 ) ĊĠĠĠĠĠĠĠ Ġclasses Se ar ched . add ( looking In Class ) ĊĠĠĠĠĠĠĠ Ġmethod Ġ= Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( matching Params ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlooking In Class . getDeclared Method ( methodName , Ġ* declaration Params ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlooking In Class . declared Methods . first OrNull Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . name Ġ== ĠmethodName Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . parameter Types . size Ġ== Ġdeclaration Params . size ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġsuperclass Ġ= Ġlooking In Class . super class ĊĠĠĠĠĠĠĠ Ġif Ġ( super class Ġ!= Ġnull Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ! classes To Search . contains ( super class ) Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ! classes Se ar ched . contains ( super class ) ĊĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclasses To Search . add ( super class ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġlooking In Class . interfaces . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! classes To Search . contains ( it ) Ġ&& Ġ! classes Se ar ched . contains ( it )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclasses To Search . add ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ġwhile Ġ( method Ġ== Ġnull Ġ&& Ġclasses To Search . isNotEmpty ()) ĊĊĠĠĠ ĠcheckNotNull ( method ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ" Unable Ġto Ġaccess Ġmethod Ġ$ methodName Ġon Ġ${ java Class . canonical Name }" ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġmethod Ċ } Ċ Ċ @ SuppressWarnings (" Print StackTrace ") Ċ private Ġfun Ġ< R > Ġset FieldValue ( instance : ĠAny ?, Ġfield : ĠField , Ġfield Value : ĠR ): ĠBoolean Ġ{ ĊĠĠĠ Ġfield . is Accessible Ġ= Ġtrue ĊĠĠĠ Ġ// ĠMake Ġit Ġnon Ġfinal ĊĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġaccess Field Ġ= Ġresolve Access Field () ĊĠĠĠĠĠĠĠ Ġaccess Field . is Accessible Ġ= Ġtrue ĊĠĠĠĠĠĠĠ Ġaccess Field . setInt ( field , Ġfield . modifiers Ġand ĠModifier . FINAL . inv ()) ĊĠĠĠ Ġ} Ġcatch Ġ( e : ĠNoSuch Field Exception ) Ġ{ ĊĠĠĠĠĠĠĠ Ġe . printStackTrace () ĊĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠ Ġ} ĊĠĠĠ Ġfield . set ( instance , Ġfield Value ) ĊĠĠĠ Ġreturn Ġtrue Ċ } Ċ Ċ @ SuppressWarnings (" Sw allowed Exception ") Ċ private Ġfun Ġresolve Access Field (): ĠField Ġ{ ĊĠĠĠ Ġ// ĠAndroid ĠJVM Ġdoes Ġnot Ġuse Ġthe ĠJDK Ġsources Ġfor Ġreflection Ġtherefore Ġthe Ġproperty Ġaccess Ġtype ĊĠĠĠ Ġ// Ġfield Ġis Ġnamed Ġ` access Flags ` Ġinstead Ġof Ġ` modifiers ` Ġas Ġin Ġa Ġdefault ĠJVM ĊĠĠĠ Ġ// ĠBecause Ġthese Ġmethods Ġare Ġbeing Ġshared Ġbetween ĠJ Unit Ġand ĠAndroid JUnit Ġruntime s Ġwe Ġwill ĊĠĠĠ Ġ// Ġhave Ġto Ġsupport Ġboth Ġimplementations . ĊĠĠĠ Ġreturn Ġtry Ġ{ ĊĠĠĠĠĠĠĠ ĠField :: class . java . getDeclared Field (" modifiers ") ĊĠĠĠ Ġ} Ġcatch Ġ( e : ĠNoSuch Field Exception ) Ġ{ ĊĠĠĠĠĠĠĠ ĠField :: class . java . getDeclared Field (" access Flags ") ĊĠĠĠ Ġ} Ċ } Ċ