1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <ddk/device.h>
6 #include <ddk/driver.h>
7 #include <ddk/binding.h>
8 #include <ddk/protocol/test.h>
9 
10 #include <unittest/unittest.h>
11 #include <stddef.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <limits.h>
16 
17 extern struct test_case_element* test_case_ddk_metadata;
18 extern struct test_case_element* test_case_ddk_usb_request;
19 
20 zx_device_t* ddk_test_dev;
21 
ddk_test_output_func(const char * line,int len,void * arg)22 static void ddk_test_output_func(const char* line, int len, void* arg) {
23     zx_handle_t h = *(zx_handle_t*)arg;
24     // len is not actually the number of bytes to output
25     zx_socket_write(h, 0u, line, strlen(line), NULL);
26 }
27 
update_test_report(bool success,test_report_t * report)28 static void update_test_report(bool success, test_report_t* report) {
29     report->n_tests++;
30     if (success) {
31         report->n_success++;
32     } else {
33         report->n_failed++;
34     }
35 }
36 
ddk_test_func(void * cookie,test_report_t * report)37 static zx_status_t ddk_test_func(void* cookie, test_report_t* report) {
38     zx_device_t* dev = (zx_device_t*)cookie;
39 
40     test_protocol_t proto;
41     zx_status_t status = device_get_protocol(dev, ZX_PROTOCOL_TEST, &proto);
42     if (status != ZX_OK) {
43         return status;
44     }
45 
46     zx_handle_t output;
47     proto.ops->get_output_socket(proto.ctx, &output);
48     if (output != ZX_HANDLE_INVALID) {
49         unittest_set_output_function(ddk_test_output_func, &output);
50     }
51 
52     memset(report, 0, sizeof(*report));
53     update_test_report(unittest_run_one_test(test_case_ddk_metadata, TEST_ALL), report);
54     update_test_report(unittest_run_one_test(test_case_ddk_usb_request, TEST_ALL), report);
55     unittest_restore_output_function();
56     zx_handle_close(output);
57     return report->n_failed == 0 ? ZX_OK : ZX_ERR_INTERNAL;
58 }
59 
ddk_test_bind(void * ctx,zx_device_t * parent)60 zx_status_t ddk_test_bind(void* ctx, zx_device_t* parent) {
61     test_protocol_t proto;
62     zx_status_t status = device_get_protocol(parent, ZX_PROTOCOL_TEST, &proto);
63     if (status != ZX_OK) {
64         return status;
65     }
66 
67     ddk_test_dev = parent;
68     proto.ops->set_test_func(proto.ctx, &(test_func_t){ddk_test_func, parent});
69     return ZX_OK;
70 }
71