1 /* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
2 
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6 
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation.  The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License, version 2.0, for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 #include <fcntl.h>
24 #include <mysql/components/component_implementation.h>
25 #include <mysql/components/service_implementation.h>
26 #include <mysql/components/services/mysql_string.h>
27 #include "m_string.h"  // strlen
28 #include "my_sys.h"    // my_write, my_malloc
29 #include "test_string_service_long.h"
30 
31 #define MAX_BUFFER_LENGTH 80
32 
33 #define WRITE_LOG(lit_log_text)   \
34   strcpy(log_text, lit_log_text); \
35   fwrite((uchar *)log_text, sizeof(char), strlen(log_text), outfile)
36 
37 /**
38   This file contains a test (example) component, which tests the service
39   "test_service", provided by the component "service_component".
40 */
41 
42 /**
43   Initialization entry method for test component. It executes the tests of the
44   service.
45 */
test_string_service_init()46 mysql_service_status_t test_string_service_init() {
47   FILE *outfile;
48 
49   my_h_string out_string = nullptr;
50   const char *test_text = "Hello MySql-8.0";
51   const char *empty_test_text = "";
52   char low_test_text[MAX_BUFFER_LENGTH];
53   char upper_test_text[MAX_BUFFER_LENGTH];
54   char log_text[MAX_BUFFER_LENGTH];
55   const char *filename = "test_string_service.log";
56 
57   unlink(filename);
58   outfile = fopen(filename, "w+");
59 
60   WRITE_LOG("test_string_service init:\n");
61 
62   if (mysql_service_mysql_string_factory->create(&out_string)) {
63     WRITE_LOG("Create string failed.\n");
64   } else {
65     mysql_service_mysql_string_factory->destroy(out_string);
66     WRITE_LOG("Destroy string object.\n");
67     // In buffer=NULL in convert from buffer
68     if (mysql_service_mysql_string_converter->convert_from_buffer(
69             &out_string,
70             nullptr,  // its a input buffer
71             strlen(test_text), "utf8")) {
72       WRITE_LOG("Buffer=NULL in convert from buffer: passed.\n");
73     };
74     // Lenght is too high for buffer in convert from buffer
75     if (mysql_service_mysql_string_converter->convert_from_buffer(
76             &out_string,
77             test_text,  // its a input buffer
78             strlen(test_text) + 10, "utf8")) {
79       WRITE_LOG("Length too high for buffer in convert from buffer: passed.\n");
80     }
81     // Lenght is zero for buffer in convert from buffer
82     if (mysql_service_mysql_string_converter->convert_from_buffer(
83             &out_string,
84             test_text,  // its a input buffer
85             0, "utf8")) {
86       WRITE_LOG("Length is zero for buffer in convert from buffer: failed.\n");
87     } else {
88       WRITE_LOG("Length is zero for buffer in convert from buffer: passed.\n");
89     }
90     // Lenght is negative for buffer in convert from buffer
91     // Crash as real_alloc (this=0x7f1ddc29a528, length=18446744073709551615)
92     /*      if
93        (mysql_service_mysql_string_converter->convert_from_buffer(&out_string,
94                                                 test_text, // its a input buffer
95                                                 -1,
96                                                 "utf8"))
97           {
98             WRITE_LOG ("Length is negative for buffer in convert from buffer:
99        failed.\n");
100           }
101           else
102           {
103             WRITE_LOG ("Length is negative for buffer in convert from buffer:
104        passed.\n");
105           }
106     */
107     // Empty string in convert from buffer
108     if (mysql_service_mysql_string_converter->convert_from_buffer(
109             &out_string,
110             empty_test_text,  // its a input buffer
111             strlen(empty_test_text), "utf8")) {
112       WRITE_LOG("Empty string as input to convert from buffer failed.\n");
113     } else {
114       WRITE_LOG("Empty string as input to convert from buffer passed.\n");
115     }
116     // Valid convert from buffer
117     if (mysql_service_mysql_string_converter->convert_from_buffer(
118             &out_string,
119             test_text,  // its a input buffer
120             strlen(test_text), "utf8")) {
121       WRITE_LOG("Convert from buffer failed.\n");
122     } else {
123       uint out_length = 0;
124       WRITE_LOG("Convert from buffer passed.\n");
125       // NULL as in_string in get number of chars
126       if (mysql_service_mysql_string_character_access->get_char_length(
127               nullptr, &out_length)) {
128         WRITE_LOG("NULL as input spring in get_char_length passed.\n");
129       }
130       // valid get number of chars
131       if (mysql_service_mysql_string_character_access->get_char_length(
132               out_string, &out_length)) {
133         WRITE_LOG("Get number of chars failed.\n");
134       } else {
135         if (out_length == 15) {
136           WRITE_LOG("Number of chars right.\n");
137         } else {
138           WRITE_LOG("Number of chars wrong.\n");
139         }
140       }
141       out_length = 0;
142       // NULL as in_string in get number of bytes
143       if (mysql_service_mysql_string_byte_access->get_byte_length(
144               nullptr, &out_length)) {
145         WRITE_LOG("NULL as input buffer in get_byte_length passed.\n");
146       }
147       // valid get number of bytes
148       if (mysql_service_mysql_string_byte_access->get_byte_length(
149               out_string, &out_length)) {
150         WRITE_LOG("Get number of bytes failed.\n");
151       } else {
152         if (out_length == 15) {
153           WRITE_LOG("Number of bytes right.\n");
154         } else {
155           WRITE_LOG("Number of bytes wrong.\n");
156         }
157       }
158       // Convert to low string
159       my_h_string low_string = nullptr;
160       if (mysql_service_mysql_string_factory->create(&low_string)) {
161         WRITE_LOG("Create lower string object failed.\n");
162       } else {
163         // NULL as input buffer in tolower
164         if (mysql_service_mysql_string_case->tolower(&low_string, nullptr)) {
165           WRITE_LOG("NULL as input buffer in tolower passed.\n");
166         }
167         if (mysql_service_mysql_string_case->tolower(&low_string, out_string)) {
168           WRITE_LOG("Tolower failed.\n");
169         } else {
170           WRITE_LOG("Tolower passed:\n");
171           // NULL as input buffer in Convert string to buffer
172           if (mysql_service_mysql_string_converter->convert_to_buffer(
173                   nullptr, low_test_text, MAX_BUFFER_LENGTH, "utf8")) {
174             WRITE_LOG("NULL as input buffer in Convert to buffer passed.\n");
175           }
176           // Convert low string to buffer
177           if (mysql_service_mysql_string_converter->convert_to_buffer(
178                   low_string, low_test_text, MAX_BUFFER_LENGTH, "utf8")) {
179             WRITE_LOG("Convert to buffer failed.\n");
180           } else {
181             WRITE_LOG(low_test_text);
182             WRITE_LOG("\n");
183           }
184         }
185       }
186       mysql_service_mysql_string_factory->destroy(low_string);
187       // Convert to upper string
188       my_h_string upper_string = nullptr;
189       if (mysql_service_mysql_string_factory->create(&upper_string)) {
190         WRITE_LOG("Create upper string object failed.\n");
191       } else {
192         // NULL as input buffer in toupper
193         if (mysql_service_mysql_string_case->toupper(&upper_string, nullptr)) {
194           WRITE_LOG("NULL as input buffer in toupper passed.\n");
195         }
196         if (mysql_service_mysql_string_case->toupper(&upper_string,
197                                                      out_string)) {
198           WRITE_LOG("Toupper failed.\n");
199         } else {
200           WRITE_LOG("Toupper passed:\n");
201           if (mysql_service_mysql_string_converter->convert_to_buffer(
202                   upper_string, upper_test_text, MAX_BUFFER_LENGTH, "utf8")) {
203             WRITE_LOG("Convert to buffer failed.\n");
204           } else {
205             WRITE_LOG(upper_test_text);
206             WRITE_LOG("\n");
207           }
208         }
209       }
210       mysql_service_mysql_string_factory->destroy(upper_string);
211       // Get char with index 1
212       ulong out_char;
213       if (mysql_service_mysql_string_character_access->get_char(out_string, 1,
214                                                                 &out_char)) {
215         WRITE_LOG("Get char with index 1 failed.\n");
216       } else {
217         WRITE_LOG("Get char with index 1 passed.");
218         WRITE_LOG("\n");
219       }
220       // Get char with index > strlen : Must fail
221       if (mysql_service_mysql_string_character_access->get_char(
222               out_string, strlen(test_text) + 1, &out_char)) {
223         WRITE_LOG("Get char with index > strlen passed.\n");
224       }
225       // Get byte with index strlen
226       uint out_byte;
227       if (mysql_service_mysql_string_byte_access->get_byte(
228               out_string, strlen(test_text) - 1, &out_byte)) {
229         WRITE_LOG("Get byte with index strlen failed.\n");
230       } else {
231         WRITE_LOG("Get byte with index strlen passed.");
232         WRITE_LOG("\n");
233       }
234       // Get byte with index > strlen : Must fail
235       if (mysql_service_mysql_string_byte_access->get_byte(
236               out_string, strlen(test_text) + 1, &out_byte)) {
237         WRITE_LOG("Get byte with index > strlen passed.\n");
238       }
239       // Iterator functions:
240       my_h_string_iterator out_iterator = nullptr;
241       // NULL as input buffer in iterator_create
242       if (mysql_service_mysql_string_iterator->iterator_create(nullptr,
243                                                                &out_iterator)) {
244         WRITE_LOG("NULL as input buffer in create iterator passed.\n");
245       }
246       if (mysql_service_mysql_string_iterator->iterator_create(out_string,
247                                                                &out_iterator)) {
248         WRITE_LOG("Create iterator failed.\n");
249       } else {
250         int out_iter_char;
251         bool out = false;
252         WRITE_LOG("Create iterator passed.\n");
253         // NULL as iterator in get_next
254         if (mysql_service_mysql_string_iterator->iterator_get_next(
255                 nullptr, &out_iter_char)) {
256           WRITE_LOG("NULL as Iterator in get next passed.\n");
257         }
258         // NULL as iterator in is_lower
259         if (mysql_service_mysql_string_ctype->is_lower(nullptr, &out)) {
260           WRITE_LOG("NULL as iterator in Is lower passed.\n");
261         }
262         // NULL as iterator in is_upper
263         if (mysql_service_mysql_string_ctype->is_upper(nullptr, &out)) {
264           WRITE_LOG("NULL as iterator in is_upper passed.\n");
265         }
266         // NULL as iterator in is_digit
267         if (mysql_service_mysql_string_ctype->is_digit(nullptr, &out)) {
268           WRITE_LOG("NULL as iterator in is_digit passed.\n");
269         }
270         while (mysql_service_mysql_string_iterator->iterator_get_next(
271                    out_iterator, &out_iter_char) != true) {
272           WRITE_LOG("Iterator get next passed.\n");
273           if (mysql_service_mysql_string_ctype->is_lower(out_iterator, &out)) {
274             WRITE_LOG("Is lower failed.\n");
275           } else {
276             if (out) {
277               WRITE_LOG("Is lower.\n");
278             }
279           }
280           if (mysql_service_mysql_string_ctype->is_upper(out_iterator, &out)) {
281             WRITE_LOG("Is upper failed.\n");
282           } else {
283             if (out) {
284               WRITE_LOG("Is upper.\n");
285             }
286           }
287           if (mysql_service_mysql_string_ctype->is_digit(out_iterator, &out)) {
288             WRITE_LOG("Is digit failed.\n");
289           } else {
290             if (out) {
291               WRITE_LOG("Is digit.\n");
292             }
293           }
294         }
295         mysql_service_mysql_string_iterator->iterator_destroy(out_iterator);
296         WRITE_LOG("Iterator destroyed.\n");
297       }
298     }
299   }
300   mysql_service_mysql_string_factory->destroy(out_string);
301   WRITE_LOG("Destroy string object.\n");
302 
303   WRITE_LOG("End of init\n");
304   fclose(outfile);
305 
306   return false;
307 }
308 
309 /**
310   De-initialization method for Component.
311 */
test_string_service_deinit()312 mysql_service_status_t test_string_service_deinit() { return false; }
313 
314 /* An empty list as no service is provided. */
315 BEGIN_COMPONENT_PROVIDES(test_string_service)
316 END_COMPONENT_PROVIDES();
317 
318 REQUIRES_SERVICE_PLACEHOLDER(mysql_string_factory);
319 REQUIRES_SERVICE_PLACEHOLDER(mysql_string_converter);
320 REQUIRES_SERVICE_PLACEHOLDER(mysql_string_character_access);
321 REQUIRES_SERVICE_PLACEHOLDER(mysql_string_byte_access);
322 REQUIRES_SERVICE_PLACEHOLDER(mysql_string_case);
323 REQUIRES_SERVICE_PLACEHOLDER(mysql_string_iterator);
324 REQUIRES_SERVICE_PLACEHOLDER(mysql_string_ctype);
325 
326 /* A list of required services. */
327 BEGIN_COMPONENT_REQUIRES(test_string_service)
328 REQUIRES_SERVICE(mysql_string_factory),
329     REQUIRES_SERVICE(mysql_string_converter),
330     REQUIRES_SERVICE(mysql_string_character_access),
331     REQUIRES_SERVICE(mysql_string_byte_access),
332     REQUIRES_SERVICE(mysql_string_case),
333     REQUIRES_SERVICE(mysql_string_iterator),
334     REQUIRES_SERVICE(mysql_string_ctype), END_COMPONENT_REQUIRES();
335 
336 /* A list of metadata to describe the Component. */
337 BEGIN_COMPONENT_METADATA(test_string_service)
338 METADATA("mysql.author", "Oracle Corporation"),
339     METADATA("mysql.license", "GPL"), METADATA("test_string_service", "1"),
340     END_COMPONENT_METADATA();
341 
342 /* Declaration of the Component. */
343 DECLARE_COMPONENT(test_string_service, "mysql:test_string_service")
344 test_string_service_init, test_string_service_deinit END_DECLARE_COMPONENT();
345 
346 /* Defines list of Components contained in this library. Note that for now
347   we assume that library will have exactly one Component. */
348 DECLARE_LIBRARY_COMPONENTS &COMPONENT_REF(test_string_service)
349     END_DECLARE_LIBRARY_COMPONENTS
350