package Ġcom . squareup . sql de light . drivers . native . connection pool Ċ Ċ import Ġco . touch lab . test help . concurrency . Thread Operations Ċ import Ġco . touch lab . test help . concurrency . sleep Ċ import Ġcom . squareup . sql de light . Query Ċ import Ġcom . squareup . sql de light . Trans acter Impl Ċ import Ġcom . squareup . sql de light . db . Sql Cursor Ċ import Ġcom . squareup . sql de light . drivers . native . Native Sqlite Driver Ċ import Ġcom . squareup . sql de light . internal . copy On Write List Ċ import Ġkotlin . native . concurrent . Atomic Int Ċ import Ġkotlin . native . concurrent . Transfer Mode Ċ import Ġkotlin . native . concurrent . Worker Ċ import Ġkotlin . native . concurrent . freeze Ċ import Ġkotlin . test . Before Test Ċ import Ġkotlin . test . Ignore Ċ import Ġkotlin . test . Test Ċ import Ġkotlin . test . assertEquals Ċ import Ġkotlin . test . assertTrue Ċ Ċ /** Ċ Ġ* ĠTesting Ġmultiple Ġread Ġand Ġtransaction Ġpool Ġconnections . ĠThese Ġwere Ċ Ġ* Ġwritten Ġwhen Ġit Ġa Ġwas Ġa Ġsingle Ġpool , Ġso Ġthis Ġwill Ġneed Ġsome Ġrefactor . Ċ Ġ* ĠThe Ġreader Ġpool Ġis Ġmuch Ġmore Ġlikely Ġto Ġbe Ġmultiple Ġwith Ġa Ġsingle Ġtransaction Ġpool Ċ Ġ* Ġconnection , Ġwhich Ġremoves Ġa Ġlot Ġof Ġthe Ġpotential Ġconcurrency Ġissues , Ġbut Ġintroduces Ġnew Ġthings Ċ Ġ* Ġwe Ġshould Ġprobably Ġtest . Ċ Ġ*/ Ċ class ĠW al Concurrency Test Ġ: ĠBase Concurrency Test () Ġ{ ĊĠ Ġ@ Before Test ĊĠ Ġfun Ġsetup () Ġ{ ĊĠĠĠ Ġinit Driver ( DbType . Regular W al ) ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠThis Ġis Ġless Ġimportant Ġnow Ġthat Ġwe Ġhave Ġa Ġseparate Ġreader Ġpool Ġagain , Ġbut Ġwill Ġre visit . ĊĠĠ Ġ*/ ĊĠ Ġ@ Test ĊĠ Ġfun Ġwrite Not Block Read () Ġ{ ĊĠĠĠ ĠassertEquals ( count Rows (), Ġ 0 ) ĊĊĠĠĠ Ġval Ġtrans acter : ĠTrans acter Impl Ġ= Ġobject Ġ: ĠTrans acter Impl ( driver ) Ġ{} ĊĠĠĠ Ġval Ġworker Ġ= ĠWorker . start () ĊĠĠĠ Ġval Ġcounter Ġ= ĠAtomic Int ( 0 ) ĊĠĠĠ Ġval Ġtransaction Started Ġ= ĠAtomic Int ( 0 ) ĊĊĠĠĠ Ġval Ġblock Ġ= Ġ{ ĊĠĠĠĠĠ Ġtrans acter . transaction Ġ{ ĊĠĠĠĠĠĠĠ Ġinsert TestData ( TestData ( 1 L , Ġ" ar st Ġ 1 ")) ĊĠĠĠĠĠĠĠ Ġtransaction Started . increment () ĊĠĠĠĠĠĠĠ Ġsleep ( 1 5 0 0 ) ĊĠĠĠĠĠĠĠ Ġcounter . increment () ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġfuture Ġ= Ġworker . execute ( Transfer Mode . SAFE , Ġ{ Ġblock . freeze () Ġ}) Ġ{ Ġit () Ġ} ĊĊĠĠĠ Ġ// ĠWhen Ġready , Ġtransaction Ġstarted Ġbut Ġsleep ing ĊĠĠĠ ĠwaitFor Ġ{ Ġtransaction Started . value Ġ> Ġ 0 Ġ} ĊĊĠĠĠ Ġ// ĠThese Ġthree Ġshould Ġrun Ġbefore Ġtransaction Ġis Ġdone Ġ( not Ġblocking ) ĊĠĠĠ ĠassertEquals ( counter . value , Ġ 0 ) ĊĠĠĠ ĠassertEquals ( 0 L , Ġcount Rows ()) ĊĠĠĠ ĠassertEquals ( counter . value , Ġ 0 ) ĊĊĠĠĠ Ġfuture . result ĊĊĠĠĠ Ġworker . request Termination () ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠReader Ġpool Ġstress Ġtest ĊĠĠ Ġ*/ ĊĠ Ġ@ Test Ġ@ Ignore ĊĠ Ġfun Ġmany Reads () Ġ= Ġrun Concurrent Ġ{ ĊĠĠĠ Ġval Ġtrans acter : ĠTrans acter Impl Ġ= Ġobject Ġ: ĠTrans acter Impl ( driver ) Ġ{} ĊĠĠĠ Ġval Ġdata Size Ġ= Ġ 2 _ 0 0 0 ĊĠĠĠ Ġtrans acter . transaction Ġ{ ĊĠĠĠĠĠ Ġrepeat ( data Size ) Ġ{ ĊĠĠĠĠĠĠĠ Ġinsert TestData ( TestData ( it . to Long (), Ġ" Data Ġ$ it ")) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġops Ġ= ĠThread Operations Ġ{} ĊĠĠĠ Ġval Ġtotal Count Ġ= ĠAtomic Int ( 0 ) ĊĠĠĠ Ġval Ġquery Runs Ġ= Ġ 1 0 0 ĊĠĠĠ Ġrepeat ( query Runs ) Ġ{ ĊĠĠĠĠĠ Ġops . exe Ġ{ ĊĠĠĠĠĠĠĠ Ġtotal Count . add AndGet ( testData Query (). execute As List (). size ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġops . run ( 6 ) ĊĠĠĠ ĠassertEquals ( total Count . value , Ġdata Size Ġ* Ġquery Runs ) ĊĠĠĠ Ġval Ġreader Pool Ġ= Ġ( driver Ġas ĠNative Sqlite Driver ). reader Pool ĊĠĠĠ Ġ// ĠMake Ġsure Ġwe Ġactually Ġcreated Ġall Ġof Ġthe Ġconnections ĊĠĠĠ ĠassertTrue ( reader Pool . entry Count () Ġ> Ġ 1 , Ġ" Reader Ġpool Ġsize Ġ${ reader Pool . entry Count () }") ĊĠ Ġ} ĊĊĠ Ġprivate Ġval Ġmapper Ġ= Ġ{ Ġcursor : ĠSql Cursor Ġ-> ĊĠĠĠ ĠTest Data ( ĊĠĠĠĠĠ Ġcursor . getLong ( 0 ) !! , Ġcursor . getString ( 1 ) !! ĊĠĠĠ Ġ) ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun ĠtestData Query (): ĠQuery < TestData > Ġ{ ĊĠĠĠ Ġreturn Ġobject Ġ: ĠQuery < TestData >( copy On Write List (), Ġmapper ) Ġ{ ĊĠĠĠĠĠ Ġoverride Ġfun Ġexecute (): ĠSql Cursor Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġdriver . executeQuery ( 0 , Ġ" SELECT Ġ* ĠFROM Ġtest ", Ġ 0 ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġwrite Blocks Write () Ġ{ ĊĠĠĠ Ġval Ġtrans acter : ĠTrans acter Impl Ġ= Ġobject Ġ: ĠTrans acter Impl ( driver ) Ġ{} ĊĠĠĠ Ġval Ġworker Ġ= ĠWorker . start () ĊĠĠĠ Ġval Ġcounter Ġ= ĠAtomic Int ( 0 ) ĊĠĠĠ Ġval Ġtransaction Started Ġ= ĠAtomic Int ( 0 ) ĊĊĠĠĠ Ġval Ġblock Ġ= Ġ{ ĊĠĠĠĠĠ Ġtrans acter . transaction Ġ{ ĊĠĠĠĠĠĠĠ Ġinsert TestData ( TestData ( 1 L , Ġ" ar st Ġ 1 ")) ĊĠĠĠĠĠĠĠ Ġtransaction Started . increment () ĊĠĠĠĠĠĠĠ Ġsleep ( 1 5 0 0 ) ĊĠĠĠĠĠĠĠ Ġcounter . increment () ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġfuture Ġ= Ġworker . execute ( Transfer Mode . SAFE , Ġ{ Ġblock . freeze () Ġ}) Ġ{ Ġit () Ġ} ĊĊĠĠĠ Ġ// ĠTransaction Ġwith Ġwrite Ġstarted Ġbut Ġsleep ing ĊĠĠĠ ĠwaitFor Ġ{ Ġtransaction Started . value Ġ> Ġ 0 Ġ} ĊĊĠĠĠ ĠassertEquals ( counter . value , Ġ 0 ) ĊĠĠĠ Ġinsert TestData ( TestData ( 2 L , Ġ" ar st Ġ 2 ")) Ġ// ĠThis Ġwaits Ġon Ġtransaction Ġto Ġwrap Ġup ĊĠĠĠ ĠassertEquals ( counter . value , Ġ 1 ) Ġ// ĠCounter Ġwould Ġbe Ġzero Ġif Ġwrite Ġdidn 't Ġblock Ġ( see Ġabove ) ĊĊĠĠĠ Ġfuture . result ĊĊĠĠĠ Ġworker . request Termination () ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġmultiple Writes Dont TimeOut () Ġ{ ĊĠĠĠ Ġval Ġtrans acter : ĠTrans acter Impl Ġ= Ġobject Ġ: ĠTrans acter Impl ( driver ) Ġ{} ĊĠĠĠ Ġval Ġworker Ġ= ĠWorker . start () ĊĠĠĠ Ġval Ġtransaction Started Ġ= ĠAtomic Int ( 0 ) ĊĊĠĠĠ Ġval Ġblock Ġ= Ġ{ ĊĠĠĠĠĠ Ġtrans acter . transaction Ġ{ ĊĠĠĠĠĠĠĠ Ġinsert TestData ( TestData ( 1 L , Ġ" ar st Ġ 1 "), Ġdriver ) ĊĠĠĠĠĠĠĠ Ġtransaction Started . increment () ĊĠĠĠĠĠĠĠ Ġsleep ( 1 5 0 0 ) ĊĠĠĠĠĠĠĠ Ġinsert TestData ( TestData ( 5 L , Ġ" ar st Ġ 1 "), Ġdriver ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġfuture Ġ= Ġworker . execute ( Transfer Mode . SAFE , Ġ{ Ġblock . freeze () Ġ}) Ġ{ Ġit () Ġ} ĊĊĠĠĠ Ġ// ĠWhen Ġwe Ġget Ġhere , Ġfirst Ġtransaction Ġhas Ġrun Ġa Ġwrite Ġcommand , Ġand Ġis Ġsleep ing ĊĠĠĠ ĠwaitFor Ġ{ Ġtransaction Started . value Ġ> Ġ 0 Ġ} ĊĠĠĠ Ġtrans acter . transaction Ġ{ ĊĠĠĠĠĠ Ġinsert TestData ( TestData ( 2 L , Ġ" ar st Ġ 2 "), Ġdriver ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfuture . result ĊĠĠĠ Ġworker . request Termination () ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠJust Ġa Ġbunch Ġof Ġinserts Ġon Ġmultiple Ġthreads . ĠMore Ġof Ġa Ġstress Ġtest . ĊĠĠ Ġ*/ ĊĠ Ġ@ Test ĊĠ Ġfun Ġmulti Write () Ġ{ ĊĠĠĠ Ġval Ġops Ġ= ĠThread Operations Ġ{} ĊĠĠĠ Ġval Ġtimes Ġ= Ġ 1 0 _ 0 0 0 ĊĠĠĠ Ġval Ġtrans acter : ĠTrans acter Impl Ġ= Ġobject Ġ: ĠTrans acter Impl ( driver ) Ġ{} ĊĊĠĠĠ Ġrepeat ( times ) Ġ{ Ġindex Ġ-> ĊĠĠĠĠĠ Ġops . exe Ġ{ ĊĠĠĠĠĠĠĠ Ġtrans acter . transaction Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġinsert TestData ( TestData ( index . to Long (), Ġ" ar st Ġ$ index ")) ĊĊĠĠĠĠĠĠĠĠĠ Ġval Ġid 2 Ġ= Ġindex . to Long () Ġ+ Ġtimes ĊĠĠĠĠĠĠĠĠĠ Ġinsert TestData ( TestData ( id 2 , Ġ" ar st Ġ$ id 2 ")) ĊĊĠĠĠĠĠĠĠĠĠ Ġval Ġid 3 Ġ= Ġindex . to Long () Ġ+ Ġtimes Ġ+ Ġtimes ĊĠĠĠĠĠĠĠĠĠ Ġinsert TestData ( TestData ( id 3 , Ġ" ar st Ġ$ id 3 ")) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġops . run ( 1 0 ) ĊĊĠĠĠ ĠassertEquals ( count Rows (), Ġtimes . to Long () Ġ* Ġ 3 ) ĊĠ Ġ} Ċ } Ċ