package Ġrun . smt . k test . json . matcher . api Ċ Ċ import Ġcom . fasterxml . jackson . databind . JsonNode Ċ import Ġcom . fasterxml . jackson . databind . node .* Ċ import Ġrun . smt . k test . util . collection .* Ċ import Ġrun . smt . k test . json . matcher . api . Comparison Mismatch .* Ċ Ċ private Ġtype alias ĠFailure Ġ= Ġ( JsonNode ?, ĠJsonNode ?, ĠComparison Path ) Ġ-> ĠComparison Mismatch Ċ Ċ class ĠJson Comparator Ġinternal Ġconstructor ( private Ġval Ġarray Comparison Mode : ĠArray Comparison Mode , Ġprivate Ġval Ġstrict Null Checking : ĠBoolean Ġ= Ġfalse , Ġprivate Ġval Ġstrict Object Fields : ĠBoolean Ġ= Ġtrue , Ġprivate Ġval Ġfield Difference Threshold : ĠInt Ġ= Ġ 5 ) Ġ{ ĊĊĠĠĠ Ġfun Ġdiff ( expected : ĠJsonNode , Ġactual : ĠJsonNode ): ĠList < Comparison Mismatch > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġdiff Ġ= Ġmutable ListOf < Comparison Mismatch >() ĊĠĠĠĠĠĠĠ Ġdiff ( expected , Ġactual , ĠComparison Path (), Ġdiff ) ĊĠĠĠĠĠĠĠ Ġreturn Ġdiff . toList () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġdiff ( expected : ĠJsonNode ?, Ġactual : ĠJsonNode ?, Ġpath : ĠComparison Path , Ġfailed : ĠMutable List < Comparison Mismatch >) Ġ{ ĊĠĠĠĠĠĠĠ Ġfun Ġfail ( failure : ĠFailure ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfailed Ġ+= Ġfailure ( expected , Ġactual , Ġpath ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġassert ( condition : ĠBoolean , Ġfailure : ĠFailure ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! condition ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfail ( failure ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis Null Json ( actual ) Ġ|| Ġis Null Json ( expected ) Ġ-> Ġcompare Null Nodes ( actual , Ġexpected , Ġpath , Ġfailed ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġactual Ġ== Ġnull Ġ|| Ġexpected Ġ== Ġnull Ġ-> Ġ{ Ġ/* Ġmake Ġkotlin Ġhappy Ġ*/ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġactual . nodeType Ġ!= Ġexpected . nodeType Ġ-> Ġfail ( Comparison Mismatch :: Type Mismatch ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġwhen Ġ( actual . nodeType ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠJson NodeType . ARRAY Ġ-> Ġcompare Json Arrays ( expected Ġas ĠArray Node , Ġactual Ġas ĠArray Node , Ġpath , Ġfailed ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠJson NodeType . OBJECT Ġ-> Ġcompare Json Objects ( expected Ġas ĠObject Node , Ġactual Ġas ĠObject Node , Ġpath , Ġfailed ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠJson NodeType . BOOLEAN Ġ-> Ġassert ( expected . boolean Value () Ġ== Ġactual . boolean Value (), ĠComparison Mismatch :: Boolean Mismatch ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠJson NodeType . NUMBER Ġ-> Ġassert ( expected . number Value () Ġ== Ġactual . number Value (), ĠComparison Mismatch :: Numeric Mismatch ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġassert ( expected Ġ== Ġactual , ĠComparison Mismatch :: Value Mismatch ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcompare Null Nodes ( actual : ĠJsonNode ?, Ġexpected : ĠJsonNode ?, Ġpath : ĠComparison Path , Ġfailed : ĠMutable List < Comparison Mismatch >) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġa Ġ= Ġactual Ġ?: ĠMissing Node . getInstance () ĊĠĠĠĠĠĠĠ Ġval Ġe Ġ= Ġexpected Ġ?: ĠMissing Node . getInstance () ĊĊĠĠĠĠĠĠĠ Ġfun Ġfail ( failure : Ġ( JsonNode ?, ĠJsonNode ?, ĠComparison Path ) Ġ-> ĠComparison Mismatch ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfailed Ġ+= Ġfailure ( expected , Ġactual , Ġpath ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġstrict Only ( failure : Ġ( JsonNode ?, ĠJsonNode ?, ĠComparison Path ) Ġ-> ĠComparison Mismatch ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( strict Null Checking Ġ&& Ġa . nodeType Ġ!= Ġe . nodeType ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfail ( failure ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġe . nodeType Ġ== Ġa . nodeType Ġ-> Ġ{} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġe . nodeType Ġ== ĠJson NodeType . NULL Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( a . nodeType ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠJson NodeType . MISSING Ġ-> Ġstrict Only ( Comparison Mismatch :: Expected Null ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġfail ( Comparison Mismatch :: Expected Null ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġe . nodeType Ġ== ĠJson NodeType . MISSING Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( a . nodeType ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠJson NodeType . NULL Ġ-> Ġstrict Only ( Comparison Mismatch :: Unexpected Value ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġfail ( Comparison Mismatch :: Unexpected Value ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġfail ( Comparison Mismatch :: Missing Value ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġis Null Json ( v : ĠJsonNode ?): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġv Ġ== Ġnull Ġ|| Ġv Ġis ĠNull Node Ġ|| Ġv Ġis ĠMissing Node ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcompare Json Objects ( expected : ĠObject Node , Ġactual : ĠObject Node , Ġpath : ĠComparison Path , Ġfailed : ĠMutable List < Comparison Mismatch >) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġval Ġexpected Field Names Ġ= Ġexpected . field Names (). as Sequence (). sorted (). to Mutable List () ĊĠĠĠĠĠĠĠ Ġval Ġactual Field Names Ġ= Ġactual . field Names (). as Sequence (). sorted (). to Mutable List () ĊĊĠĠĠĠĠĠĠ Ġif Ġ( expected Field Names Ġ!= Ġactual Field Names ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġextra Fields Ġ= Ġactual Field Names Ġ- Ġexpected Field Names ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmissing Fields Ġ= Ġexpected Field Names Ġ- Ġactual Field Names ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(( extra Fields . isNotEmpty () Ġ&& Ġstrict Object Fields ) Ġ|| Ġ( missing Fields . isNotEmpty () Ġ&& Ġstrict Null Checking )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfailed Ġ+= ĠStructural Mismatch ( extra Fields , Ġmissing Fields , Ġexpected , Ġactual , Ġpath ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( strict Object Fields Ġ&& Ġextra Fields . size Ġ> Ġfield Difference Threshold ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( strict Null Checking Ġ&& Ġmissing Fields . size Ġ> Ġfield Difference Threshold ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( strict Null Checking Ġ&& Ġstrict Object Fields Ġ&& Ġexpected Field Names . size Ġ+ Ġmissing Fields . size Ġ> Ġfield Difference Threshold ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġextra Fields . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġactual Field Names . remove ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmissing Fields . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexpected Field Names . remove ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġactual Field Names . as Sequence () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. sorted () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. zip ( expected Field Names . as Sequence (). sorted ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. forEach Ġ{ Ġ( actual FieldName , Ġexpected FieldName ) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdiff ( expected . get ( expected FieldName ), Ġactual . get ( actual FieldName ), Ġpath Ġ+ Ġactual FieldName , Ġfailed ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġ< T > Ġsort ( toBe Sorted : ĠIterable < Pair < Int , ĠT >> ): ĠIterable < Pair < Int , ĠT >> Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( array Comparison Mode Ġ== ĠArray Comparison Mode . STRICT ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġto Be Sorted ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġto Be Sorted . as Sequence (). sorted By Ġ{ Ġit . second . toString () Ġ}. as Iterable () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcompare Json Arrays ( expected : ĠArray Node , Ġactual : ĠArray Node , Ġpath : ĠComparison Path , Ġfailed : ĠMutable List < Comparison Mismatch >) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( actual . size () Ġ!= Ġexpected . size ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfailed Ġ+= ĠArray Size Mismatch ( expected . size (), Ġactual . size (), Ġexpected , Ġactual , Ġpath ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( array Comparison Mode Ġ!= ĠArray Comparison Mode . PER MUT ATION _ BASE D ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġwhen Ġ( array Comparison Mode ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠArray Comparison Mode . PER MUT ATION _ BASE D Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpadded Actual Ġ= Ġactual . toList (). pad To ( expected . size (), ĠMissing Node . getInstance ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpadded Expected Ġ= Ġexpected . toList (). pad To ( actual . size (), ĠMissing Node . getInstance ()) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmis matches Ġ= Ġpadded Actual . as Sequence () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. zip With Index () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. per mutations () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. cross Product ( padded Expected . as Sequence (). zip With Index (). per mutations ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġ( actual Per mutations , Ġexpected Per mutations ) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmutable ListOf < Comparison Mismatch >(). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġactual Per mutations . zip ( expected Per mutations ). forEach Ġ{ Ġ( a , Ġe ) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Path Ġ= Ġpath ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. append Expected ( e . first . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. append Actual ( a . first . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdiff ( e . second , Ġa . second , Ġnew Path , Ġthis ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. min By Ġ{ Ġit . size Ġ} Ġ?: Ġempty List < Comparison Mismatch >() ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfailed Ġ+= Ġmis matches ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsort ( actual . zip With Index ()). as Sequence () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. zip ( sort ( expected . zip With Index ()). as Sequence ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. forEach Ġ{ Ġ( actual , Ġexpected ) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Path Ġ= Ġpath ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. append Actual ( actual . first . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. append Expected ( expected . first . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdiff ( expected . second , Ġactual . second , Ġnew Path , Ġfailed ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ