diff --git a/TESTS/netsocket/dns/asynchronous_dns.cpp b/TESTS/netsocket/dns/asynchronous_dns.cpp new file mode 100644 index 0000000000..8dcac3c65c --- /dev/null +++ b/TESTS/netsocket/dns/asynchronous_dns.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "dns_tests.h" + +using namespace utest::v1; + +namespace { +int result_ok; +int result_no_mem; +int result_dns_failure; +int result_exp_timeout; +} + +void ASYNCHRONOUS_DNS() +{ + do_asynchronous_gethostbyname(dns_test_hosts, 1, &result_ok, &result_no_mem, &result_dns_failure, &result_exp_timeout); + + TEST_ASSERT(result_ok == 1); + TEST_ASSERT(result_no_mem == 0); + TEST_ASSERT(result_dns_failure == 0); + TEST_ASSERT(result_exp_timeout == 0); +} diff --git a/TESTS/netsocket/dns/asynchronous_dns_cache.cpp b/TESTS/netsocket/dns/asynchronous_dns_cache.cpp new file mode 100644 index 0000000000..70283cbae9 --- /dev/null +++ b/TESTS/netsocket/dns/asynchronous_dns_cache.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "dns_tests.h" + +using namespace utest::v1; + +namespace { +int ticker_us = 0; +} + +static void test_dns_query_ticker(void) +{ + ticker_us += 100; +} + +void ASYNCHRONOUS_DNS_CACHE() +{ + rtos::Semaphore semaphore; + dns_application_data data; + data.semaphore = &semaphore; + + Ticker ticker; + ticker.attach_us(&test_dns_query_ticker, 100); + + for (unsigned int i = 0; i < 5; i++) { + int started_us = ticker_us; + + nsapi_error_t err = get_interface()->gethostbyname_async(dns_test_hosts[0], + mbed::Callback(hostbyname_cb, (void *) &data)); + TEST_ASSERT(err >= 0); + + semaphore.wait(); + + TEST_ASSERT(data.result == NSAPI_ERROR_OK); + TEST_ASSERT(strlen(data.addr.get_ip_address()) > 1); + + int delay_ms = (ticker_us - started_us) / 1000; + + static int delay_first = delay_ms / 2; + // Check that cached accesses are at least twice as fast as the first one + TEST_ASSERT_FALSE(i != 0 && delay_ms > delay_first); + + printf("DNS: query \"%s\" => \"%s\", time %i ms\n", + dns_test_hosts[0], data.addr.get_ip_address(), delay_ms); + } +} diff --git a/TESTS/netsocket/dns/asynchronous_dns_cancel.cpp b/TESTS/netsocket/dns/asynchronous_dns_cancel.cpp new file mode 100644 index 0000000000..2c866cf6f7 --- /dev/null +++ b/TESTS/netsocket/dns/asynchronous_dns_cancel.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "dns_tests.h" + +using namespace utest::v1; + +void ASYNCHRONOUS_DNS_CANCEL() +{ + rtos::Semaphore semaphore; + dns_application_data *data = new dns_application_data[MBED_CONF_APP_DNS_TEST_HOSTS_NUM]; + + int count = 0; + + for (unsigned int i = 0; i < MBED_CONF_APP_DNS_TEST_HOSTS_NUM; i++) { + data[i].value_set = false; + data[i].semaphore = &semaphore; + data[i].req_result = get_interface()->gethostbyname_async(dns_test_hosts[i], + mbed::Callback(hostbyname_cb, (void *) &data[i])); + TEST_ASSERT(data[i].req_result >= 0 || data[i].req_result == NSAPI_ERROR_NO_MEMORY); + + if (data[i].req_result >= 0) { + // Callback will be called + count++; + } else { + // No memory to initiate DNS query, callback will not be called + data[i].result = NSAPI_ERROR_NO_MEMORY; + data[i].value_set = true; + } + } + + for (unsigned int i = 0; i < MBED_CONF_APP_DNS_TEST_HOSTS_NUM; i++) { + if (data[i].req_result > 0) { + if (get_interface()->gethostbyname_async_cancel(data[i].req_result) == NSAPI_ERROR_OK) { + count--; + } + } + } + + // Wait for callback(s) to complete + for (int i = 0; i < count; i++) { + semaphore.wait(); + } + + for (unsigned int i = 0; i < MBED_CONF_APP_DNS_TEST_HOSTS_NUM; i++) { + if (!data[i].value_set) { + printf("DNS: query \"%s\" => cancel\n", dns_test_hosts[i]); + continue; + } + TEST_ASSERT(data[i].result == NSAPI_ERROR_OK || data[i].result == NSAPI_ERROR_NO_MEMORY || data[i].result == NSAPI_ERROR_DNS_FAILURE || data[i].result == NSAPI_ERROR_TIMEOUT); + if (data[i].result == NSAPI_ERROR_OK) { + printf("DNS: query \"%s\" => \"%s\"\n", + dns_test_hosts[i], data[i].addr.get_ip_address()); + } else if (data[i].result == NSAPI_ERROR_DNS_FAILURE) { + printf("DNS: query \"%s\" => DNS failure\n", dns_test_hosts[i]); + } else if (data[i].result == NSAPI_ERROR_TIMEOUT) { + printf("DNS: query \"%s\" => timeout\n", dns_test_hosts[i]); + } else if (data[i].result == NSAPI_ERROR_NO_MEMORY) { + printf("DNS: query \"%s\" => no memory\n", dns_test_hosts[i]); + } + } + + delete[] data; + + wait(5.0); +} diff --git a/TESTS/netsocket/dns/asynchronous_dns_external_event_queue.cpp b/TESTS/netsocket/dns/asynchronous_dns_external_event_queue.cpp new file mode 100644 index 0000000000..11291f5e93 --- /dev/null +++ b/TESTS/netsocket/dns/asynchronous_dns_external_event_queue.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "dns_tests.h" + +#include "nsapi_dns.h" + +using namespace utest::v1; + +namespace { +int result_ok; +int result_no_mem; +int result_dns_failure; +int result_exp_timeout; + +const int EXTERNAL_THREAD_SIZE = 2048; +const int EVENT_QUEUE_SIZE = 10; + +events::EventQueue *event_queue; +} + +static nsapi_error_t event_queue_call(int delay, mbed::Callback func) +{ + if (delay) { + if (event_queue->call_in(delay, func) == 0) { + return NSAPI_ERROR_NO_MEMORY; + } + } else { + if (event_queue->call(func) == 0) { + return NSAPI_ERROR_NO_MEMORY; + } + } + return NSAPI_ERROR_OK; +} + +void ASYNCHRONOUS_DNS_EXTERNAL_EVENT_QUEUE() +{ + // Ensures that cache does not contain entries + do_asynchronous_gethostbyname(dns_test_hosts, MBED_CONF_NSAPI_DNS_CACHE_SIZE, &result_ok, &result_no_mem, + &result_dns_failure, &result_exp_timeout); + + TEST_ASSERT(result_ok == MBED_CONF_NSAPI_DNS_CACHE_SIZE); + TEST_ASSERT(result_no_mem == 0); + TEST_ASSERT(result_dns_failure == 0); + TEST_ASSERT(result_exp_timeout == 0); + + // Dispatch event queue + Thread eventThread(osPriorityNormal, EXTERNAL_THREAD_SIZE); + EventQueue queue(EVENT_QUEUE_SIZE * EVENTS_EVENT_SIZE); + eventThread.start(callback(&queue, &EventQueue::dispatch_forever)); + event_queue = &queue; + + nsapi_dns_call_in_set(event_queue_call); + + do_asynchronous_gethostbyname(dns_test_hosts_second, MBED_CONF_APP_DNS_SIMULT_QUERIES + 1, &result_ok, &result_no_mem, + &result_dns_failure, &result_exp_timeout); + + TEST_ASSERT(result_ok == MBED_CONF_APP_DNS_SIMULT_QUERIES); + TEST_ASSERT(result_no_mem == 1); // last query fails for no memory as expected + TEST_ASSERT(result_dns_failure == 0); + TEST_ASSERT(result_exp_timeout == 0); + + // Give event queue time to finalise before destructors + wait(2.0); + + nsapi_dns_call_in_set(0); +} diff --git a/TESTS/netsocket/dns/asynchronous_dns_invalid_host.cpp b/TESTS/netsocket/dns/asynchronous_dns_invalid_host.cpp new file mode 100644 index 0000000000..57780b26ef --- /dev/null +++ b/TESTS/netsocket/dns/asynchronous_dns_invalid_host.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "dns_tests.h" + +using namespace utest::v1; + +namespace { +int result_ok; +int result_no_mem; +int result_dns_failure; +int result_exp_timeout; +} + +void ASYNCHRONOUS_DNS_INVALID_HOST() +{ + // Ensures that cache does not contain entries + do_asynchronous_gethostbyname(dns_test_hosts_second, MBED_CONF_NSAPI_DNS_CACHE_SIZE, &result_ok, &result_no_mem, + &result_dns_failure, &result_exp_timeout); + + char dns_test_hosts_new[MBED_CONF_APP_DNS_TEST_HOSTS_NUM][DNS_TEST_HOST_LEN]; + memcpy(dns_test_hosts_new, dns_test_hosts, sizeof(dns_test_hosts_new)); + + int exp_dns_failure = 0; + int exp_ok = 0; + + // Invalidate 1st and 3th etc. entries + for (unsigned int i = 0; i < MBED_CONF_APP_DNS_SIMULT_QUERIES + 1; i++) { + if ((i % 2) == 0) { + // Last query fails to no memory so do not increase + if (i != MBED_CONF_APP_DNS_SIMULT_QUERIES) { + exp_dns_failure++; + } + strcat(&(dns_test_hosts_new[i][0]), "_invalid"); + } else { + // Last query fails to no memory so do not increase + if (i != MBED_CONF_APP_DNS_SIMULT_QUERIES) { + exp_ok++; + } + } + } + + do_asynchronous_gethostbyname(dns_test_hosts_new, MBED_CONF_APP_DNS_SIMULT_QUERIES + 1, &result_ok, &result_no_mem, + &result_dns_failure, &result_exp_timeout); + + TEST_ASSERT(result_ok == exp_ok); + TEST_ASSERT(result_no_mem == 1); // last query fails for no memory as expected + TEST_ASSERT(result_dns_failure == exp_dns_failure || result_dns_failure == exp_dns_failure + 1); + TEST_ASSERT(result_exp_timeout == 0); +} diff --git a/TESTS/netsocket/dns/asynchronous_dns_non_async_and_async.cpp b/TESTS/netsocket/dns/asynchronous_dns_non_async_and_async.cpp new file mode 100644 index 0000000000..37831b511b --- /dev/null +++ b/TESTS/netsocket/dns/asynchronous_dns_non_async_and_async.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "dns_tests.h" + +using namespace utest::v1; + +void ASYNCHRONOUS_DNS_NON_ASYNC_AND_ASYNC() +{ + rtos::Semaphore semaphore; + dns_application_data data; + data.semaphore = &semaphore; + + // Initiate + nsapi_error_t err = get_interface()->gethostbyname_async(dns_test_hosts_second[0], + mbed::Callback(hostbyname_cb, (void *) &data)); + TEST_ASSERT(err >= 0); + + for (unsigned int i = 0; i < MBED_CONF_APP_DNS_TEST_HOSTS_NUM; i++) { + SocketAddress addr; + int err = get_interface()->gethostbyname(dns_test_hosts[i], &addr); + printf("DNS: query \"%s\" => \"%s\"\n", + dns_test_hosts[i], addr.get_ip_address()); + + TEST_ASSERT_EQUAL(0, err); + TEST_ASSERT((bool)addr); + TEST_ASSERT(strlen(addr.get_ip_address()) > 1); + } + + semaphore.wait(); + + TEST_ASSERT(data.result == NSAPI_ERROR_OK); + + printf("DNS: query \"%s\" => \"%s\"\n", + dns_test_hosts_second[0], data.addr.get_ip_address()); + + TEST_ASSERT(strlen(data.addr.get_ip_address()) > 1); +} diff --git a/TESTS/netsocket/dns/asynchronous_dns_simultaneous.cpp b/TESTS/netsocket/dns/asynchronous_dns_simultaneous.cpp new file mode 100644 index 0000000000..ae99074570 --- /dev/null +++ b/TESTS/netsocket/dns/asynchronous_dns_simultaneous.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "dns_tests.h" + +using namespace utest::v1; + +namespace { +int result_ok; +int result_no_mem; +int result_dns_failure; +int result_exp_timeout; +} + +void ASYNCHRONOUS_DNS_SIMULTANEOUS() +{ + do_asynchronous_gethostbyname(dns_test_hosts_second, MBED_CONF_APP_DNS_SIMULT_QUERIES + 1, &result_ok, &result_no_mem, + &result_dns_failure, &result_exp_timeout); + + TEST_ASSERT(result_ok == MBED_CONF_APP_DNS_SIMULT_QUERIES); + TEST_ASSERT(result_no_mem == 1); // last query fails for no memory as expected + TEST_ASSERT(result_dns_failure == 0); + TEST_ASSERT(result_exp_timeout == 0); +} diff --git a/TESTS/netsocket/dns/asynchronous_dns_simultaneous_cache.cpp b/TESTS/netsocket/dns/asynchronous_dns_simultaneous_cache.cpp new file mode 100644 index 0000000000..3fef74aa55 --- /dev/null +++ b/TESTS/netsocket/dns/asynchronous_dns_simultaneous_cache.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "dns_tests.h" + +using namespace utest::v1; + +namespace { +int result_ok; +int result_no_mem; +int result_dns_failure; +int result_exp_timeout; +} + +void ASYNCHRONOUS_DNS_SIMULTANEOUS_CACHE() +{ + do_asynchronous_gethostbyname(dns_test_hosts_second, MBED_CONF_APP_DNS_SIMULT_QUERIES + 1, &result_ok, &result_no_mem, + &result_dns_failure, &result_exp_timeout); + + // Addresses were cached on last step, OK for all + TEST_ASSERT(result_ok == MBED_CONF_APP_DNS_SIMULT_QUERIES + 1); + TEST_ASSERT(result_no_mem == 0); + TEST_ASSERT(result_dns_failure == 0); + TEST_ASSERT(result_exp_timeout == 0); +} diff --git a/TESTS/netsocket/dns/asynchronous_dns_simultaneous_repeat.cpp b/TESTS/netsocket/dns/asynchronous_dns_simultaneous_repeat.cpp new file mode 100644 index 0000000000..98c8dcb685 --- /dev/null +++ b/TESTS/netsocket/dns/asynchronous_dns_simultaneous_repeat.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "dns_tests.h" + +using namespace utest::v1; + +namespace { +int result_ok; +int result_no_mem; +int result_dns_failure; +int result_exp_timeout; +} + +void ASYNCHRONOUS_DNS_SIMULTANEOUS_REPEAT() +{ + + for (int i = 0; i < 100; i++) { + do_asynchronous_gethostbyname(dns_test_hosts, MBED_CONF_APP_DNS_SIMULT_QUERIES + 1, &result_ok, &result_no_mem, + &result_dns_failure, &result_exp_timeout); + + // For 1st round can fail to no memory, on other rounds some of the addresses are found from cache + TEST_ASSERT(result_ok == MBED_CONF_APP_DNS_SIMULT_QUERIES || result_ok == MBED_CONF_APP_DNS_SIMULT_QUERIES + 1); + TEST_ASSERT(result_no_mem == 1 || result_no_mem == 0); // last query fails for 1st round to no memory as expected + TEST_ASSERT(result_dns_failure == 0); + TEST_ASSERT(result_exp_timeout == 0); + } +} diff --git a/TESTS/netsocket/dns/asynchronous_dns_timeouts.cpp b/TESTS/netsocket/dns/asynchronous_dns_timeouts.cpp new file mode 100644 index 0000000000..37401df1e9 --- /dev/null +++ b/TESTS/netsocket/dns/asynchronous_dns_timeouts.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "dns_tests.h" + +#include "nsapi_dns.h" + +using namespace utest::v1; + +namespace { +int result_ok; +int result_no_mem; +int result_dns_failure; +int result_exp_timeout; + +const int EXTERNAL_THREAD_SIZE = 2048; +const int EVENT_QUEUE_SIZE = 10; + +events::EventQueue *event_queue; +} + +static nsapi_error_t event_queue_call(int delay, mbed::Callback func) +{ + // Run event queue without delays + if (event_queue->call(func) == 0) { + return NSAPI_ERROR_NO_MEMORY; + } + + return NSAPI_ERROR_OK; +} + +void ASYNCHRONOUS_DNS_TIMEOUTS() +{ + // Ensures that cache does not contain entries + do_asynchronous_gethostbyname(dns_test_hosts, MBED_CONF_NSAPI_DNS_CACHE_SIZE, &result_ok, &result_no_mem, + &result_dns_failure, &result_exp_timeout); + + TEST_ASSERT(result_ok == MBED_CONF_NSAPI_DNS_CACHE_SIZE); + TEST_ASSERT(result_no_mem == 0); + TEST_ASSERT(result_dns_failure == 0); + TEST_ASSERT(result_exp_timeout == 0); + + // Dispatch event queue + Thread eventThread(osPriorityNormal, EXTERNAL_THREAD_SIZE); + EventQueue queue(EVENT_QUEUE_SIZE * EVENTS_EVENT_SIZE); + eventThread.start(callback(&queue, &EventQueue::dispatch_forever)); + event_queue = &queue; + + // Set event queue callback to test specific one + nsapi_dns_call_in_set(event_queue_call); + + do_asynchronous_gethostbyname(dns_test_hosts_second, MBED_CONF_APP_DNS_SIMULT_QUERIES + 1, &result_ok, &result_no_mem, + &result_dns_failure, &result_exp_timeout); + + // Depends on timing, but at least one operation shall fail to timeout + TEST_ASSERT(result_exp_timeout > 0); + + // Give event queue time to finalise before destructors + wait(2.0); + + nsapi_dns_call_in_set(0); +} diff --git a/TESTS/netsocket/dns/dns_tests.h b/TESTS/netsocket/dns/dns_tests.h new file mode 100644 index 0000000000..f393560011 --- /dev/null +++ b/TESTS/netsocket/dns/dns_tests.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ + +#ifndef DNS_TESTS_H +#define DNS_TESTS_H + +#ifndef MBED_CONF_APP_DNS_SIMULT_QUERIES +#define MBED_CONF_APP_DNS_SIMULT_QUERIES 5 +#endif + +#ifndef MBED_CONF_NSAPI_DNS_CACHE_SIZE +#define MBED_CONF_NSAPI_DNS_CACHE_SIZE 3 +#endif + +// Hostnames for testing against +// Both lists must have A and AAAA records +#ifndef MBED_CONF_APP_DNS_TEST_HOSTS +#define MBED_CONF_APP_DNS_TEST_HOSTS {"google.com", "youtube.com", "facebook.com", "wikipedia.org", "yahoo.com", "instagram.com"} +#endif + +#ifndef MBED_CONF_APP_DNS_TEST_HOSTS_SECOND +#define MBED_CONF_APP_DNS_TEST_HOSTS_SECOND {"ipv6ready.org", "wireshark.org", "bbc.co.uk", "cnn.com", "www.flickr.com", "www.mozilla.org"} +#endif + +#ifndef MBED_CONF_APP_DNS_TEST_HOSTS_NUM +#define MBED_CONF_APP_DNS_TEST_HOSTS_NUM 6 +#endif + +#define DNS_TEST_HOST_LEN 40 + +struct dns_application_data { + rtos::Semaphore *semaphore; + nsapi_error_t result; + SocketAddress addr; + nsapi_error_t req_result; + bool value_set; +}; + +extern const char dns_test_hosts[MBED_CONF_APP_DNS_TEST_HOSTS_NUM][DNS_TEST_HOST_LEN]; +extern const char dns_test_hosts_second[MBED_CONF_APP_DNS_TEST_HOSTS_NUM][DNS_TEST_HOST_LEN]; + +/* + * Utility functions + */ +NetworkInterface *get_interface(); +void hostbyname_cb(void *data, nsapi_error_t result, SocketAddress *address); +void do_asynchronous_gethostbyname(const char hosts[][DNS_TEST_HOST_LEN], unsigned int op_count, int *exp_ok, int *exp_no_mem, int *exp_dns_failure, int *exp_timeout); + +/* + * Test cases + */ +void ASYNCHRONOUS_DNS(); +void ASYNCHRONOUS_DNS_SIMULTANEOUS(); +void ASYNCHRONOUS_DNS_SIMULTANEOUS_CACHE(); +void ASYNCHRONOUS_DNS_CACHE(); +void ASYNCHRONOUS_DNS_NON_ASYNC_AND_ASYNC(); +void ASYNCHRONOUS_DNS_CANCEL(); +void ASYNCHRONOUS_DNS_EXTERNAL_EVENT_QUEUE(); +void ASYNCHRONOUS_DNS_INVALID_HOST(); +void ASYNCHRONOUS_DNS_TIMEOUTS(); +void ASYNCHRONOUS_DNS_SIMULTANEOUS_REPEAT(); + +#endif diff --git a/TESTS/netsocket/dns/main.cpp b/TESTS/netsocket/dns/main.cpp new file mode 100644 index 0000000000..9dee6b2d99 --- /dev/null +++ b/TESTS/netsocket/dns/main.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ + +#ifndef MBED_CONF_APP_CONNECT_STATEMENT +#error [NOT_SUPPORTED] No network configuration found for this target. +#endif + +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "nsapi_dns.h" +#include "EventQueue.h" +#include "dns_tests.h" + +#include MBED_CONF_APP_HEADER_FILE + +using namespace utest::v1; + +namespace { +NetworkInterface *net; +} + +const char dns_test_hosts[MBED_CONF_APP_DNS_TEST_HOSTS_NUM][DNS_TEST_HOST_LEN] = MBED_CONF_APP_DNS_TEST_HOSTS; +const char dns_test_hosts_second[MBED_CONF_APP_DNS_TEST_HOSTS_NUM][DNS_TEST_HOST_LEN] = MBED_CONF_APP_DNS_TEST_HOSTS_SECOND; + +// Callback used for asynchronous DNS result +void hostbyname_cb(void *data, nsapi_error_t result, SocketAddress *address) +{ + dns_application_data *app_data = static_cast(data); + app_data->result = result; + if (address) { + app_data->addr = *address; + } + app_data->semaphore->release(); + app_data->value_set = true; +} + +// General function to do asynchronous DNS host name resolution +void do_asynchronous_gethostbyname(const char hosts[][DNS_TEST_HOST_LEN], unsigned int op_count, int *exp_ok, int *exp_no_mem, int *exp_dns_failure, int *exp_timeout) +{ + // Verify that there is enough hosts in the host list + TEST_ASSERT(op_count <= MBED_CONF_APP_DNS_TEST_HOSTS_NUM) + + // Reset counters + (*exp_ok) = 0; + (*exp_no_mem) = 0; + (*exp_dns_failure) = 0; + (*exp_timeout) = 0; + + // Create callback semaphore and data + rtos::Semaphore semaphore; + dns_application_data *data = new dns_application_data[op_count]; + + unsigned int count = 0; + for (unsigned int i = 0; i < op_count; i++) { + data[i].semaphore = &semaphore; + nsapi_error_t err = net->gethostbyname_async(hosts[i], mbed::Callback(hostbyname_cb, (void *) &data[i])); + TEST_ASSERT(err >= 0 || err == NSAPI_ERROR_NO_MEMORY); + if (err >= 0) { + // Callback will be called + count++; + } else { + // No memory to initiate DNS query, callback will not be called + data[i].result = NSAPI_ERROR_NO_MEMORY; + } + } + + // Wait for callback(s) to complete + for (unsigned int i = 0; i < count; i++) { + semaphore.wait(); + } + + // Print result + for (unsigned int i = 0; i < op_count; i++) { + TEST_ASSERT(data[i].result == NSAPI_ERROR_OK || data[i].result == NSAPI_ERROR_NO_MEMORY || data[i].result == NSAPI_ERROR_DNS_FAILURE || data[i].result == NSAPI_ERROR_TIMEOUT); + if (data[i].result == NSAPI_ERROR_OK) { + (*exp_ok)++; + printf("DNS: query \"%s\" => \"%s\"\n", + hosts[i], data[i].addr.get_ip_address()); + } else if (data[i].result == NSAPI_ERROR_DNS_FAILURE) { + (*exp_dns_failure)++; + printf("DNS: query \"%s\" => DNS failure\n", hosts[i]); + } else if (data[i].result == NSAPI_ERROR_TIMEOUT) { + (*exp_timeout)++; + printf("DNS: query \"%s\" => timeout\n", hosts[i]); + } else if (data[i].result == NSAPI_ERROR_NO_MEMORY) { + (*exp_no_mem)++; + printf("DNS: query \"%s\" => no memory\n", hosts[i]); + } + } + + delete[] data; +} + +NetworkInterface *get_interface() +{ + return net; +} + +static void net_bringup() +{ + MBED_ASSERT(MBED_CONF_APP_DNS_TEST_HOSTS_NUM >= MBED_CONF_NSAPI_DNS_CACHE_SIZE && MBED_CONF_APP_DNS_TEST_HOSTS_NUM >= MBED_CONF_APP_DNS_SIMULT_QUERIES + 1); + + net = MBED_CONF_APP_OBJECT_CONSTRUCTION; + int err = MBED_CONF_APP_CONNECT_STATEMENT; + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: Connected to network\n"); + printf("MBED: IP Address: %s\n", net->get_ip_address()); +} + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(120, "default_auto"); + net_bringup(); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("ASYNCHRONOUS_DNS", ASYNCHRONOUS_DNS), + Case("ASYNCHRONOUS_DNS_SIMULTANEOUS", ASYNCHRONOUS_DNS_SIMULTANEOUS), + Case("ASYNCHRONOUS_DNS_SIMULTANEOUS_CACHE", ASYNCHRONOUS_DNS_SIMULTANEOUS_CACHE), + Case("ASYNCHRONOUS_DNS_CACHE", ASYNCHRONOUS_DNS_CACHE), + Case("ASYNCHRONOUS_DNS_NON_ASYNC_AND_ASYNC", ASYNCHRONOUS_DNS_NON_ASYNC_AND_ASYNC), + Case("ASYNCHRONOUS_DNS_CANCEL", ASYNCHRONOUS_DNS_CANCEL), + Case("ASYNCHRONOUS_DNS_EXTERNAL_EVENT_QUEUE", ASYNCHRONOUS_DNS_EXTERNAL_EVENT_QUEUE), + Case("ASYNCHRONOUS_DNS_INVALID_HOST", ASYNCHRONOUS_DNS_INVALID_HOST), + Case("ASYNCHRONOUS_DNS_TIMEOUTS", ASYNCHRONOUS_DNS_TIMEOUTS), + Case("ASYNCHRONOUS_DNS_SIMULTANEOUS_REPEAT", ASYNCHRONOUS_DNS_SIMULTANEOUS_REPEAT), +}; + +Specification specification(test_setup, cases); + +int main() +{ + return !Harness::run(specification); +}