]>
Commit | Line | Data |
---|---|---|
427c49bc A |
1 | // |
2 | // su-15-cfdictionary-der.c | |
3 | // utilities | |
4 | // | |
5 | // Created by Mitch Adler on 6/20/12. | |
6 | // Copyright (c) 2012 Apple Inc. All rights reserved. | |
7 | // | |
8 | ||
9 | #include "utilities_regressions.h" | |
10 | ||
11 | #include "utilities/der_plist.h" | |
12 | #include "utilities/der_plist_internal.h" | |
13 | ||
14 | #include "utilities/SecCFRelease.h" | |
15 | #include "utilities/array_size.h" | |
16 | ||
17 | #include <CoreFoundation/CoreFoundation.h> | |
18 | ||
19 | ||
20 | #define kMaxResultSize 1024 | |
21 | ||
22 | struct test_case { | |
23 | CFTypeRef keys[10]; | |
24 | CFTypeRef values[10]; | |
25 | size_t encoded_size; | |
26 | uint8_t encoded[256]; | |
27 | }; | |
28 | ||
29 | static struct test_case test_cases[] = | |
30 | { | |
31 | { .keys = { CFSTR("First"), }, | |
32 | .values = { CFSTR("First Value!"), }, | |
33 | .encoded_size = 25, .encoded = { 0x31, 0x17, 0x30, 0x15, 0x0C, 0x05, 0x46, 0x69, 0x72, 0x73, 0x74, 0x0C, 0x0C, 0x46, 0x69, 0x72, 0x73, 0x74, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x21, }, | |
34 | }, | |
35 | { .keys = { CFSTR("First"), CFSTR("Second"), }, | |
36 | .values = { CFSTR("First Value!"), CFSTR("A second value"), }, | |
37 | .encoded_size = 51, .encoded = { 0x31, 0x31, | |
38 | 0x30, 0x15, 0x0C, 0x05, 0x46, 0x69, 0x72, 0x73, 0x74, 0x0C, 0x0C, 0x46, 0x69, 0x72, 0x73, 0x74, 0x20, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x21, | |
39 | 0x30, 0x18, 0x0C, 0x06, 0x53, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x0C, 0x0E, 0x41, 0x20, 0x73, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, }, | |
40 | }, | |
41 | }; | |
42 | ||
43 | #define kTestsPerDictionaryTest 8 | |
44 | static void test_dictionary(CFDictionaryRef testValue, size_t expected_size, const uint8_t* expected_data) | |
45 | { | |
46 | uint8_t buffer[kMaxResultSize]; | |
47 | uint8_t* buffer_end = buffer + sizeof(buffer); | |
48 | ||
49 | uint8_t* encoded = der_encode_plist(testValue, NULL, buffer, buffer_end); | |
50 | ||
51 | ok(encoded != NULL && | |
52 | (expected_size == (buffer_end - encoded)) && | |
53 | (memcmp(encoded, expected_data, expected_size) == 0)); | |
54 | ||
55 | encoded = der_encode_dictionary(testValue, NULL, buffer, buffer_end); | |
56 | ||
57 | ok(encoded != NULL && | |
58 | (expected_size == (buffer_end - encoded)) && | |
59 | (memcmp(encoded, expected_data, expected_size) == 0)); | |
60 | ||
61 | #if 0 | |
62 | printf(".encoded_size = %d, .encoded = { ", (buffer_end - encoded)); | |
63 | for(int c = 0; c < (buffer_end - encoded); ++c) | |
64 | printf("0x%02X, ", encoded[c]); | |
65 | printf("},\n"); | |
66 | #endif | |
67 | ||
68 | CFDictionaryRef decoded = NULL; | |
69 | ||
70 | const uint8_t* decode_end = der_decode_dictionary(NULL, kCFPropertyListMutableContainersAndLeaves, | |
71 | &decoded, NULL, encoded, buffer_end); | |
72 | ||
73 | ok(decode_end == buffer_end, "didn't decode whole buffer"); | |
74 | ok((decoded != NULL) && CFEqual(decoded, testValue), "Didn't make equal value."); | |
75 | ||
76 | CFPropertyListRef decoded_type = NULL; | |
77 | ||
78 | decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainersAndLeaves, | |
79 | &decoded_type, NULL, encoded, buffer_end); | |
80 | ||
81 | ok(decode_end == buffer_end, "didn't decode whole buffer"); | |
82 | ok((decoded != NULL) && CFEqual(decoded_type, testValue), "Didn't make equal value."); | |
83 | ||
84 | ok(der_sizeof_dictionary(testValue, NULL) == expected_size, "Size correct."); | |
85 | ok(der_sizeof_plist(testValue, NULL) == expected_size, "Size correct."); | |
86 | ||
87 | CFReleaseNull(decoded); | |
88 | CFReleaseNull(decoded_type); | |
89 | } | |
90 | ||
91 | ||
92 | #define kTestsPerTestCase (1 + kTestsPerDictionaryTest) | |
93 | static void one_test(const struct test_case * thisCase) | |
94 | { | |
95 | CFIndex key_count = 0; | |
96 | while (key_count < array_size(thisCase->keys) && thisCase->keys[key_count] != NULL) | |
97 | ++key_count; | |
98 | ||
99 | CFIndex value_count = 0; | |
100 | while (value_count < array_size(thisCase->values) && thisCase->values[value_count] != NULL) | |
101 | ++value_count; | |
102 | ||
103 | ok(key_count == value_count); | |
104 | ||
105 | CFDictionaryRef testValue = CFDictionaryCreate(NULL, (const void**)thisCase->keys, (const void**)thisCase->values, key_count, | |
106 | &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); | |
107 | ||
108 | test_dictionary(testValue, thisCase->encoded_size, thisCase->encoded); | |
109 | ||
110 | CFReleaseNull(testValue); | |
111 | } | |
112 | ||
113 | #define kTestCount (array_size(test_cases) * kTestsPerTestCase) + kTestsPerDictionaryTest | |
114 | static void tests(void) | |
115 | { | |
116 | for (int testnumber = 0; testnumber < array_size(test_cases); ++testnumber) | |
117 | one_test(test_cases + testnumber); | |
118 | ||
119 | ||
120 | // Big honking test case. | |
121 | CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); | |
122 | ||
123 | const uint8_t some[] = { 0x10, 0xFF, 0x00, 0x12, 0xA5 }; | |
124 | CFDataRef someData = CFDataCreate(NULL, some, array_size(some)); | |
125 | ||
126 | const void * arrayElements[] = { kCFBooleanFalse, someData, CFSTR("In Array"), }; | |
127 | ||
128 | CFArrayRef arrayValue = CFArrayCreate(NULL, arrayElements, array_size(arrayElements), &kCFTypeArrayCallBacks); | |
129 | CFReleaseNull(someData); | |
130 | ||
131 | const uint8_t key[] = { 0xFC, 0xFF, 0xFA }; | |
132 | CFDataRef dataKey = CFDataCreate(NULL, key, array_size(key)); | |
133 | ||
134 | CFDictionaryAddValue(dictionary, dataKey, arrayValue); | |
135 | CFReleaseNull(dataKey); | |
136 | CFReleaseNull(arrayValue); | |
137 | ||
138 | int numberValueValue = 2313; | |
139 | CFNumberRef numberValue = CFNumberCreate(NULL, kCFNumberIntType, &numberValueValue); | |
140 | ||
141 | CFDictionaryAddValue(dictionary, CFSTR("Oh yeah"), kCFBooleanTrue); | |
142 | CFDictionaryAddValue(dictionary, kCFBooleanFalse, numberValue); | |
143 | CFReleaseNull(numberValue); | |
144 | ||
145 | int numberKeyValue = 2313; | |
146 | CFNumberRef numberKey = CFNumberCreate(NULL, kCFNumberIntType, &numberKeyValue); | |
147 | ||
148 | CFDictionaryAddValue(dictionary, numberKey, kCFBooleanTrue); | |
149 | CFReleaseNull(numberKey); | |
150 | ||
151 | uint8_t expected_result[] = { 0x31, 0x3D, 0x30, 0x07, 0x01, 0x01, 0x00, 0x02, 0x02, 0x09, 0x09, 0x30, 0x07, 0x02, 0x02, 0x09, 0x09, 0x01, 0x01, 0x01, 0x30, 0x0C, 0x0C, 0x07, 0x4F, 0x68, 0x20, 0x79, 0x65, 0x61, 0x68, 0x01, 0x01, 0x01, 0x30, 0x1B, 0x04, 0x03, 0xFC, 0xFF, 0xFA, 0x30, 0x14, 0x01, 0x01, 0x00, 0x04, 0x05, 0x10, 0xFF, 0x00, 0x12, 0xA5, 0x0C, 0x08, 0x49, 0x6E, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, }; | |
152 | test_dictionary(dictionary, array_size(expected_result), expected_result); | |
153 | CFReleaseSafe(dictionary); | |
154 | } | |
155 | ||
156 | int su_15_cfdictionary_der(int argc, char *const *argv) | |
157 | { | |
158 | plan_tests(kTestCount); | |
159 | tests(); | |
160 | ||
161 | return 0; | |
162 | } |