Skip to content

Commit 943060f

Browse files
committed
La til initielt rammeverk for utvidete tester av bekreftelse
1 parent 33ed8e4 commit 943060f

File tree

5 files changed

+397
-1
lines changed

5 files changed

+397
-1
lines changed

apps/bekreftelse-tjeneste/src/test/kotlin/no/nav/paw/bekreftelsetjeneste/ApplicationTestContext.kt

+18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package no.nav.paw.bekreftelsetjeneste
22

3+
import arrow.atomic.update
34
import io.confluent.kafka.schemaregistry.testutil.MockSchemaRegistry
45
import io.confluent.kafka.serializers.KafkaAvroSerializerConfig
56
import io.confluent.kafka.streams.serdes.avro.SpecificAvroSerde
@@ -32,13 +33,17 @@ import org.apache.kafka.streams.TopologyTestDriver
3233
import org.apache.kafka.streams.state.Stores
3334
import org.slf4j.Logger
3435
import org.slf4j.LoggerFactory
36+
import java.time.Duration
37+
import java.time.Duration.between
3538
import java.time.Instant
3639
import java.util.*
40+
import java.util.concurrent.atomic.AtomicReference
3741

3842
class ApplicationTestContext(
3943
initialWallClockTime: Instant = Instant.now(),
4044
val bekreftelseKonfigurasjon: BekreftelseKonfigurasjon = loadNaisOrLocalConfiguration<BekreftelseKonfigurasjon>(BEKREFTELSE_CONFIG_FILE_NAME)
4145
) {
46+
val wallclock = AtomicReference(initialWallClockTime)
4247
val bekreftelsePaaVegneAvTopicSerde: Serde<PaaVegneAv> = opprettSerde()
4348
val bekreftelseSerde: Serde<Bekreftelse> = opprettSerde()
4449
val periodeTopicSerde: Serde<Periode> = opprettSerde()
@@ -55,6 +60,19 @@ class ApplicationTestContext(
5560

5661
val logger: Logger = LoggerFactory.getLogger(ApplicationTestContext::class.java)
5762

63+
fun tidspunkt(): String = wallclock.get().prettyPrint
64+
65+
fun still_klokken_frem_til(tidspunkt: Instant) {
66+
val duration = between(wallclock.get(), tidspunkt)
67+
require(duration >= Duration.ZERO) { "Tidspunkt kan ikke være i fortiden" }
68+
still_klokken_frem(duration)
69+
}
70+
71+
fun still_klokken_frem(duration: Duration) {
72+
wallclock.update { it.plus(duration) }
73+
testDriver.advanceWallClockTime(duration)
74+
}
75+
5876
val topology = StreamsBuilder()
5977
.addStateStore(
6078
Stores.keyValueStoreBuilder(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package no.nav.paw.bekreftelsetjeneste
2+
3+
import io.kotest.core.spec.style.FreeSpec
4+
import no.nav.paw.arbeidssoekerregisteret.testdata.KafkaKeyContext
5+
import no.nav.paw.arbeidssoekerregisteret.testdata.mainavro.metadata
6+
import no.nav.paw.arbeidssoekerregisteret.testdata.mainavro.periode
7+
8+
class BekreftelseHappyPathCase : FreeSpec({
9+
val identietsnummer = "12345678901"
10+
val periodeStartet = "05.02.2025 15:26".timestamp //Første onsdag i februar 2025
11+
"Test $periodeStartet" - {
12+
with(
13+
setOppTest(
14+
datoOgKlokkeslettVedStart = periodeStartet,
15+
bekreftelseIntervall = 14.dager,
16+
tilgjengeligOffset = 3.dager,
17+
innleveringsfrist = 7.dager
18+
)
19+
) {
20+
with(KafkaKeyContext(this.kafkaKeysClient)) {
21+
val periode = periode(
22+
identitetsnummer = identietsnummer,
23+
startetMetadata = metadata(tidspunkt = periodeStartet)
24+
)
25+
"En arbeidssøkerperiode starter ${tidspunkt()}" {
26+
periodeTopic.pipeInput(periode.key, periode.value)
27+
}
28+
"[${tidspunkt()}]: Ingen bekreftelser skal være publisert" {
29+
ingen_bekreftelser_skal_være_publisert()
30+
}
31+
still_klokken_frem_til("20.02.2025 16:00".timestamp)
32+
"[${tidspunkt()}]: Ingen bekreftelser skal være publisert" {
33+
ingen_bekreftelser_skal_være_publisert()
34+
}
35+
still_klokken_frem_til("21.02.2025 02:00".timestamp)
36+
val gjelderTil = "24.02.2025 00:00".timestamp
37+
"[${tidspunkt()}]: En bekreftelse skal være tilgjengelig, gjelder: fra ${periodeStartet.prettyPrint} til ${gjelderTil.prettyPrint}" {
38+
bekreftelse_er_tilgjengelig(
39+
fra = periodeStartet,
40+
til = gjelderTil
41+
)
42+
}
43+
"[${tidspunkt()}]: Ingen andre bekreftelser skal være publisert" {
44+
ingen_flere_hendelser()
45+
}
46+
still_klokken_frem_til("24.02.2025 04:00".timestamp)
47+
val fristUtloept = "24.02.2025 00:00".timestamp
48+
"[${tidspunkt()}]: Første frist for levering passerte ${fristUtloept.prettyPrint}" {
49+
bekreftelse_venter_på_svar(fristUtloept)
50+
}
51+
still_klokken_frem_til("27.02.2025 17:00".timestamp)
52+
val gjenstaaendeTid = 83.timer
53+
"[${tidspunkt()}]: Intern versel hendelse skal være publisert, $gjenstaaendeTid" {
54+
internt_varsel_hendelse_skal_være_publisert(gjenstaaendeTid)
55+
}
56+
"[${tidspunkt()}]: Ingen flere hendelser skal være publisert" {
57+
ingen_flere_hendelser()
58+
}
59+
val sisteFrist = "03.03.2025 00:00".timestamp
60+
still_klokken_frem_til("03.03.2025 05:00".timestamp)
61+
"[${tidspunkt()}]: Siste frist for levering passerte ${sisteFrist.prettyPrint}" {
62+
bekreftelse_siste_frist_utloept(sisteFrist)
63+
}
64+
}
65+
}
66+
}
67+
})
68+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package no.nav.paw.bekreftelsetjeneste
2+
3+
import no.nav.paw.arbeidssoekerregisteret.testdata.KafkaKeyContext
4+
import no.nav.paw.arbeidssoekerregisteret.testdata.ValueWithKafkaKeyData
5+
import no.nav.paw.arbeidssoekerregisteret.testdata.bekreftelse.bekreftelseMelding
6+
import no.nav.paw.arbeidssoekerregisteret.testdata.bekreftelse.startPaaVegneAv
7+
import no.nav.paw.arbeidssoekerregisteret.testdata.bekreftelse.stoppPaaVegneAv
8+
import no.nav.paw.arbeidssoekerregisteret.testdata.mainavro.metadata
9+
import no.nav.paw.arbeidssoekerregisteret.testdata.mainavro.periode
10+
import no.nav.paw.arbeidssokerregisteret.api.v1.Periode
11+
import no.nav.paw.bekreftelse.internehendelser.BekreftelseHendelse
12+
import no.nav.paw.bekreftelse.internehendelser.BekreftelseMeldingMottatt
13+
import no.nav.paw.bekreftelse.internehendelser.BekreftelseTilgjengelig
14+
import no.nav.paw.bekreftelse.internehendelser.RegisterGracePeriodeUtloept
15+
import no.nav.paw.bekreftelse.melding.v1.Bekreftelse
16+
import no.nav.paw.bekreftelse.melding.v1.vo.Bekreftelsesloesning
17+
import no.nav.paw.bekreftelse.melding.v1.vo.Svar
18+
import no.nav.paw.bekreftelse.paavegneav.v1.PaaVegneAv
19+
import java.time.Duration
20+
import java.time.Instant
21+
import java.util.*
22+
23+
fun main() {
24+
val identietsnummer = "12345678901"
25+
val periodeStartet = "05.02.2025 15:26".timestamp //Første onsdag i februar 2025
26+
val interval = 14.dager
27+
val graceperiode = 7.dager
28+
val tilgjengeligOffset = 3.dager
29+
with(
30+
setOppTest(
31+
datoOgKlokkeslettVedStart = periodeStartet,
32+
bekreftelseIntervall =interval,
33+
tilgjengeligOffset = tilgjengeligOffset,
34+
innleveringsfrist = graceperiode
35+
)
36+
) {
37+
val opploesning = Duration.ofSeconds(60)
38+
val stoppTid = "01.06.2025 00:00".timestamp
39+
with(KafkaKeyContext(this.kafkaKeysClient)) {
40+
val periode = periode(
41+
identitetsnummer = identietsnummer,
42+
startetMetadata = metadata(tidspunkt = periodeStartet)
43+
)
44+
val eksterneHendelser: List<Pair<Instant, ValueWithKafkaKeyData<*>>> = listOf(
45+
"05.02.2025 15:26".timestamp to periode,
46+
"22.02.2025 13:34".timestamp to ValueWithKafkaKeyData(periode.id, periode.key, bekreftelseMelding(
47+
periodeId = periode.value.id,
48+
gjelderFra = periodeStartet,
49+
gjelderTil = "24.02.2025 00:00".timestamp,
50+
harJobbetIDennePerioden = true,
51+
vilFortsetteSomArbeidssoeker = true
52+
)),
53+
"12.03.2025 09:12".timestamp to ValueWithKafkaKeyData(periode.id, periode.key, startPaaVegneAv(
54+
periodeId = periode.value.id,
55+
bekreftelsesloesning = no.nav.paw.bekreftelse.paavegneav.v1.vo.Bekreftelsesloesning.DAGPENGER,
56+
grace = Duration.ofDays(7),
57+
interval = Duration.ofDays(14)
58+
)),
59+
"29.03.2025 12:01".timestamp to ValueWithKafkaKeyData(periode.id, periode.key, bekreftelseMelding(
60+
periodeId = periode.value.id,
61+
gjelderFra = "10.03.2025 00:00".timestamp,
62+
gjelderTil = "31.03.2025 00:00".timestamp,
63+
harJobbetIDennePerioden = true,
64+
vilFortsetteSomArbeidssoeker = true,
65+
bekreftelsesloesning = Bekreftelsesloesning.DAGPENGER
66+
)),
67+
"21.04.2025 05:00".timestamp to ValueWithKafkaKeyData(periode.id, periode.key, stoppPaaVegneAv(
68+
periodeId = periode.value.id,
69+
bekreftelsesloesning = no.nav.paw.bekreftelse.paavegneav.v1.vo.Bekreftelsesloesning.DAGPENGER
70+
))
71+
)
72+
val hendelser = run(eksterneHendelser, stoppTid, opploesning)
73+
println("${periodeStartet.prettyPrint} Arbeidssøkerperiode startet")
74+
println(
75+
hendelser
76+
.toList().joinToString("\n") { (tidspunkt, hendelse) ->
77+
"${tidspunkt.prettyPrint}: hendelse: ${hendelse.prettyPrint()}"
78+
})
79+
}
80+
}
81+
}
82+
83+
fun ApplicationTestContext.run(
84+
input: List<Pair<Instant, ValueWithKafkaKeyData<*>>>,
85+
stoppTid: Instant,
86+
opploesning: Duration
87+
): List<Pair<Instant, BekreftelseHendelse>> {
88+
val perioder = input.map { it.second.value }.filterIsInstance<Periode>()
89+
val inputStream = input.iterator()
90+
var neste = if (inputStream.hasNext()) inputStream.next() else null
91+
var counter = 0
92+
val hendelser: MutableList<Pair<Instant, BekreftelseHendelse>> = mutableListOf()
93+
val ventendeBekreftelser = mutableListOf<BekreftelseTilgjengelig>()
94+
while (wallclock.get() < stoppTid) {
95+
val immutableNeste = neste
96+
if (immutableNeste != null && wallclock.get() >= immutableNeste.first) {
97+
when (val asTypedValue = immutableNeste.second.value) {
98+
null -> {}
99+
is Periode -> periodeTopic.pipeInput(immutableNeste.second.key, asTypedValue)
100+
is Bekreftelse -> {
101+
if (ventendeBekreftelser.isNotEmpty()) {
102+
with(ventendeBekreftelser.removeFirst()) {
103+
bekreftelseTopic.pipeInput(
104+
immutableNeste.second.key, Bekreftelse(
105+
asTypedValue.periodeId,
106+
asTypedValue.bekreftelsesloesning,
107+
this.bekreftelseId,
108+
asTypedValue.svar
109+
)
110+
)
111+
}
112+
113+
} else {
114+
bekreftelseTopic.pipeInput(immutableNeste.second.key, asTypedValue)
115+
}
116+
}
117+
is PaaVegneAv -> bekreftelsePaaVegneAvTopic.pipeInput(immutableNeste.second.key, asTypedValue)
118+
is BekreftelseMeldingMottatt -> ventendeBekreftelser.removeIf { it.bekreftelseId == asTypedValue.bekreftelseId }
119+
else -> throw IllegalArgumentException("Ukjent type: ${asTypedValue::class.simpleName}")
120+
}
121+
neste = if (inputStream.hasNext()) inputStream.next() else null
122+
}
123+
if (!bekreftelseHendelseloggTopicOut.isEmpty) {
124+
val kv = bekreftelseHendelseloggTopicOut.readKeyValue()
125+
when (val hendelse = kv.value) {
126+
is RegisterGracePeriodeUtloept -> {
127+
perioder
128+
.first { it.id == kv.value.periodeId }
129+
.let { periode ->
130+
Periode(
131+
periode.id,
132+
periode.identitetsnummer,
133+
periode.startet,
134+
metadata(tidspunkt = wallclock.get())
135+
)
136+
}.also { periodeTopic.pipeInput(kv.key, it) }
137+
}
138+
is BekreftelseTilgjengelig -> {
139+
ventendeBekreftelser.add(hendelse)
140+
}
141+
else -> { }
142+
}
143+
hendelser.add(wallclock.get() to kv.value)
144+
}
145+
still_klokken_frem(opploesning)
146+
counter++
147+
if (counter % 100000 == 0) {
148+
println("Tidspunkt: ${wallclock.get().prettyPrint}")
149+
}
150+
}
151+
return hendelser.toList()
152+
}
153+

0 commit comments

Comments
 (0)