package com.sptmobile.link import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Test // [unit->REQ-DEVICE-LINK-IROH] // Pins the Kotlin side of the followNext envelope contract // (rust/link-android/src/lib.rs module doc): the closed delta/timeout/end/error // set decodes exactly, and nothing an envelope can contain crashes the reader // loop. class FollowEventTest { @Test fun `delta carries the raw delta line verbatim`() { val delta = """{"version":1,"from":3,"turns":[{"seq":4}]}""" val event = FollowEvent.decode( """{"event":"delta","delta":"{\"version\":1,\"from\":3,\"turns\":[{\"seq\":4}]}"}""" ) assertEquals(FollowEvent.Delta(delta), event) } @Test fun `timeout and end decode to their singletons`() { assertEquals(FollowEvent.Timeout, FollowEvent.decode("""{"event":"timeout"}""")) assertEquals(FollowEvent.End, FollowEvent.decode("""{"event":"end"}""")) } @Test fun `error carries the message`() { assertEquals( FollowEvent.Error("link dropped"), FollowEvent.decode("""{"event":"error","message":"link dropped"}""") ) } @Test fun `error without message still decodes`() { assertEquals( FollowEvent.Error("unknown stream error"), FollowEvent.decode("""{"event":"error"}""") ) } @Test fun `unknown event becomes Error not a crash`() { val event = FollowEvent.decode("""{"event":"upgrade-v2"}""") assertTrue(event is FollowEvent.Error) } @Test fun `malformed json becomes Error not a crash`() { assertTrue(FollowEvent.decode("not json at all") is FollowEvent.Error) assertTrue(FollowEvent.decode("""{"delta":"x"}""") is FollowEvent.Error) } @Test fun `delta envelope missing its delta field becomes Error`() { assertTrue(FollowEvent.decode("""{"event":"delta"}""") is FollowEvent.Error) } @Test fun `unknown extra keys are tolerated`() { assertEquals( FollowEvent.Timeout, FollowEvent.decode("""{"event":"timeout","extra":42}""") ) } }