/* * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "clar.h" #include "util/hdlc.h" #include #include "stubs_passert.h" // Setup void test_hdlc__initialize(void) { } void test_hdlc__cleanup(void) { } // Tests void test_hdlc__decode_no_special(void) { // without any special characters const char *str = "\x7eThis is a long string without any special characters to be escaped.\x7e"; int len = strlen(str); HdlcStreamingContext ctx; hdlc_streaming_decode_reset(&ctx); for (int i = 0; i < len; i++) { char c = str[i]; bool should_store, is_invalid; bool is_complete = hdlc_streaming_decode(&ctx, (uint8_t *)&c, &should_store, &is_invalid); cl_assert(is_invalid == false); if (i == 0 || i == len - 1) { cl_assert(is_complete == true); cl_assert(should_store == false); } else { cl_assert(is_complete == false); cl_assert(should_store == true); cl_assert(c == str[i]); } } } void test_hdlc__special_characters(void) { // make sure the escape characters haven't changed cl_assert(HDLC_FLAG == 0x7e); cl_assert(HDLC_ESCAPE == 0x7d); cl_assert(HDLC_ESCAPE_MASK == 0x20); } void test_hdlc__decode_empty(void) { // consecutive empty frames const uint8_t str[4] = {HDLC_FLAG, HDLC_FLAG, HDLC_FLAG, HDLC_FLAG}; HdlcStreamingContext ctx; hdlc_streaming_decode_reset(&ctx); for (int i = 0; i < 4; i++) { char c = str[i]; bool should_store, is_invalid; bool is_complete = hdlc_streaming_decode(&ctx, (uint8_t *)&c, &should_store, &is_invalid); cl_assert(is_complete == true); cl_assert(should_store == false); cl_assert(is_invalid == false); } } void test_hdlc__decode_invalid(void) { // invalid sequences uint8_t data; bool should_store, is_invalid, is_complete; HdlcStreamingContext ctx; // two consecutive escape characters hdlc_streaming_decode_reset(&ctx); data = HDLC_ESCAPE; is_complete = hdlc_streaming_decode(&ctx, &data, &should_store, &is_invalid); cl_assert(is_complete == false); cl_assert(should_store == false); cl_assert(is_invalid == false); data = HDLC_ESCAPE; is_complete = hdlc_streaming_decode(&ctx, &data, &should_store, &is_invalid); cl_assert(is_complete == false); cl_assert(should_store == false); cl_assert(is_invalid == true); // an escape character followed by a flag hdlc_streaming_decode_reset(&ctx); data = HDLC_ESCAPE; is_complete = hdlc_streaming_decode(&ctx, &data, &should_store, &is_invalid); cl_assert(is_complete == false); cl_assert(should_store == false); cl_assert(is_invalid == false); data = HDLC_FLAG; is_complete = hdlc_streaming_decode(&ctx, &data, &should_store, &is_invalid); cl_assert(is_complete == true); cl_assert(should_store == false); cl_assert(is_invalid == true); } void test_hdlc__decode_escaped_special(void) { // 2 escaped special characters uint8_t data; bool should_store, is_invalid, is_complete; HdlcStreamingContext ctx; hdlc_streaming_decode_reset(&ctx); // escaped escape character data = HDLC_ESCAPE; is_complete = hdlc_streaming_decode(&ctx, &data, &should_store, &is_invalid); cl_assert(is_complete == false); cl_assert(should_store == false); cl_assert(is_invalid == false); data = HDLC_ESCAPE ^ HDLC_ESCAPE_MASK; is_complete = hdlc_streaming_decode(&ctx, &data, &should_store, &is_invalid); cl_assert(is_complete == false); cl_assert(should_store == true); cl_assert(is_invalid == false); cl_assert(data == HDLC_ESCAPE); // escaped flag data = HDLC_ESCAPE; is_complete = hdlc_streaming_decode(&ctx, &data, &should_store, &is_invalid); cl_assert(is_complete == false); cl_assert(should_store == false); cl_assert(is_invalid == false); data = HDLC_FLAG ^ HDLC_ESCAPE_MASK; is_complete = hdlc_streaming_decode(&ctx, &data, &should_store, &is_invalid); cl_assert(is_complete == false); cl_assert(should_store == true); cl_assert(is_invalid == false); cl_assert(data == HDLC_FLAG); } void test_hdlc__encode_decode(void) { const char *str = "this is a string with the special \x7e \x7d \x7e\x7d \x7d\x7e characters"; char buffer[100]; int write_idx = 0; for (int i = 0; i < strlen(str); i++) { char c = str[i]; if (hdlc_encode((uint8_t *)&c)) { buffer[write_idx++] = HDLC_ESCAPE; } buffer[write_idx++] = c; } buffer[write_idx++] = HDLC_FLAG; cl_assert(write_idx == strlen(str) + 7 /* 6 special characters to escape + 1 flag at end */); HdlcStreamingContext ctx; hdlc_streaming_decode_reset(&ctx); int read_idx = 0; int i = 0; while (true) { char c = buffer[i++]; bool should_store, is_invalid; bool is_complete = hdlc_streaming_decode(&ctx, (uint8_t *)&c, &should_store, &is_invalid); cl_assert(is_invalid == false); if (should_store) { cl_assert(is_complete == false); cl_assert(c == str[read_idx++]); } if (is_complete) { cl_assert(should_store == false); cl_assert(i == write_idx); break; } } cl_assert(read_idx == strlen(str)); }