diff options
Diffstat (limited to 'extras/dispatch/tests')
-rw-r--r-- | extras/dispatch/tests/CMakeLists.txt | 34 | ||||
-rw-r--r-- | extras/dispatch/tests/alloc_test.c | 86 | ||||
-rw-r--r-- | extras/dispatch/tests/message_test.c | 119 | ||||
-rw-r--r-- | extras/dispatch/tests/run_tests.c | 36 | ||||
-rw-r--r-- | extras/dispatch/tests/server_test.c | 195 | ||||
-rw-r--r-- | extras/dispatch/tests/test_case.h | 36 | ||||
-rw-r--r-- | extras/dispatch/tests/timer_test.c | 388 | ||||
-rw-r--r-- | extras/dispatch/tests/tool_test.c | 159 |
8 files changed, 1053 insertions, 0 deletions
diff --git a/extras/dispatch/tests/CMakeLists.txt b/extras/dispatch/tests/CMakeLists.txt new file mode 100644 index 0000000000..10bf1eb43a --- /dev/null +++ b/extras/dispatch/tests/CMakeLists.txt @@ -0,0 +1,34 @@ +## +## Licensed to the Apache Software Foundation (ASF) under one +## or more contributor license agreements. See the NOTICE file +## distributed with this work for additional information +## regarding copyright ownership. The ASF licenses this file +## to you 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. +## + +## +## Build test applications +## +set(test_SOURCES + alloc_test.c + message_test.c + run_tests.c + server_test.c + timer_test.c + tool_test.c + ) + +add_executable(run_tests ${test_SOURCES}) +target_link_libraries(run_tests qpid-dispatch) + diff --git a/extras/dispatch/tests/alloc_test.c b/extras/dispatch/tests/alloc_test.c new file mode 100644 index 0000000000..2406048209 --- /dev/null +++ b/extras/dispatch/tests/alloc_test.c @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 "test_case.h" +#include <stdio.h> +#include <string.h> +#include "alloc_private.h" + +typedef struct { + int A; + int B; +} object_t; + +dx_alloc_config_t config = {3, 7, 10}; + +ALLOC_DECLARE(object_t); +ALLOC_DEFINE_CONFIG(object_t, sizeof(object_t), 0, &config); + + +static char* check_stats(dx_alloc_stats_t *stats, uint64_t ah, uint64_t fh, uint64_t ht, uint64_t rt, uint64_t rg) +{ + if (stats->total_alloc_from_heap != ah) return "Incorrect alloc-from-heap"; + if (stats->total_free_to_heap != fh) return "Incorrect free-to-heap"; + if (stats->held_by_threads != ht) return "Incorrect held-by-threads"; + if (stats->batches_rebalanced_to_threads != rt) return "Incorrect rebalance-to-threads"; + if (stats->batches_rebalanced_to_global != rg) return "Incorrect rebalance-to-global"; + return 0; +} + + +static char* test_alloc_basic(void *context) +{ + object_t *obj[50]; + int idx; + dx_alloc_stats_t *stats; + char *error; + + for (idx = 0; idx < 20; idx++) + obj[idx] = new_object_t(); + + stats = alloc_stats_object_t(); + error = check_stats(stats, 21, 0, 21, 0, 0); + if (error) return error; + + for (idx = 0; idx < 20; idx++) + free_object_t(obj[idx]); + + error = check_stats(stats, 21, 5, 6, 0, 5); + if (error) return error; + + for (idx = 0; idx < 20; idx++) + obj[idx] = new_object_t(); + + error = check_stats(stats, 27, 5, 21, 3, 5); + if (error) return error; + + return 0; +} + + +int alloc_tests(void) +{ + int result = 0; + dx_alloc_initialize(); + + TEST_CASE(test_alloc_basic, 0); + + return result; +} + diff --git a/extras/dispatch/tests/message_test.c b/extras/dispatch/tests/message_test.c new file mode 100644 index 0000000000..590b7f6ed7 --- /dev/null +++ b/extras/dispatch/tests/message_test.c @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 "test_case.h" +#include <stdio.h> +#include <string.h> +#include "message_private.h" +#include <qpid/dispatch/iterator.h> +#include <proton/message.h> + + +static char* test_send_to_messenger(void *context) +{ + dx_message_t *msg = dx_allocate_message(); + dx_message_content_t *content = MSG_CONTENT(msg); + + dx_message_compose_1(msg, "test_addr_0", 0); + dx_buffer_t *buf = DEQ_HEAD(content->buffers); + if (buf == 0) return "Expected a buffer in the test message"; + + pn_message_t *pn_msg = pn_message(); + int result = pn_message_decode(pn_msg, (const char*) dx_buffer_base(buf), dx_buffer_size(buf)); + if (result != 0) return "Error in pn_message_decode"; + + if (strcmp(pn_message_get_address(pn_msg), "test_addr_0") != 0) + return "Address mismatch in received message"; + + pn_message_free(pn_msg); + dx_free_message(msg); + + return 0; +} + + +static char* test_receive_from_messenger(void *context) +{ + pn_message_t *pn_msg = pn_message(); + pn_message_set_address(pn_msg, "test_addr_1"); + + dx_buffer_t *buf = dx_allocate_buffer(); + size_t size = dx_buffer_capacity(buf); + int result = pn_message_encode(pn_msg, (char*) dx_buffer_cursor(buf), &size); + if (result != 0) return "Error in pn_message_encode"; + dx_buffer_insert(buf, size); + + dx_message_t *msg = dx_allocate_message(); + dx_message_content_t *content = MSG_CONTENT(msg); + + DEQ_INSERT_TAIL(content->buffers, buf); + int valid = dx_message_check(msg, DX_DEPTH_ALL); + if (!valid) return "dx_message_check returns 'invalid'"; + + dx_field_iterator_t *iter = dx_message_field_iterator(msg, DX_FIELD_TO); + if (iter == 0) return "Expected an iterator for the 'to' field"; + + if (!dx_field_iterator_equal(iter, (unsigned char*) "test_addr_1")) + return "Mismatched 'to' field contents"; + + pn_message_free(pn_msg); + dx_free_message(msg); + + return 0; +} + + +static char* test_insufficient_check_depth(void *context) +{ + pn_message_t *pn_msg = pn_message(); + pn_message_set_address(pn_msg, "test_addr_2"); + + dx_buffer_t *buf = dx_allocate_buffer(); + size_t size = dx_buffer_capacity(buf); + int result = pn_message_encode(pn_msg, (char*) dx_buffer_cursor(buf), &size); + if (result != 0) return "Error in pn_message_encode"; + dx_buffer_insert(buf, size); + + dx_message_t *msg = dx_allocate_message(); + dx_message_content_t *content = MSG_CONTENT(msg); + + DEQ_INSERT_TAIL(content->buffers, buf); + int valid = dx_message_check(msg, DX_DEPTH_DELIVERY_ANNOTATIONS); + if (!valid) return "dx_message_check returns 'invalid'"; + + dx_field_iterator_t *iter = dx_message_field_iterator(msg, DX_FIELD_TO); + if (iter) return "Expected no iterator for the 'to' field"; + + dx_free_message(msg); + + return 0; +} + + +int message_tests(void) +{ + int result = 0; + + TEST_CASE(test_send_to_messenger, 0); + TEST_CASE(test_receive_from_messenger, 0); + TEST_CASE(test_insufficient_check_depth, 0); + + return result; +} + diff --git a/extras/dispatch/tests/run_tests.c b/extras/dispatch/tests/run_tests.c new file mode 100644 index 0000000000..a677c04577 --- /dev/null +++ b/extras/dispatch/tests/run_tests.c @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +int tool_tests(); +int timer_tests(); +int alloc_tests(); +int server_tests(); +int message_tests(); + +int main(int argc, char** argv) +{ + int result = 0; + result += tool_tests(); + result += timer_tests(); + result += alloc_tests(); + result += server_tests(); + result += message_tests(); + return result; +} + diff --git a/extras/dispatch/tests/server_test.c b/extras/dispatch/tests/server_test.c new file mode 100644 index 0000000000..adeab62af9 --- /dev/null +++ b/extras/dispatch/tests/server_test.c @@ -0,0 +1,195 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <assert.h> +#include <qpid/dispatch/timer.h> +#include "test_case.h" +#include <qpid/dispatch/server.h> +#include <qpid/dispatch/user_fd.h> +#include <qpid/dispatch/threading.h> +#include <qpid/dispatch/log.h> + +#define THREAD_COUNT 4 +#define OCTET_COUNT 100 + +static sys_mutex_t *test_lock; + +static void *expected_context; +static int call_count; +static int threads_seen[THREAD_COUNT]; +static char stored_error[512]; + +static int write_count; +static int read_count; +static int fd[2]; +static dx_user_fd_t *ufd_write; +static dx_user_fd_t *ufd_read; + + +static void thread_start(void *context, int thread_id) +{ + sys_mutex_lock(test_lock); + if (context != expected_context && !stored_error[0]) + sprintf(stored_error, "Unexpected Context Value: %lx", (long) context); + if (thread_id >= THREAD_COUNT && !stored_error[0]) + sprintf(stored_error, "Thread_ID too large: %d", thread_id); + if (thread_id < 0 && !stored_error[0]) + sprintf(stored_error, "Thread_ID negative: %d", thread_id); + + call_count++; + if (thread_id >= 0 && thread_id < THREAD_COUNT) + threads_seen[thread_id]++; + + if (call_count == THREAD_COUNT) + dx_server_stop(); + sys_mutex_unlock(test_lock); +} + + +static int conn_handler(void *context, dx_conn_event_t event, dx_connection_t *conn) +{ + return 0; +} + + +static void ufd_handler(void *context, dx_user_fd_t *ufd) +{ + long dir = (long) context; + char buffer; + ssize_t len; + static int in_read = 0; + static int in_write = 0; + + if (dir == 0) { // READ + in_read++; + assert(in_read == 1); + if (!dx_user_fd_is_readable(ufd_read)) { + sprintf(stored_error, "Expected Readable"); + dx_server_stop(); + } else { + len = read(fd[0], &buffer, 1); + if (len == 1) { + read_count++; + if (read_count == OCTET_COUNT) + dx_server_stop(); + } + dx_user_fd_activate_read(ufd_read); + } + in_read--; + } else { // WRITE + in_write++; + assert(in_write == 1); + if (!dx_user_fd_is_writeable(ufd_write)) { + sprintf(stored_error, "Expected Writable"); + dx_server_stop(); + } else { + write(fd[1], "X", 1); + + write_count++; + if (write_count < OCTET_COUNT) + dx_user_fd_activate_write(ufd_write); + } + in_write--; + } +} + + +static void fd_test_start(void *context) +{ + dx_user_fd_activate_read(ufd_read); +} + + +static char* test_start_handler(void *context) +{ + int i; + + dx_server_initialize(THREAD_COUNT); + + expected_context = (void*) 0x00112233; + stored_error[0] = 0x0; + call_count = 0; + for (i = 0; i < THREAD_COUNT; i++) + threads_seen[i] = 0; + + dx_server_set_conn_handler(conn_handler); + dx_server_set_start_handler(thread_start, expected_context); + dx_server_run(); + dx_server_finalize(); + + if (stored_error[0]) return stored_error; + if (call_count != THREAD_COUNT) return "Incorrect number of thread-start callbacks"; + for (i = 0; i < THREAD_COUNT; i++) + if (threads_seen[i] != 1) return "Incorrect count on one thread ID"; + + return 0; +} + + +static char* test_user_fd(void *context) +{ + int res; + dx_timer_t *timer; + + dx_server_initialize(THREAD_COUNT); + dx_server_set_conn_handler(conn_handler); + dx_server_set_user_fd_handler(ufd_handler); + timer = dx_timer(fd_test_start, 0); + dx_timer_schedule(timer, 0); + + stored_error[0] = 0x0; + res = pipe2(fd, O_NONBLOCK); + if (res != 0) return "Error creating pipe2"; + + ufd_write = dx_user_fd(fd[1], (void*) 1); + ufd_read = dx_user_fd(fd[0], (void*) 0); + + dx_server_run(); + dx_timer_free(timer); + dx_server_finalize(); + close(fd[0]); + close(fd[1]); + + if (stored_error[0]) return stored_error; + if (write_count - OCTET_COUNT > 2) sprintf(stored_error, "Excessively high Write Count: %d", write_count); + if (read_count != OCTET_COUNT) sprintf(stored_error, "Incorrect Read Count: %d", read_count);; + + if (stored_error[0]) return stored_error; + return 0; +} + + +int server_tests(void) +{ + int result = 0; + test_lock = sys_mutex(); + dx_log_set_mask(LOG_NONE); + + TEST_CASE(test_start_handler, 0); + TEST_CASE(test_user_fd, 0); + + sys_mutex_free(test_lock); + return result; +} + diff --git a/extras/dispatch/tests/test_case.h b/extras/dispatch/tests/test_case.h new file mode 100644 index 0000000000..6e36b440a5 --- /dev/null +++ b/extras/dispatch/tests/test_case.h @@ -0,0 +1,36 @@ +#ifndef _nexus_test_case_h_ +#define _nexus_test_case_h_ 1 +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +typedef char* (*testcase_t)(void *context); + +#define TEST_CASE(T,C) do { \ + char *r = T(C); \ + printf("Test Case %s.%s: ", __FUNCTION__, #T); \ + if (r) { \ + printf("FAIL: %s\n", r); \ + result++; \ + } else \ + printf("PASS\n"); \ +} while(0); + + +#endif + diff --git a/extras/dispatch/tests/timer_test.c b/extras/dispatch/tests/timer_test.c new file mode 100644 index 0000000000..3d199f2aa2 --- /dev/null +++ b/extras/dispatch/tests/timer_test.c @@ -0,0 +1,388 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 <stdio.h> +#include <qpid/dispatch/timer.h> +#include "alloc_private.h" +#include "timer_private.h" +#include "test_case.h" +#include <qpid/dispatch/threading.h> + + +static unsigned long fire_mask; +static dx_timer_list_t pending_timers; +static sys_mutex_t *lock; +static long time; +static dx_timer_t *timers[16]; + + +void dx_server_timer_pending_LH(dx_timer_t *timer) +{ + DEQ_INSERT_TAIL(pending_timers, timer); +} + + +void dx_server_timer_cancel_LH(dx_timer_t *timer) +{ + if (timer->state == TIMER_PENDING) + DEQ_REMOVE(pending_timers, timer); +} + + +static int fire_head() +{ + sys_mutex_lock(lock); + int result = DEQ_SIZE(pending_timers); + dx_timer_t *timer = DEQ_HEAD(pending_timers); + if (timer) { + DEQ_REMOVE_HEAD(pending_timers); + dx_timer_idle_LH(timer); + fire_mask |= (unsigned long) timer->context; + } + sys_mutex_unlock(lock); + return result; +} + + +static char* test_quiet(void *context) +{ + fire_mask = 0; + + sys_mutex_lock(lock); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + sys_mutex_unlock(lock); + + while(fire_head()); + + if (fire_mask != 0) + return "Expected zero timers fired"; + return 0; +} + +static char* test_immediate(void *context) +{ + while(fire_head()); + fire_mask = 0; + + dx_timer_schedule(timers[0], 0); + + if (fire_mask != 0) return "Premature firing"; + if (fire_head() > 1) return "Too many firings"; + if (fire_mask != 1) return "Incorrect fire mask"; + + return 0; +} + + +static char* test_immediate_plus_delayed(void *context) +{ + while(fire_head()); + fire_mask = 0; + + dx_timer_schedule(timers[0], 0); + dx_timer_schedule(timers[1], 5); + + if (fire_mask != 0) return "Premature firing"; + if (fire_head() > 1) return "Too many firings"; + if (fire_mask != 1) return "Incorrect fire mask 1"; + + sys_mutex_lock(lock); + dx_timer_visit_LH(time++); + time += 8; + dx_timer_visit_LH(time++); + sys_mutex_unlock(lock); + + if (fire_head() < 1) return "Delayed Failed to fire"; + if (fire_mask != 3) return "Incorrect fire mask 3"; + + return 0; +} + + +static char* test_single(void *context) +{ + while(fire_head()); + fire_mask = 0; + + dx_timer_schedule(timers[0], 2); + if (fire_head() > 0) return "Premature firing 1"; + + sys_mutex_lock(lock); + dx_timer_visit_LH(time++); + sys_mutex_unlock(lock); + if (fire_head() > 0) return "Premature firing 2"; + + sys_mutex_lock(lock); + dx_timer_visit_LH(time++); + sys_mutex_unlock(lock); + if (fire_head() < 1) return "Failed to fire"; + + sys_mutex_lock(lock); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + sys_mutex_unlock(lock); + if (fire_head() != 0) return "Spurious fires"; + + if (fire_mask != 1) return "Incorrect fire mask"; + if (timers[0]->state != TIMER_IDLE) return "Expected idle timer state"; + + return 0; +} + + +static char* test_two_inorder(void *context) +{ + while(fire_head()); + fire_mask = 0; + + dx_timer_schedule(timers[0], 2); + dx_timer_schedule(timers[1], 4); + + sys_mutex_lock(lock); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + sys_mutex_unlock(lock); + int count = fire_head(); + if (count < 1) return "First failed to fire"; + if (count > 1) return "Second fired prematurely"; + if (fire_mask != 1) return "Incorrect fire mask 1"; + + sys_mutex_lock(lock); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + sys_mutex_unlock(lock); + if (fire_head() < 1) return "Second failed to fire"; + if (fire_mask != 3) return "Incorrect fire mask 3"; + + return 0; +} + + +static char* test_two_reverse(void *context) +{ + while(fire_head()); + fire_mask = 0; + + dx_timer_schedule(timers[0], 4); + dx_timer_schedule(timers[1], 2); + + sys_mutex_lock(lock); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + sys_mutex_unlock(lock); + int count = fire_head(); + if (count < 1) return "First failed to fire"; + if (count > 1) return "Second fired prematurely"; + if (fire_mask != 2) return "Incorrect fire mask 2"; + + sys_mutex_lock(lock); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + sys_mutex_unlock(lock); + if (fire_head() < 1) return "Second failed to fire"; + if (fire_mask != 3) return "Incorrect fire mask 3"; + + return 0; +} + + +static char* test_two_duplicate(void *context) +{ + while(fire_head()); + fire_mask = 0; + + dx_timer_schedule(timers[0], 2); + dx_timer_schedule(timers[1], 2); + + sys_mutex_lock(lock); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + sys_mutex_unlock(lock); + int count = fire_head(); + if (count != 2) return "Expected two firings"; + fire_head(); + if (fire_mask != 3) return "Incorrect fire mask 3"; + + sys_mutex_lock(lock); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + sys_mutex_unlock(lock); + if (fire_head() > 0) return "Spurious timer fires"; + + return 0; +} + + +static char* test_separated(void *context) +{ + int count; + + while(fire_head()); + fire_mask = 0; + + dx_timer_schedule(timers[0], 2); + dx_timer_schedule(timers[1], 4); + + sys_mutex_lock(lock); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + sys_mutex_unlock(lock); + count = fire_head(); + if (count < 1) return "First failed to fire"; + if (count > 1) return "Second fired prematurely"; + if (fire_mask != 1) return "Incorrect fire mask 1"; + + dx_timer_schedule(timers[2], 2); + dx_timer_schedule(timers[3], 4); + + sys_mutex_lock(lock); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + sys_mutex_unlock(lock); + count = fire_head(); + fire_head(); + if (count < 1) return "Second failed to fire"; + if (count < 2) return "Third failed to fire"; + if (fire_mask != 7) return "Incorrect fire mask 7"; + + sys_mutex_lock(lock); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + sys_mutex_unlock(lock); + count = fire_head(); + if (count < 1) return "Fourth failed to fire"; + if (fire_mask != 15) return "Incorrect fire mask 15"; + + sys_mutex_lock(lock); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + dx_timer_visit_LH(time++); + sys_mutex_unlock(lock); + count = fire_head(); + if (count > 0) return "Spurious fire"; + + return 0; +} + + +static char* test_big(void *context) +{ + while(fire_head()); + fire_mask = 0; + + long durations[16] = + { 5, 8, 7, 6, + 14, 10, 16, 15, + 11, 12, 9, 12, + 1, 2, 3, 4}; + unsigned long masks[18] = { + 0x1000, + 0x3000, + 0x7000, + 0xf000, + 0xf001, + 0xf009, + 0xf00d, + 0xf00f, + 0xf40f, + 0xf42f, + 0xf52f, + 0xff2f, + 0xff2f, + 0xff3f, + 0xffbf, + 0xffff, + 0xffff, + 0xffff + }; + + int i; + for (i = 0; i < 16; i++) + dx_timer_schedule(timers[i], durations[i]); + for (i = 0; i < 18; i++) { + sys_mutex_lock(lock); + dx_timer_visit_LH(time++); + sys_mutex_unlock(lock); + while(fire_head()); + if (fire_mask != masks[i]) { + static char error[100]; + sprintf(error, "Iteration %d: expected mask %04lx, got %04lx", i, masks[i], fire_mask); + return error; + } + } + + return 0; +} + + +int timer_tests(void) +{ + int result = 0; + dx_alloc_initialize(); + + fire_mask = 0; + DEQ_INIT(pending_timers); + lock = sys_mutex(); + dx_timer_initialize(lock); + time = 1; + + timers[0] = dx_timer(0, (void*) 0x00000001); + timers[1] = dx_timer(0, (void*) 0x00000002); + timers[2] = dx_timer(0, (void*) 0x00000004); + timers[3] = dx_timer(0, (void*) 0x00000008); + timers[4] = dx_timer(0, (void*) 0x00000010); + timers[5] = dx_timer(0, (void*) 0x00000020); + timers[6] = dx_timer(0, (void*) 0x00000040); + timers[7] = dx_timer(0, (void*) 0x00000080); + timers[8] = dx_timer(0, (void*) 0x00000100); + timers[9] = dx_timer(0, (void*) 0x00000200); + timers[10] = dx_timer(0, (void*) 0x00000400); + timers[11] = dx_timer(0, (void*) 0x00000800); + timers[12] = dx_timer(0, (void*) 0x00001000); + timers[13] = dx_timer(0, (void*) 0x00002000); + timers[14] = dx_timer(0, (void*) 0x00004000); + timers[15] = dx_timer(0, (void*) 0x00008000); + + TEST_CASE(test_quiet, 0); + TEST_CASE(test_immediate, 0); + TEST_CASE(test_immediate_plus_delayed, 0); + TEST_CASE(test_single, 0); + TEST_CASE(test_two_inorder, 0); + TEST_CASE(test_two_reverse, 0); + TEST_CASE(test_two_duplicate, 0); + TEST_CASE(test_separated, 0); + TEST_CASE(test_big, 0); + + int i; + for (i = 0; i < 16; i++) + dx_timer_free(timers[i]); + + dx_timer_finalize(); + + return result; +} + diff --git a/extras/dispatch/tests/tool_test.c b/extras/dispatch/tests/tool_test.c new file mode 100644 index 0000000000..7923ee3381 --- /dev/null +++ b/extras/dispatch/tests/tool_test.c @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 "test_case.h" +#include <stdio.h> +#include <string.h> +#include <qpid/dispatch/ctools.h> + +typedef struct item_t { + DEQ_LINKS(struct item_t); + char letter; +} item_t; + +DEQ_DECLARE(item_t, item_list_t); + + +static char* list_well_formed(item_list_t list, char *key) +{ + item_t *ptr; + item_t *last = 0; + int size = DEQ_SIZE(list); + int count = 0; + char str[32]; + + ptr = DEQ_HEAD(list); + while (ptr) { + str[count] = ptr->letter; + count++; + if (DEQ_PREV(ptr) != last) return "Corrupt previous link"; + last = ptr; + ptr = DEQ_NEXT(ptr); + } + str[count] = '\0'; + if (strcmp(str, key) != 0) return "Invalid key"; + + if (count != size) return "Size different from number of items (forward)"; + + count = 0; + last = 0; + ptr = DEQ_TAIL(list); + while (ptr) { + count++; + if (DEQ_NEXT(ptr) != last) return "Corrupt next link"; + last = ptr; + ptr = DEQ_PREV(ptr); + } + + if (count != size) return "Size different from number of items (backward)"; + + return 0; +} + + +static char* test_deq_basic(void *context) +{ + item_list_t list; + item_t item[10]; + item_t *ptr; + int idx; + char *subtest; + + DEQ_INIT(list); + if (DEQ_SIZE(list) != 0) return "Expected zero initial size"; + + for (idx = 0; idx < 10; idx++) { + DEQ_ITEM_INIT(&item[idx]); + item[idx].letter = 'A' + idx; + DEQ_INSERT_TAIL(list, &item[idx]); + } + if (DEQ_SIZE(list) != 10) return "Expected 10 items in list"; + + ptr = DEQ_HEAD(list); + if (!ptr) return "Expected valid head item"; + if (DEQ_PREV(ptr)) return "Head item has non-null previous link"; + if (ptr->letter != 'A') return "Expected item A at the head"; + if (DEQ_NEXT(ptr) == 0) return "Head item has null next link"; + subtest = list_well_formed(list, "ABCDEFGHIJ"); + if (subtest) return subtest; + + DEQ_REMOVE_HEAD(list); + if (DEQ_SIZE(list) != 9) return "Expected 9 items in list"; + ptr = DEQ_HEAD(list); + if (ptr->letter != 'B') return "Expected item B at the head"; + subtest = list_well_formed(list, "BCDEFGHIJ"); + if (subtest) return subtest; + + DEQ_REMOVE_TAIL(list); + if (DEQ_SIZE(list) != 8) return "Expected 8 items in list"; + ptr = DEQ_TAIL(list); + if (ptr->letter != 'I') return "Expected item I at the tail"; + subtest = list_well_formed(list, "BCDEFGHI"); + if (subtest) return subtest; + + DEQ_REMOVE(list, &item[4]); + if (DEQ_SIZE(list) != 7) return "Expected 7 items in list"; + subtest = list_well_formed(list, "BCDFGHI"); + if (subtest) return subtest; + + DEQ_REMOVE(list, &item[1]); + if (DEQ_SIZE(list) != 6) return "Expected 6 items in list"; + subtest = list_well_formed(list, "CDFGHI"); + if (subtest) return subtest; + + DEQ_REMOVE(list, &item[8]); + if (DEQ_SIZE(list) != 5) return "Expected 5 items in list"; + subtest = list_well_formed(list, "CDFGH"); + if (subtest) return subtest; + + DEQ_INSERT_HEAD(list, &item[8]); + if (DEQ_SIZE(list) != 6) return "Expected 6 items in list"; + ptr = DEQ_HEAD(list); + if (ptr->letter != 'I') return "Expected item I at the head"; + subtest = list_well_formed(list, "ICDFGH"); + if (subtest) return subtest; + + DEQ_INSERT_AFTER(list, &item[4], &item[7]); + if (DEQ_SIZE(list) != 7) return "Expected 7 items in list"; + ptr = DEQ_TAIL(list); + if (ptr->letter != 'E') return "Expected item E at the head"; + subtest = list_well_formed(list, "ICDFGHE"); + if (subtest) return subtest; + + DEQ_INSERT_AFTER(list, &item[1], &item[5]); + if (DEQ_SIZE(list) != 8) return "Expected 8 items in list"; + subtest = list_well_formed(list, "ICDFBGHE"); + if (subtest) return subtest; + + if (item[0].prev || item[0].next) return "Unlisted item A has non-null pointers"; + if (item[9].prev || item[9].next) return "Unlisted item J has non-null pointers"; + + return 0; +} + + +int tool_tests(void) +{ + int result = 0; + + TEST_CASE(test_deq_basic, 0); + + return result; +} + |