mirror of
https://github.com/google/pebble.git
synced 2025-03-22 03:32:20 +00:00
519 lines
20 KiB
C
519 lines
20 KiB
C
|
/*
|
||
|
* Copyright 2024 Google LLC
|
||
|
*
|
||
|
* 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 "clar.h"
|
||
|
|
||
|
#include "applib/ui/recognizer/recognizer.h"
|
||
|
#include "applib/ui/recognizer/recognizer_impl.h"
|
||
|
#include "applib/ui/recognizer/recognizer_manager.h"
|
||
|
#include "applib/ui/recognizer/recognizer_private.h"
|
||
|
#include "util/size.h"
|
||
|
|
||
|
// Stubs
|
||
|
#include "stubs_passert.h"
|
||
|
#include "stubs_pbl_malloc.h"
|
||
|
#include "stubs_logging.h"
|
||
|
#include "test_recognizer_impl.h"
|
||
|
|
||
|
static bool s_manager_state_change = false;
|
||
|
void recognizer_manager_handle_state_change(RecognizerManager *manager, Recognizer *changed) {
|
||
|
s_manager_state_change = true;
|
||
|
}
|
||
|
|
||
|
static TestImplData s_test_impl_data;
|
||
|
|
||
|
// setup and teardown
|
||
|
void test_recognizer__initialize(void) {
|
||
|
s_test_impl_data = (TestImplData) {};
|
||
|
}
|
||
|
|
||
|
void test_recognizer__cleanup(void) {
|
||
|
|
||
|
}
|
||
|
|
||
|
// tests
|
||
|
void test_recognizer__create_with_data(void) {
|
||
|
int sub_data;
|
||
|
void *dummy = &sub_data;
|
||
|
RecognizerImpl s_test_impl = {
|
||
|
.handle_touch_event = dummy,
|
||
|
.cancel = dummy,
|
||
|
.reset = dummy
|
||
|
};
|
||
|
Recognizer *r = recognizer_create_with_data(&s_test_impl, &s_test_impl_data,
|
||
|
sizeof(s_test_impl_data), dummy,
|
||
|
&sub_data);
|
||
|
cl_assert(r != NULL);
|
||
|
cl_assert_equal_p(r->impl, &s_test_impl);
|
||
|
cl_assert_equal_m(r->impl_data, &s_test_impl_data, sizeof(s_test_impl_data));
|
||
|
cl_assert_equal_p(r->subscriber.event, dummy);
|
||
|
cl_assert_equal_p(r->subscriber.data, &sub_data);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Possible);
|
||
|
cl_assert_equal_i(r->flags, 0);
|
||
|
cl_assert_equal_p(r->simultaneous_with_cb, NULL);
|
||
|
cl_assert_equal_p(r->fail_after, NULL);
|
||
|
|
||
|
cl_assert_passert(recognizer_create_with_data(NULL, &s_test_impl_data,
|
||
|
sizeof(s_test_impl_data), dummy,
|
||
|
NULL));
|
||
|
cl_assert_passert(recognizer_create_with_data(&s_test_impl, NULL,
|
||
|
sizeof(s_test_impl_data), dummy,
|
||
|
NULL));
|
||
|
cl_assert_passert(recognizer_create_with_data(&s_test_impl, &s_test_impl_data,
|
||
|
0, dummy, NULL));
|
||
|
cl_assert_equal_p(NULL, recognizer_create_with_data(&s_test_impl, &s_test_impl_data,
|
||
|
sizeof(s_test_impl_data), NULL, NULL));
|
||
|
s_test_impl.handle_touch_event = NULL;
|
||
|
cl_assert_passert(recognizer_create_with_data(&s_test_impl, &s_test_impl_data,
|
||
|
sizeof(s_test_impl_data), dummy,
|
||
|
NULL));
|
||
|
s_test_impl.handle_touch_event = dummy;
|
||
|
s_test_impl.reset = NULL;
|
||
|
cl_assert_passert(recognizer_create_with_data(&s_test_impl, &s_test_impl_data,
|
||
|
sizeof(s_test_impl_data), dummy,
|
||
|
NULL));
|
||
|
s_test_impl.reset = dummy;
|
||
|
s_test_impl.cancel = NULL;
|
||
|
cl_assert_passert(recognizer_create_with_data(&s_test_impl, &s_test_impl_data,
|
||
|
sizeof(s_test_impl_data), dummy,
|
||
|
NULL));
|
||
|
|
||
|
recognizer_destroy(r);
|
||
|
}
|
||
|
|
||
|
void test_recognizer__transition_state(void) {
|
||
|
RecognizerEvent event_type = -1;
|
||
|
NEW_RECOGNIZER(r) = test_recognizer_create(&s_test_impl_data, &event_type);
|
||
|
// Test that manager state change handler is called when not called from a touch event handler
|
||
|
recognizer_transition_state(r, RecognizerState_Failed);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Failed);
|
||
|
cl_assert(s_manager_state_change);
|
||
|
cl_assert_equal_i(event_type, -1);
|
||
|
|
||
|
r->state = RecognizerState_Possible;
|
||
|
s_manager_state_change = false;
|
||
|
recognizer_transition_state(r, RecognizerState_Completed);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Completed);
|
||
|
cl_assert(s_manager_state_change);
|
||
|
cl_assert_equal_i(event_type, RecognizerEvent_Completed);
|
||
|
|
||
|
s_manager_state_change = false;
|
||
|
r->handling_touch_event = true;
|
||
|
r->state = RecognizerState_Possible;
|
||
|
event_type = -1;
|
||
|
recognizer_transition_state(r, RecognizerState_Failed);
|
||
|
cl_assert(!s_manager_state_change);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Failed);
|
||
|
cl_assert_equal_i(event_type, -1);
|
||
|
|
||
|
// Test that invalid state transitions get caught by asserts
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Completed));
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Started));
|
||
|
|
||
|
r->state = RecognizerState_Possible;
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Possible));
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Updated));
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Cancelled));
|
||
|
|
||
|
recognizer_transition_state(r, RecognizerState_Started);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Started);
|
||
|
cl_assert_equal_i(event_type, RecognizerEvent_Started);
|
||
|
cl_assert(!s_manager_state_change);
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Failed));
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Possible));
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Started));
|
||
|
|
||
|
recognizer_transition_state(r, RecognizerState_Updated);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Updated);
|
||
|
cl_assert_equal_i(event_type, RecognizerEvent_Updated);
|
||
|
cl_assert(!s_manager_state_change);
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Failed));
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Possible));
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Started));
|
||
|
|
||
|
event_type = -1;
|
||
|
recognizer_transition_state(r, RecognizerState_Updated);
|
||
|
cl_assert_equal_i(event_type, RecognizerEvent_Updated);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Updated);
|
||
|
cl_assert(!s_manager_state_change);
|
||
|
|
||
|
recognizer_transition_state(r, RecognizerState_Completed);
|
||
|
cl_assert_equal_i(event_type, RecognizerEvent_Completed);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Completed);
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Failed));
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Possible));
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Started));
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Updated));
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Cancelled));
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Completed));
|
||
|
|
||
|
r->state = RecognizerState_Updated;
|
||
|
recognizer_transition_state(r, RecognizerState_Cancelled);
|
||
|
cl_assert_equal_i(event_type, RecognizerEvent_Cancelled);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Cancelled);
|
||
|
cl_assert(!s_manager_state_change);
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Failed));
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Possible));
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Started));
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Updated));
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Cancelled));
|
||
|
cl_assert_passert(recognizer_transition_state(r, RecognizerState_Completed));
|
||
|
|
||
|
r->state = RecognizerState_Started;
|
||
|
event_type = -1;
|
||
|
recognizer_transition_state(r, RecognizerState_Cancelled);
|
||
|
cl_assert_equal_i(event_type, RecognizerEvent_Cancelled);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Cancelled);
|
||
|
cl_assert(!s_manager_state_change);
|
||
|
|
||
|
r->state = RecognizerState_Started;
|
||
|
recognizer_transition_state(r, RecognizerState_Completed);
|
||
|
cl_assert_equal_i(event_type, RecognizerEvent_Completed);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Completed);
|
||
|
cl_assert(!s_manager_state_change);
|
||
|
|
||
|
r->state = RecognizerState_Possible;
|
||
|
recognizer_transition_state(r, RecognizerState_Completed);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Completed);
|
||
|
cl_assert(!s_manager_state_change);
|
||
|
}
|
||
|
|
||
|
void test_recognizer__set_failed(void) {
|
||
|
bool failed = false;
|
||
|
s_test_impl_data.failed = &failed;
|
||
|
NEW_RECOGNIZER(r) = test_recognizer_create(&s_test_impl_data, NULL);
|
||
|
|
||
|
recognizer_set_failed(r);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Failed);
|
||
|
cl_assert(failed);
|
||
|
|
||
|
// Failed -> Failed invalid transition
|
||
|
cl_assert_passert(recognizer_set_failed(r));
|
||
|
|
||
|
// (!Possible) -> Failed invalid transition
|
||
|
r->state = RecognizerState_Started;
|
||
|
cl_assert_passert(recognizer_set_failed(r));
|
||
|
|
||
|
r->state = RecognizerState_Completed;
|
||
|
cl_assert_passert(recognizer_set_failed(r));
|
||
|
}
|
||
|
|
||
|
static void prv_sub_destroy(const Recognizer *r) {
|
||
|
bool *destroyed = recognizer_get_user_data(r);
|
||
|
*destroyed = true;
|
||
|
}
|
||
|
|
||
|
void test_recognizer__destroy(void) {
|
||
|
bool impl_destroyed = false;
|
||
|
s_test_impl_data.destroyed = &impl_destroyed;
|
||
|
|
||
|
bool sub_destroyed = false;
|
||
|
Recognizer *r = test_recognizer_create(&s_test_impl_data, &sub_destroyed);
|
||
|
test_recognizer_enable_on_destroy();
|
||
|
recognizer_set_on_destroy(r, prv_sub_destroy);
|
||
|
|
||
|
// can't destroy a recognizer if it is owned
|
||
|
r->is_owned = true;
|
||
|
recognizer_destroy(r);
|
||
|
cl_assert_equal_b(impl_destroyed, false);
|
||
|
cl_assert_equal_b(sub_destroyed, false);
|
||
|
|
||
|
r->is_owned = false;
|
||
|
recognizer_destroy(r);
|
||
|
cl_assert_equal_b(impl_destroyed, true);
|
||
|
cl_assert_equal_b(sub_destroyed, true);
|
||
|
}
|
||
|
|
||
|
void test_recognizer__reset(void) {
|
||
|
bool reset = false;
|
||
|
bool cancelled = false;
|
||
|
s_test_impl_data.reset = &reset;
|
||
|
s_test_impl_data.cancelled = &cancelled;
|
||
|
|
||
|
NEW_RECOGNIZER(r) = test_recognizer_create(&s_test_impl_data, NULL);
|
||
|
recognizer_reset(r);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Possible);
|
||
|
cl_assert_equal_b(reset, true);
|
||
|
cl_assert_equal_b(cancelled, false);
|
||
|
|
||
|
reset = false;
|
||
|
r->state = RecognizerState_Failed;
|
||
|
recognizer_reset(r);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Possible);
|
||
|
cl_assert_equal_b(reset, true);
|
||
|
cl_assert_equal_b(cancelled, false);
|
||
|
|
||
|
reset = false;
|
||
|
r->state = RecognizerState_Cancelled;
|
||
|
recognizer_reset(r);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Possible);
|
||
|
cl_assert_equal_b(reset, true);
|
||
|
cl_assert_equal_b(cancelled, false);
|
||
|
|
||
|
reset = false;
|
||
|
r->state = RecognizerState_Completed;
|
||
|
recognizer_reset(r);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Possible);
|
||
|
cl_assert_equal_b(reset, true);
|
||
|
cl_assert_equal_b(cancelled, false);
|
||
|
|
||
|
reset = false;
|
||
|
r->state = RecognizerState_Started;
|
||
|
recognizer_reset(r);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Possible);
|
||
|
cl_assert_equal_b(reset, true);
|
||
|
cl_assert_equal_b(cancelled, true);
|
||
|
|
||
|
reset = false;
|
||
|
cancelled = false;
|
||
|
r->state = RecognizerState_Updated;
|
||
|
recognizer_reset(r);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Possible);
|
||
|
cl_assert_equal_b(reset, true);
|
||
|
cl_assert_equal_b(cancelled, true);
|
||
|
}
|
||
|
|
||
|
void test_recognizer__cancel(void) {
|
||
|
bool cancelled = false;
|
||
|
s_test_impl_data.cancelled = &cancelled;
|
||
|
RecognizerEvent rec_event = -1;
|
||
|
|
||
|
NEW_RECOGNIZER(r) = test_recognizer_create(&s_test_impl_data, &rec_event);
|
||
|
recognizer_cancel(r);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Possible);
|
||
|
cl_assert_equal_b(cancelled, false);
|
||
|
cl_assert_equal_i(rec_event, -1);
|
||
|
|
||
|
r->state = RecognizerState_Failed;
|
||
|
recognizer_cancel(r);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Failed);
|
||
|
cl_assert_equal_b(cancelled, false);
|
||
|
cl_assert_equal_i(rec_event, -1);
|
||
|
|
||
|
r->state = RecognizerState_Cancelled;
|
||
|
recognizer_cancel(r);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Cancelled);
|
||
|
cl_assert_equal_b(cancelled, false);
|
||
|
cl_assert_equal_i(rec_event, -1);
|
||
|
|
||
|
r->state = RecognizerState_Completed;
|
||
|
recognizer_cancel(r);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Completed);
|
||
|
cl_assert_equal_b(cancelled, false);
|
||
|
cl_assert_equal_i(rec_event, -1);
|
||
|
|
||
|
r->state = RecognizerState_Started;
|
||
|
recognizer_cancel(r);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Cancelled);
|
||
|
cl_assert_equal_b(cancelled, true);
|
||
|
cl_assert_equal_i(rec_event, RecognizerEvent_Cancelled);
|
||
|
|
||
|
cancelled = false;
|
||
|
r->state = RecognizerState_Updated;
|
||
|
rec_event = -1;
|
||
|
recognizer_cancel(r);
|
||
|
cl_assert_equal_i(r->state, RecognizerState_Cancelled);
|
||
|
cl_assert_equal_b(cancelled, true);
|
||
|
cl_assert_equal_i(rec_event, RecognizerEvent_Cancelled);
|
||
|
}
|
||
|
|
||
|
void test_recognizer__handle_touch_events(void) {
|
||
|
RecognizerEvent rec_event = -1;
|
||
|
TouchEvent last_touch_event = { .type = TouchEvent_Liftoff };
|
||
|
RecognizerState new_state;
|
||
|
bool updated = false;
|
||
|
s_test_impl_data.last_touch_event = &last_touch_event;
|
||
|
s_test_impl_data.new_state = &new_state;
|
||
|
s_test_impl_data.updated = &updated;
|
||
|
NEW_RECOGNIZER(r) = test_recognizer_create(&s_test_impl_data, &rec_event);
|
||
|
|
||
|
new_state = RecognizerState_Possible;
|
||
|
recognizer_handle_touch_event(r, &(TouchEvent) { .type = TouchEvent_Touchdown });
|
||
|
cl_assert_equal_i(last_touch_event.type, TouchEvent_Touchdown);
|
||
|
cl_assert_equal_b(updated, false);
|
||
|
|
||
|
new_state = RecognizerState_Completed;
|
||
|
recognizer_handle_touch_event(r, &(TouchEvent) { .type = TouchEvent_Liftoff });
|
||
|
cl_assert_equal_i(last_touch_event.type, TouchEvent_Liftoff);
|
||
|
cl_assert_equal_b(updated, true);
|
||
|
cl_assert_equal_i(rec_event, RecognizerEvent_Completed);
|
||
|
|
||
|
r->state = RecognizerState_Possible;
|
||
|
updated = false;
|
||
|
new_state = RecognizerState_Started;
|
||
|
recognizer_handle_touch_event(r, &(TouchEvent) { .type = TouchEvent_Touchdown });
|
||
|
cl_assert_equal_i(last_touch_event.type, TouchEvent_Touchdown);
|
||
|
cl_assert_equal_b(updated, true);
|
||
|
cl_assert_equal_i(rec_event, RecognizerEvent_Started);
|
||
|
|
||
|
updated = false;
|
||
|
new_state = RecognizerState_Updated;
|
||
|
recognizer_handle_touch_event(r, &(TouchEvent) { .type = TouchEvent_PositionUpdate });
|
||
|
cl_assert_equal_i(last_touch_event.type, TouchEvent_PositionUpdate);
|
||
|
cl_assert_equal_b(updated, true);
|
||
|
cl_assert_equal_i(rec_event, RecognizerEvent_Updated);
|
||
|
|
||
|
updated = false;
|
||
|
new_state = RecognizerState_Cancelled;
|
||
|
recognizer_handle_touch_event(r, &(TouchEvent) { .type = TouchEvent_Liftoff });
|
||
|
cl_assert_equal_i(last_touch_event.type, TouchEvent_Liftoff);
|
||
|
cl_assert_equal_b(updated, true);
|
||
|
cl_assert_equal_i(rec_event, RecognizerEvent_Cancelled);
|
||
|
|
||
|
// Should not pass touch events to recognizers that are not active
|
||
|
cl_assert_passert(recognizer_handle_touch_event(r, &(TouchEvent) {}));
|
||
|
|
||
|
// Should not pass null touch events
|
||
|
r->state = RecognizerState_Possible;
|
||
|
cl_assert_passert(recognizer_handle_touch_event(r, NULL));
|
||
|
}
|
||
|
|
||
|
void test_recognizer__handle_touch_events_fail_after(void) {
|
||
|
RecognizerEvent rec_event = -1;
|
||
|
RecognizerState new_state;
|
||
|
bool updated = false;
|
||
|
TouchEvent last_touch_event = { .type = TouchEvent_Liftoff };
|
||
|
s_test_impl_data.new_state = &new_state;
|
||
|
s_test_impl_data.updated = &updated;
|
||
|
s_test_impl_data.last_touch_event = &last_touch_event;
|
||
|
|
||
|
NEW_RECOGNIZER(r) = test_recognizer_create(&s_test_impl_data, &rec_event);
|
||
|
NEW_RECOGNIZER(fail) = test_recognizer_create(&s_test_impl_data, NULL);
|
||
|
recognizer_set_fail_after(r, fail);
|
||
|
|
||
|
new_state = RecognizerState_Completed;
|
||
|
recognizer_handle_touch_event(r, &(TouchEvent) { .type = TouchEvent_Touchdown });
|
||
|
cl_assert_equal_i(last_touch_event.type, TouchEvent_Liftoff);
|
||
|
cl_assert_equal_b(updated, false);
|
||
|
|
||
|
fail->state = RecognizerState_Failed;
|
||
|
recognizer_handle_touch_event(r, &(TouchEvent) { .type = TouchEvent_Touchdown });
|
||
|
cl_assert_equal_i(last_touch_event.type, TouchEvent_Touchdown);
|
||
|
cl_assert_equal_b(updated, true);
|
||
|
cl_assert_equal_i(rec_event, RecognizerEvent_Completed);
|
||
|
}
|
||
|
|
||
|
static bool prv_filter(const Recognizer *recognizer, const TouchEvent *touch_event) {
|
||
|
bool *allow = recognizer_get_user_data(recognizer);
|
||
|
return *allow;
|
||
|
}
|
||
|
|
||
|
void test_recognizer__handle_touch_events_filter_cb(void) {
|
||
|
RecognizerState new_state;
|
||
|
bool updated = false;
|
||
|
TouchEvent last_touch_event = { .type = TouchEvent_Liftoff };
|
||
|
s_test_impl_data.new_state = &new_state;
|
||
|
s_test_impl_data.updated = &updated;
|
||
|
s_test_impl_data.last_touch_event = &last_touch_event;
|
||
|
|
||
|
bool allow = false;
|
||
|
NEW_RECOGNIZER(r) = test_recognizer_create(&s_test_impl_data, &allow);
|
||
|
recognizer_set_touch_filter(r, prv_filter);
|
||
|
|
||
|
new_state = RecognizerState_Completed;
|
||
|
recognizer_handle_touch_event(r, &(TouchEvent) { .type = TouchEvent_Touchdown });
|
||
|
cl_assert_equal_i(last_touch_event.type, TouchEvent_Liftoff);
|
||
|
cl_assert_equal_b(updated, false);
|
||
|
|
||
|
allow = true;
|
||
|
recognizer_handle_touch_event(r, &(TouchEvent) { .type = TouchEvent_Touchdown });
|
||
|
cl_assert_equal_i(last_touch_event.type, TouchEvent_Touchdown);
|
||
|
cl_assert_equal_b(updated, true);
|
||
|
cl_assert_equal_i(r->state, new_state);
|
||
|
}
|
||
|
|
||
|
bool s_simultaneous = false;
|
||
|
static bool prv_simultaneous_with_cb(const Recognizer *recognizer,
|
||
|
const Recognizer *simultaneous_with) {
|
||
|
return s_simultaneous;
|
||
|
}
|
||
|
|
||
|
void test_recognizer__set_simultaneous_with(void) {
|
||
|
NEW_RECOGNIZER(r1) = test_recognizer_create(&s_test_impl_data, NULL);
|
||
|
NEW_RECOGNIZER(r2) = test_recognizer_create(&s_test_impl_data, NULL);
|
||
|
|
||
|
s_simultaneous = false;
|
||
|
cl_assert(!recognizer_should_evaluate_simultaneously(NULL, NULL));
|
||
|
cl_assert(!recognizer_should_evaluate_simultaneously(r1, NULL));
|
||
|
cl_assert(!recognizer_should_evaluate_simultaneously(NULL, r2));
|
||
|
cl_assert(!recognizer_should_evaluate_simultaneously(r1, r2));
|
||
|
|
||
|
recognizer_set_simultaneous_with(r1, prv_simultaneous_with_cb);
|
||
|
cl_assert(!recognizer_should_evaluate_simultaneously(NULL, NULL));
|
||
|
cl_assert(!recognizer_should_evaluate_simultaneously(r1, NULL));
|
||
|
cl_assert(!recognizer_should_evaluate_simultaneously(NULL, r2));
|
||
|
cl_assert(!recognizer_should_evaluate_simultaneously(r1, r2));
|
||
|
|
||
|
s_simultaneous = true;
|
||
|
cl_assert(!recognizer_should_evaluate_simultaneously(NULL, NULL));
|
||
|
cl_assert(!recognizer_should_evaluate_simultaneously(r1, NULL));
|
||
|
cl_assert(!recognizer_should_evaluate_simultaneously(NULL, r2));
|
||
|
cl_assert(recognizer_should_evaluate_simultaneously(r1, r2));
|
||
|
}
|
||
|
|
||
|
void test_recognizer__add_remove_list(void) {
|
||
|
RecognizerList list = { NULL };
|
||
|
NEW_RECOGNIZER(r1) = test_recognizer_create(&s_test_impl_data, NULL);
|
||
|
NEW_RECOGNIZER(r2) = test_recognizer_create(&s_test_impl_data, NULL);
|
||
|
|
||
|
recognizer_add_to_list(r1, &list);
|
||
|
recognizer_add_to_list(r2, &list);
|
||
|
cl_assert_equal_i(list_count(list.node), 2);
|
||
|
cl_assert(list_contains(list.node, &r1->node));
|
||
|
cl_assert(list_contains(list.node, &r2->node));
|
||
|
cl_assert(r1->is_owned);
|
||
|
cl_assert(r2->is_owned);
|
||
|
|
||
|
recognizer_remove_from_list(r1, &list);
|
||
|
cl_assert(!list_contains(list.node, &r1->node));
|
||
|
cl_assert(!r1->is_owned);
|
||
|
|
||
|
recognizer_remove_from_list(r1, &list);
|
||
|
cl_assert(!r1->is_owned);
|
||
|
}
|
||
|
|
||
|
static int s_list_idx = 0;
|
||
|
static bool prv_list_iterator(Recognizer *recognizer, void *context) {
|
||
|
const char *names[] = { "R1", "R2", "R3" };
|
||
|
cl_assert(s_list_idx < ARRAY_LENGTH(names));
|
||
|
char s[20];
|
||
|
snprintf(s, sizeof(s), "%s != %s", recognizer->subscriber.data, names[s_list_idx]);
|
||
|
cl_assert_(strcmp(recognizer->subscriber.data, names[s_list_idx++]) == 0, s);
|
||
|
|
||
|
return (s_list_idx < *((int *)context));
|
||
|
}
|
||
|
|
||
|
void test_recognizer__list_iterate(void) {
|
||
|
NEW_RECOGNIZER(r1) = test_recognizer_create(&s_test_impl_data, "R1");
|
||
|
NEW_RECOGNIZER(r2) = test_recognizer_create(&s_test_impl_data, "R2");
|
||
|
NEW_RECOGNIZER(r3) = test_recognizer_create(&s_test_impl_data, "R3");
|
||
|
|
||
|
RecognizerList list = { NULL };
|
||
|
recognizer_add_to_list(r1, &list);
|
||
|
recognizer_add_to_list(r2, &list);
|
||
|
recognizer_add_to_list(r3, &list);
|
||
|
|
||
|
s_list_idx = 0;
|
||
|
int end = 4;
|
||
|
recognizer_list_iterate(&list, prv_list_iterator, &end);
|
||
|
cl_assert_equal_i(s_list_idx, 3);
|
||
|
|
||
|
end = 2;
|
||
|
s_list_idx = 0;
|
||
|
recognizer_list_iterate(&list, prv_list_iterator, &end);
|
||
|
cl_assert_equal_i(s_list_idx, 2);
|
||
|
}
|