Include payload content type in wire frame
[dcaegen2/collectors/hv-ves.git] / hv-collector-domain / src / test / kotlin / org / onap / dcae / collectors / veshv / domain / WireFrameCodecsTest.kt
1 /*
2  * ============LICENSE_START=======================================================
3  * dcaegen2-collectors-veshv
4  * ================================================================================
5  * Copyright (C) 2018 NOKIA
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20 package org.onap.dcae.collectors.veshv.domain
21
22 import io.netty.buffer.Unpooled
23 import io.netty.buffer.UnpooledByteBufAllocator
24 import org.assertj.core.api.Assertions.assertThat
25 import org.assertj.core.api.Assertions.assertThatExceptionOfType
26 import org.jetbrains.spek.api.Spek
27 import org.jetbrains.spek.api.dsl.describe
28 import org.jetbrains.spek.api.dsl.given
29 import org.jetbrains.spek.api.dsl.it
30 import org.onap.dcae.collectors.veshv.domain.exceptions.InvalidWireFrameMarkerException
31 import org.onap.dcae.collectors.veshv.domain.exceptions.MissingWireFrameBytesException
32 import java.nio.charset.Charset
33
34 /**
35  * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
36  * @since June 2018
37  */
38 object WireFrameCodecsTest : Spek({
39     val payloadAsString = "coffeebabe"
40     val encoder = WireFrameEncoder(UnpooledByteBufAllocator.DEFAULT)
41     val decoder = WireFrameDecoder()
42
43     fun createSampleFrame() =
44             WireFrame(payloadAsString.toByteArray(Charset.defaultCharset()))
45
46     fun encodeSampleFrame() =
47             createSampleFrame().let {
48                 encoder.encode(it)
49             }
50
51     describe("Wire Frame invariants") {
52
53         given("input with unsupported version") {
54             val input = WireFrame(
55                     payload = ByteData.EMPTY,
56                     version = 100,
57                     payloadTypeRaw = PayloadContentType.GOOGLE_PROTOCOL_BUFFER.hexValue,
58                     payloadSize = 0)
59
60             it("should fail validation") {
61                 assertThat(input.isValid()).isFalse()
62             }
63         }
64
65         given("input with unsupported payload type") {
66             val input = WireFrame(
67                     payload = ByteData.EMPTY,
68                     version = 1,
69                     payloadTypeRaw = 0x69,
70                     payloadSize = 0)
71
72             it("should fail validation") {
73                 assertThat(input.isValid()).isFalse()
74             }
75         }
76
77         given("input with too small payload size") {
78             val input = WireFrame(
79                     payload = ByteData(byteArrayOf(1, 2, 3)),
80                     version = 1,
81                     payloadTypeRaw = PayloadContentType.GOOGLE_PROTOCOL_BUFFER.hexValue,
82                     payloadSize = 1)
83
84             it("should fail validation") {
85                 assertThat(input.isValid()).isFalse()
86             }
87         }
88
89         given("input with too big payload size") {
90             val input = WireFrame(
91                     payload = ByteData(byteArrayOf(1, 2, 3)),
92                     version = 1,
93                     payloadTypeRaw = PayloadContentType.GOOGLE_PROTOCOL_BUFFER.hexValue,
94                     payloadSize = 8)
95
96             it("should fail validation") {
97                 assertThat(input.isValid()).isFalse()
98             }
99         }
100
101         given("valid input") {
102             val payload = byteArrayOf(6, 9, 8, 6)
103             val input = WireFrame(
104                     payload = ByteData(payload),
105                     version = 1,
106                     payloadTypeRaw = PayloadContentType.GOOGLE_PROTOCOL_BUFFER.hexValue,
107                     payloadSize = payload.size)
108
109             it("should pass validation") {
110                 assertThat(input.isValid()).isTrue()
111             }
112         }
113
114
115     }
116
117     describe("Wire Frame codec") {
118
119         describe("encode-decode methods' compatibility") {
120             val frame = createSampleFrame()
121             val encoded = encodeSampleFrame()
122             val decoded = decoder.decodeFirst(encoded)
123
124             it("should decode version") {
125                 assertThat(decoded.version).isEqualTo(frame.version)
126             }
127
128             it("should decode payload type") {
129                 assertThat(decoded.payloadTypeRaw).isEqualTo(frame.payloadTypeRaw)
130             }
131
132             it("should decode payload size") {
133                 assertThat(decoded.payloadSize).isEqualTo(frame.payloadSize)
134             }
135
136             it("should decode payload") {
137                 assertThat(decoded.payload.asString())
138                         .isEqualTo(payloadAsString)
139             }
140         }
141
142         describe("TCP framing") {
143             // see "Dealing with a Stream-based Transport" on http://netty.io/wiki/user-guide-for-4.x.html#wiki-h3-11
144
145             it("should decode message leaving rest unread") {
146                 val buff = Unpooled.buffer()
147                         .writeBytes(encodeSampleFrame())
148                         .writeByte(0xAA)
149                 val decoded = decoder.decodeFirst(buff)
150
151                 assertThat(decoded.isValid()).describedAs("should be valid").isTrue()
152                 assertThat(buff.readableBytes()).isEqualTo(1)
153             }
154
155             it("should throw exception when not even header fits") {
156                 val buff = Unpooled.buffer()
157                         .writeByte(0xFF)
158
159                 assertThatExceptionOfType(MissingWireFrameBytesException::class.java)
160                         .isThrownBy { decoder.decodeFirst(buff) }
161             }
162
163             it("should throw exception when first byte is not 0xFF but length looks ok") {
164                 val buff = Unpooled.buffer()
165                         .writeByte(0xAA)
166                         .writeBytes("some garbage".toByteArray())
167
168                 assertThatExceptionOfType(InvalidWireFrameMarkerException::class.java)
169                         .isThrownBy { decoder.decodeFirst(buff) }
170             }
171
172             it("should throw exception when first byte is not 0xFF and length is to short") {
173                 val buff = Unpooled.buffer()
174                         .writeByte(0xAA)
175
176                 assertThatExceptionOfType(InvalidWireFrameMarkerException::class.java)
177                         .isThrownBy { decoder.decodeFirst(buff) }
178             }
179
180             it("should throw exception when payload doesn't fit") {
181                 val buff = Unpooled.buffer()
182                         .writeBytes(encodeSampleFrame())
183                 buff.writerIndex(buff.writerIndex() - 2)
184
185                 assertThatExceptionOfType(MissingWireFrameBytesException::class.java)
186                         .isThrownBy { decoder.decodeFirst(buff) }
187             }
188
189         }
190     }
191
192 })