3 * oFono - Open Source Telephony
5 * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 const unsigned char invalid_gsm_extended[] = {
37 const unsigned char invalid_gsm_extended_len[] = {
41 const unsigned char invalid_ucs2[] = {
42 0x03, 0x93, 0x00, 0x00
45 unsigned short gsm_to_unicode_map[] =
187 unsigned short gsm_turkish_to_unicode_map[] =
216 /* We're not including some of the single shift codes to this map,
217 * because the turkish variant isn't symmetric, i.e., the same
218 * character is present in both the locking shift table as well as the
219 * single shift table */
340 #define UTF8_LENGTH(c) \
342 ((c) < 0x800 ? 2 : 3))
344 static void test_invalid(void)
348 short unsigned int exp_code;
350 char *res, *exp_res = NULL;
353 res = convert_gsm_to_utf8(invalid_gsm_extended, 0, &nread, &nwritten,
356 g_assert(nread == 0);
357 g_assert(nwritten == 0);
358 g_assert(res[0] == '\0');
362 * In case of invalid GSM extended code, we should display
363 * the character of the main default alphabet table.
365 res = convert_gsm_to_utf8(invalid_gsm_extended,
366 sizeof(invalid_gsm_extended),
367 &nread, &nwritten, 0);
369 exp_code = gsm_to_unicode_map[invalid_gsm_extended[1]*2 + 1];
371 exp_res_length = UTF8_LENGTH(exp_code);
372 exp_res = g_new0(char, exp_res_length + 1);
373 g_unichar_to_utf8(exp_code, exp_res);
375 g_assert(g_strcmp0(res, exp_res) == 0);
376 g_assert(nread == exp_res_length);
380 res = convert_gsm_to_utf8(invalid_gsm_extended_len,
381 sizeof(invalid_gsm_extended_len),
382 &nread, &nwritten, 0);
383 g_assert(res == NULL);
384 g_assert(nread == 3);
386 gsm = convert_ucs2_to_gsm(invalid_ucs2,
387 sizeof(invalid_ucs2),
388 &nread, &nwritten, 0);
389 g_assert(gsm == NULL);
390 g_assert(nread == 2);
393 gsm = convert_ucs2_to_gsm(invalid_ucs2,
394 sizeof(invalid_ucs2) - 1,
395 &nread, &nwritten, 0);
396 g_assert(gsm == NULL);
397 g_assert(nread == 0);
400 static void test_valid(void)
410 unsigned char buf[2];
412 static int map_size =
413 sizeof(gsm_to_unicode_map) / sizeof(unsigned short) / 2;
415 for (i = 0; i < map_size; i++) {
416 unsigned short c = gsm_to_unicode_map[i*2];
427 res = convert_gsm_to_utf8(buf, size, &nread, &nwritten, 0);
430 if (g_test_verbose())
431 g_print("size: %ld, nread:%ld, nwritten:%ld, %s\n",
432 size, nread, nwritten, res);
434 g_assert(nread == size);
436 verify = g_utf8_to_ucs4(res, -1, NULL, NULL, NULL);
438 g_assert(verify[0] == gsm_to_unicode_map[i*2+1]);
439 g_assert(verify[1] == 0);
441 g_assert(nwritten == UTF8_LENGTH(verify[0]));
443 back = convert_utf8_to_gsm(res, -1, &nread, &nwritten, 0);
447 g_assert(nwritten == size);
450 g_assert(back[0] == 0x1b);
451 g_assert(back[1] == (c & 0x7f));
453 g_assert(back[0] == (c & 0x7f));
462 static void test_valid_turkish(void)
472 unsigned char buf[2];
474 static int map_size =
475 sizeof(gsm_turkish_to_unicode_map) / sizeof(unsigned short) / 2;
477 for (i = 0; i < map_size; i++) {
478 unsigned short c = gsm_turkish_to_unicode_map[i*2];
489 res = convert_gsm_to_utf8_with_lang(buf, size, &nread,
493 if (g_test_verbose())
494 g_print("size: %ld, nread:%ld, nwritten:%ld, %s\n",
495 size, nread, nwritten, res);
497 g_assert(nread == size);
499 verify = g_utf8_to_ucs4(res, -1, NULL, NULL, NULL);
501 g_assert(verify[0] == gsm_turkish_to_unicode_map[i*2+1]);
502 g_assert(verify[1] == 0);
504 g_assert(nwritten == UTF8_LENGTH(verify[0]));
506 back = convert_utf8_to_gsm_with_lang(res, -1, &nread,
511 g_assert(nwritten == size);
514 g_assert(back[0] == 0x1b);
515 g_assert(back[1] == (c & 0x7f));
517 g_assert(back[0] == (c & 0x7f));
526 static const char hex_packed_sms[] = "493A283D0795C3F33C88FE06C9CB6132885EC6D34"
527 "1EDF27C1E3E97E7207B3A0C0A5241E377BB1D"
529 static const char expected[] = "It is easy to read text messages via AT "
531 static int reported_text_size = 49;
533 static void test_decode_encode(void)
535 const char *sms = hex_packed_sms;
536 unsigned char *decoded, *packed;
537 char *utf8, *hex_packed;
538 unsigned char *gsm, *gsm_encoded;
539 long hex_decoded_size;
540 long unpacked_size, packed_size;
541 long gsm_encoded_size;
544 if (g_test_verbose())
545 g_print("Size of the orig string: %u\n",
546 (unsigned int)strlen(sms));
548 decoded = decode_hex(sms, -1, &hex_decoded_size, 0);
550 g_assert(decoded != NULL);
552 if (g_test_verbose())
553 g_print("Decode to %ld bytes\n", hex_decoded_size);
555 if (g_test_verbose()) {
556 g_print("%s\n", sms);
558 for (i = 0; i < hex_decoded_size; i++)
559 g_print("%02X", decoded[i]);
563 gsm = unpack_7bit(decoded, hex_decoded_size, 0, FALSE,
564 reported_text_size, &unpacked_size, 0xff);
566 g_assert(gsm != NULL);
568 if (g_test_verbose())
569 g_print("String unpacked to %ld bytes\n", unpacked_size);
571 utf8 = convert_gsm_to_utf8(gsm, -1, NULL, NULL, 0xff);
573 g_assert(utf8 != NULL);
575 if (g_test_verbose())
576 g_print("String is: -->%s<--\n", utf8);
578 g_assert(strcmp(utf8, expected) == 0);
580 gsm_encoded = convert_utf8_to_gsm(utf8, -1, NULL,
581 &gsm_encoded_size, 0xff);
583 g_assert(gsm_encoded != NULL);
585 if (g_test_verbose())
586 g_print("Converted back to GSM string of %ld bytes\n",
589 g_assert(gsm_encoded[gsm_encoded_size] == 0xff);
590 g_assert(gsm_encoded_size == unpacked_size);
591 g_assert(memcmp(gsm_encoded, gsm, gsm_encoded_size) == 0);
596 packed = pack_7bit(gsm_encoded, -1, 0, FALSE, &packed_size, 0xff);
600 g_assert(packed != NULL);
602 if (g_test_verbose())
603 g_print("Packed GSM to size of %ld bytes\n", packed_size);
605 if (g_test_verbose()) {
606 for (i = 0; i < packed_size; i++)
607 g_print("%02X", packed[i]);
611 g_assert(packed_size == hex_decoded_size);
612 g_assert(memcmp(packed, decoded, packed_size) == 0);
616 hex_packed = encode_hex(packed, packed_size, 0);
618 g_assert(hex_packed != NULL);
622 if (g_test_verbose())
623 g_print("Hex encoded packed to size %ld bytes\n",
624 (long)strlen(hex_packed));
626 g_assert(strlen(hex_packed) == strlen(sms));
627 g_assert(strcmp(hex_packed, sms) == 0);
632 static void test_pack_size(void)
634 unsigned char c1[] = { 'a' };
635 unsigned char c2[] = { 'a', 'b' };
636 unsigned char c3[] = { 'a', 'b', 'c' };
637 unsigned char c4[] = { 'a', 'b', 'c', 'd' };
638 unsigned char c5[] = { 'a', 'b', 'c', 'd', 'e' };
639 unsigned char c6[] = { 'a', 'b', 'c', 'd', 'e', 'f' };
640 unsigned char c7[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g' };
641 unsigned char c8[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' };
643 unsigned char *packed;
646 packed = pack_7bit(c1, 1, 0, FALSE, &size, 0);
647 g_assert(packed != NULL);
651 packed = pack_7bit(c2, 2, 0, FALSE, &size, 0);
652 g_assert(packed != NULL);
656 packed = pack_7bit(c3, 3, 0, FALSE, &size, 0);
657 g_assert(packed != NULL);
661 packed = pack_7bit(c4, 4, 0, FALSE, &size, 0);
662 g_assert(packed != NULL);
666 packed = pack_7bit(c5, 5, 0, FALSE, &size, 0);
667 g_assert(packed != NULL);
671 packed = pack_7bit(c6, 6, 0, FALSE, &size, 0);
672 g_assert(packed != NULL);
676 packed = pack_7bit(c7, 7, 0, FALSE, &size, 0);
677 g_assert(packed != NULL);
679 g_assert((packed[6] & 0xfe) == 0);
682 packed = pack_7bit(c7, 7, 0, TRUE, &size, 0);
683 g_assert(packed != NULL);
685 g_assert(((packed[6] & 0xfe) >> 1) == '\r');
688 packed = pack_7bit(c8, 8, 0, FALSE, &size, 0);
689 g_assert(packed != NULL);
694 static void test_cr_handling(void)
696 unsigned char c7[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g' };
697 unsigned char c7_expected[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
699 unsigned char c8[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', '\r' };
700 unsigned char c8_expected[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
703 unsigned char *packed;
704 unsigned char *unpacked;
708 packed = pack_7bit(c8, 8, 0, TRUE, &packed_size, 0);
709 g_assert(packed != NULL);
710 g_assert(packed_size == 8);
711 g_assert(((packed[6] & 0xfe) >> 1) == '\r');
712 g_assert((packed[7] & 0x7f) == '\r');
714 unpacked = unpack_7bit(packed, 8, 0, TRUE, -1, &unpacked_size, 0);
715 if (g_test_verbose())
716 g_print("Unpacked to size: %ld\n", unpacked_size);
718 g_assert(unpacked != NULL);
719 g_assert(unpacked_size == 9);
720 g_assert(memcmp(c8_expected, unpacked, 9) == 0);
725 packed = pack_7bit(c7, 7, 0, TRUE, &packed_size, 0);
726 g_assert(packed != NULL);
727 g_assert(packed_size == 7);
728 g_assert(((packed[6] & 0xfe) >> 1) == '\r');
730 unpacked = unpack_7bit(packed, 7, 0, TRUE, -1, &unpacked_size, 0);
731 if (g_test_verbose())
732 g_print("Unpacked to size: %ld\n", unpacked_size);
734 g_assert(unpacked != NULL);
735 g_assert(unpacked_size == 7);
736 g_assert(memcmp(c7, unpacked, 7) == 0);
741 /* As above, but now unpack using SMS style, we should now have cr at
742 * the end of the stream
744 packed = pack_7bit(c7, 7, 0, TRUE, &packed_size, 0);
745 unpacked = unpack_7bit(packed, 7, 0, FALSE, 8, &unpacked_size, 0);
746 if (g_test_verbose())
747 g_print("Unpacked to size: %ld\n", unpacked_size);
749 g_assert(unpacked != NULL);
750 g_assert(unpacked_size == 8);
751 g_assert(memcmp(c7_expected, unpacked, 8) == 0);
757 static void test_sms_handling(void)
759 unsigned char c7[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g' };
761 unsigned char *packed;
762 unsigned char *unpacked;
766 packed = pack_7bit(c7, 7, 0, FALSE, &packed_size, 0);
767 g_assert(packed != NULL);
768 g_assert(packed_size == 7);
770 unpacked = unpack_7bit(packed, 7, 0, FALSE, 8, &unpacked_size, 0xff);
771 if (g_test_verbose())
772 g_print("Unpacked to size: %ld\n", unpacked_size);
774 g_assert(unpacked != NULL);
775 g_assert(unpacked_size == 8);
776 g_assert(unpacked[7] == 0);
777 g_assert(unpacked[8] == 0xff);
782 packed = pack_7bit(c7, 7, 0, FALSE, &packed_size, 0);
783 g_assert(packed != NULL);
784 g_assert(packed_size == 7);
786 unpacked = unpack_7bit(packed, 7, 0, FALSE, 7, &unpacked_size, 0xff);
787 if (g_test_verbose())
788 g_print("Unpacked to size: %ld\n", unpacked_size);
790 g_assert(unpacked != NULL);
791 g_assert(unpacked_size == 7);
792 g_assert(unpacked[7] == 0xff);
798 static void test_offset_handling(void)
800 unsigned char c7[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g' };
801 unsigned char c8[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' };
802 unsigned char c9[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' };
803 unsigned char *packed;
804 unsigned char *unpacked;
808 /* Pack at offset = 2 bytes, e.g. starting with 21st bit */
809 packed = pack_7bit(c7, 6, 2, FALSE, &packed_size, 0);
811 if (g_test_verbose())
812 g_print("Packed to size: %ld\n", packed_size);
814 g_assert(packed != NULL);
815 g_assert(packed_size == 6);
817 unpacked = unpack_7bit(packed, 6, 2, FALSE, 6, &unpacked_size, 0xff);
818 if (g_test_verbose())
819 g_print("Unpacked to size: %ld\n", unpacked_size);
821 g_assert(unpacked != NULL);
822 g_assert(unpacked_size == 6);
823 g_assert(unpacked[6] == 0xff);
824 g_assert(unpacked[0] == 'a');
825 g_assert(unpacked[5] == 'f');
830 /* Pack at offset = 6 bytes, we should be able to fit one character
831 * into the first byte, and the other 7 characters into the following
832 * 7 bytes. The 7 MSB bits of the last byte should be 0 since
833 * we're not using CBS packing
835 packed = pack_7bit(c8, 8, 6, FALSE, &packed_size, 0);
837 if (g_test_verbose())
838 g_print("Packed to size: %ld\n", packed_size);
840 g_assert(packed != NULL);
841 g_assert(packed_size == 8);
843 unpacked = unpack_7bit(packed, 8, 6, FALSE, 8, &unpacked_size, 0xff);
844 if (g_test_verbose())
845 g_print("Unpacked to size: %ld\n", unpacked_size);
847 g_assert(unpacked != NULL);
848 g_assert(unpacked_size == 8);
849 g_assert(unpacked[8] == 0xff);
850 g_assert(unpacked[0] == 'a');
851 g_assert(unpacked[7] == 'h');
856 /* Same as above, but instead pack in 9 characters */
857 packed = pack_7bit(c9, 9, 6, FALSE, &packed_size, 0);
859 if (g_test_verbose())
860 g_print("Packed to size: %ld\n", packed_size);
862 g_assert(packed != NULL);
863 g_assert(packed_size == 8);
865 unpacked = unpack_7bit(packed, 8, 6, FALSE, 9, &unpacked_size, 0xff);
866 if (g_test_verbose())
867 g_print("Unpacked to size: %ld\n", unpacked_size);
869 g_assert(unpacked != NULL);
870 g_assert(unpacked_size == 9);
871 g_assert(unpacked[9] == 0xff);
872 g_assert(unpacked[0] == 'a');
873 g_assert(unpacked[8] == 'i');
879 static unsigned char sim_7bit[] = { 0x6F, 0x46, 0x6F, 0x6E, 0x6F, 0xFF, 0xFF };
880 static unsigned char sim_80_1[] = { 0x80, 0x00, 0x6F, 0x00, 0x6E, 0x00,
882 static unsigned char sim_80_2[] = { 0x80, 0x00, 0x6F, 0x00, 0x6E, 0x00,
883 0x6F, 0xFF, 0xFF, 0xFF};
884 static unsigned char sim_80_3[] = { 0x80, 0x00, 0x6F, 0x00, 0x6E, 0x00,
886 static unsigned char sim_81_0[] = { 0x81, 0x05, 0x13, 0x53, 0x95, 0xA6,
888 static unsigned char sim_81_1[] = { 0x81, 0x03, 0x00, 0x6F, 0x6E, 0x6F, 0xFF };
889 static unsigned char sim_81_2[] = { 0x81, 0x05, 0x08, 0xB3, 0xB4, 0xB5, 0x53,
890 0x54, 0xFF, 0xFF, 0xFF };
891 static unsigned char sim_82_0[] = { 0x82, 0x05, 0x05, 0x30, 0x2D, 0x82,
893 static unsigned char sim_82_1[] = { 0x82, 0x05, 0x04, 0x00, 0x2D, 0xB3, 0xB4,
895 static unsigned char sim_82_2[] = { 0x82, 0x05, 0xD8, 0x00, 0x2D, 0xB3, 0xB4,
898 static void test_sim(void)
902 utf8 = sim_string_to_utf8(sim_7bit, sizeof(sim_7bit));
905 g_assert(strcmp(utf8, "oFono") == 0);
908 utf8 = sim_string_to_utf8(sim_80_1, sizeof(sim_80_1));
910 g_assert(strcmp(utf8, "ono") == 0);
913 utf8 = sim_string_to_utf8(sim_80_2, sizeof(sim_80_2));
915 g_assert(strcmp(utf8, "ono") == 0);
918 utf8 = sim_string_to_utf8(sim_80_3, sizeof(sim_80_3));
920 g_assert(strcmp(utf8, "ono") == 0);
923 utf8 = sim_string_to_utf8(sim_81_0, sizeof(sim_81_0));
927 utf8 = sim_string_to_utf8(sim_81_2, sizeof(sim_81_2));
931 utf8 = sim_string_to_utf8(sim_81_1, sizeof(sim_81_1));
933 g_assert(strcmp(utf8, "ono") == 0);
936 utf8 = sim_string_to_utf8(sim_82_0, sizeof(sim_82_0));
940 utf8 = sim_string_to_utf8(sim_82_1, sizeof(sim_82_1));
944 utf8 = sim_string_to_utf8(sim_82_2, sizeof(sim_82_2));
945 g_assert(utf8 == NULL);
948 static void test_unicode_to_gsm(void)
955 unsigned char buf[2];
959 static int map_size =
960 sizeof(gsm_to_unicode_map) / sizeof(unsigned short) / 2;
962 for (i = 0; i < map_size; i++) {
963 unsigned short c = gsm_to_unicode_map[i*2+1];
968 res = convert_ucs2_to_gsm(buf, 2, &nread, &nwritten, 0);
971 if (g_test_verbose())
972 g_print("nread:%ld, nwritten:%ld, %s\n",
973 nread, nwritten, res);
976 g_assert(nwritten == 2);
978 g_assert(nwritten == 1);
980 utf8 = g_convert((const gchar *) buf, 2,
985 back = convert_utf8_to_gsm(utf8, strlen(utf8), &nread,
989 if (back[0] == 0x1B) {
990 g_assert(nwritten == 2);
991 verify = back[0] << 8 | back[1];
993 g_assert(nwritten == 1);
997 if (g_test_verbose())
998 g_print("nwritten:%ld, verify: 0x%x\n",
1001 g_assert(verify == gsm_to_unicode_map[i*2]);
1009 int main(int argc, char **argv)
1011 g_test_init(&argc, &argv, NULL);
1013 g_test_add_func("/testutil/Invalid Conversions", test_invalid);
1014 g_test_add_func("/testutil/Valid Conversions", test_valid);
1015 g_test_add_func("/testutil/Valid Turkish National Variant Conversions",
1016 test_valid_turkish);
1017 g_test_add_func("/testutil/Decode Encode", test_decode_encode);
1018 g_test_add_func("/testutil/Pack Size", test_pack_size);
1019 g_test_add_func("/testutil/CBS CR Handling", test_cr_handling);
1020 g_test_add_func("/testutil/SMS Handling", test_sms_handling);
1021 g_test_add_func("/testutil/Offset Handling", test_offset_handling);
1022 g_test_add_func("/testutil/SIM conversions", test_sim);
1023 g_test_add_func("/testutil/Valid Unicode to GSM Conversion",
1024 test_unicode_to_gsm);
1026 return g_test_run();