package Ġraw http . core . server Ċ Ċ import Ġio . kot lint est . matchers . between Ċ import Ġio . kot lint est . matchers . shouldBe Ċ import Ġio . kot lint est . matchers . should Equal Ċ import Ġio . kot lint est . matchers . should Have Ċ import Ġio . kot lint est . specs . String Spec Ċ import Ġraw http . core . Raw HttpHeaders Ċ import Ġraw http . core . valid Date Header Ċ import Ġjava . lang . Thread . sleep Ċ import Ġjava . time . Duration Ċ import Ġjava . util . concurrent . Concurrent HashMap Ċ import Ġjava . util . concurrent . Count DownLatch Ċ import Ġjava . util . concurrent . TimeUnit Ċ import Ġjava . util . concurrent . atomic . Atomic Integer Ċ import Ġjava . util . function . Supplier Ċ Ċ class ĠDate Header Provider Tests Ġ: ĠString Spec ({ ĊĊĠĠĠ Ġ" Should Ġbe Ġable Ġto Ġget Ġa Ġheader Ġonce " Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġdate Header Container Ġ= ĠDate Header Provider ( Duration . of Millis ( 1 0 0 )). get () ĊĠĠĠĠĠĠĠ Ġdate Header Container . as Map (). size ĠshouldBe Ġ 1 ĊĠĠĠĠĠĠĠ Ġdate Header Container Ġshould Have Ġvalid Date Header () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ" Should Ġcache Ġthe ĠDate ĠHeader Ġfor Ġthe Ġrequested ĠDuration " Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcreate Date Header Counter Ġ= ĠAtomicInteger () ĊĠĠĠĠĠĠĠ Ġval Ġdate Header Mock Ġ= ĠSupplier < Raw HttpHeaders > Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcreate Date Header Counter . increment AndGet () ĊĠĠĠĠĠĠĠĠĠĠĠ ĠRaw HttpHeaders . newBuilder (). with (" Date ", ĠThread . currentThread (). id . toString ()). build () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġcache Duration Millis Ġ= Ġ 4 0 L ĊĠĠĠĠĠĠĠ Ġval Ġthread Count Ġ= Ġ 1 0 ĊĠĠĠĠĠĠĠ Ġval Ġrepeat Runs Per Thread Ġ= Ġ 4 ĊĠĠĠĠĠĠĠ Ġval Ġsleep Per Run Ġ= Ġ 2 5 L ĊĊĠĠĠĠĠĠĠ Ġval Ġdate Header Provider Ġ= ĠDate Header Provider ( Duration . of Millis ( cache Duration Millis ), Ġdate Header Mock ) ĊĊĠĠĠĠĠĠĠ Ġval Ġdate Header Values Ġ= ĠConcurrent HashMap . new Key Set < String >() ĊĠĠĠĠĠĠĠ Ġval Ġthread Ids Ġ= Ġmutable Set Of < String >() ĊĊĠĠĠĠĠĠĠ Ġval Ġl atch Ġ= ĠCount DownLatch ( thread Count ) ĊĊĠĠĠĠĠĠĠ Ġ// ĠRun Ġm ĠThread s , Ġand Ġon Ġeach ĠThread , Ġget Ġthe ĠDate Ġheader Ġn Ġtimes , Ġsleep ing Ġt Ġms Ġbetween Ġeach Ġcall ĊĠĠĠĠĠĠĠ Ġfor Ġ( t Ġin Ġ 0 Ġuntil Ġthread Count ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠThread Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( r Ġin Ġ 0 Ġuntil Ġrepeat Runs Per Thread ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( r Ġ> Ġ 0 ) Ġsleep ( sleep Per Run ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdate Header Values Ġ+= Ġdate Header Provider . get ()[" Date "] !!. first () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġl atch . count Down () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. apply Ġ{ Ġthread Ids Ġ+= Ġid . toString () Ġ}. start () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġl atch . await ( 5 0 0 , ĠTimeUnit . MILLISECONDS ) ĠshouldBe Ġtrue ĊĊĠĠĠĠĠĠĠ Ġ// Ġas Ġwe Ġset Ġthe ĠDate Ġvalues Ġto Ġeach ĠThread ĠID ĊĠĠĠĠĠĠĠ Ġdate Header Values Ġshould Equal Ġthread Ids ĊĊĠĠĠĠĠĠĠ Ġ// Ġthe Ġtest Ġruns Ġfor Ġat Ġleast Ġtotal Time Ġ= Ġ( repeat Runs Per Thread Ġ* Ġsleep Per Run ) Ġms . ĊĠĠĠĠĠĠĠ Ġ// Ġso Ġthe Ġnumber Ġof Ġtimes Ġthe Ġfactory Ġmethod Ġshould Ġbe Ġcalled Ġis : ĊĠĠĠĠĠĠĠ Ġ// Ġexpected Factory Calls Ġ= Ġthread Count Ġ* Ġ( total Time Ġ/ Ġcache Duration Millis ) ĊĠĠĠĠĠĠĠ Ġval Ġtotal Time Ġ= Ġrepeat Runs Per Thread Ġ* Ġsleep Per Run ĊĠĠĠĠĠĠĠ Ġval Ġexpected Factory Calls Ġ= Ġthread Count Ġ* Ġ( total Time Ġ/ Ġcache Duration Millis ) ĊĊĠĠĠĠĠĠĠ Ġ// Ġa Ġfew Ġextra Ġcalls Ġto Ġthe Ġfactory Ġmethod Ġare Ġallowed Ġbecause Ġwe Ġdon 't Ġsynchronize ĊĠĠĠĠĠĠĠ Ġcreate Date Header Counter . get () ĠshouldBe Ġbetween ( expected Factory Calls . toInt (), Ġexpected Factory Calls . toInt () Ġ+ Ġ 5 ) ĊĠĠĠ Ġ} Ċ Ċ }) Ċ