mirror of
https://github.com/google/pebble.git
synced 2025-03-25 21:09:05 +00:00
903 lines
24 KiB
C
903 lines
24 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 "services/normal/notifications/notification_storage.h"
|
|
#include "services/normal/notifications/notification_storage_private.h"
|
|
|
|
#include "flash_region/flash_region.h"
|
|
#include "services/normal/filesystem/pfs.h"
|
|
#include "util/size.h"
|
|
|
|
#include "clar.h"
|
|
|
|
#include "stdbool.h"
|
|
|
|
// Stubs
|
|
////////////////////////////////////
|
|
#include "fake_spi_flash.h"
|
|
#include "fake_rtc.h"
|
|
#include "stubs_analytics.h"
|
|
#include "stubs_hexdump.h"
|
|
#include "stubs_layout_layer.h"
|
|
#include "stubs_logging.h"
|
|
#include "stubs_mutex.h"
|
|
#include "stubs_passert.h"
|
|
#include "stubs_pbl_malloc.h"
|
|
#include "stubs_pebble_tasks.h"
|
|
#include "stubs_prompt.h"
|
|
#include "stubs_rand_ptr.h"
|
|
#include "stubs_serial.h"
|
|
#include "stubs_sleep.h"
|
|
#include "stubs_task_watchdog.h"
|
|
|
|
#define TEST_START FLASH_REGION_FILE_TEST_SPACE_BEGIN
|
|
#define TEST_SIZE (FLASH_REGION_FILE_TEST_SPACE_END - \
|
|
FLASH_REGION_FILE_TEST_SPACE_BEGIN)
|
|
|
|
extern void notification_storage_reset(void);
|
|
|
|
typedef void (*SystemTaskEventCallback)(void *data);
|
|
|
|
static Attribute action1_attributes[] = {
|
|
{.id = AttributeIdTitle, .cstring = "Dismiss"},
|
|
};
|
|
|
|
static Attribute action2_attributes[] = {
|
|
{.id = AttributeIdTitle, .cstring = "Archive"},
|
|
};
|
|
|
|
static StringList string_list = {
|
|
.serialized_byte_length = 3,
|
|
.data = "A\0B",
|
|
};
|
|
|
|
static Attribute action3_attributes[] = {
|
|
{.id = AttributeIdAncsAction, .int8 = 1},
|
|
{.id = AttributeIdCannedResponses, .string_list = &string_list,},
|
|
};
|
|
|
|
static TimelineItemAction actions[] = {
|
|
{
|
|
.id = 0,
|
|
.type = TimelineItemActionTypeResponse,
|
|
.attr_list = {
|
|
.num_attributes = ARRAY_LENGTH(action1_attributes),
|
|
.attributes = action1_attributes
|
|
}
|
|
},
|
|
{
|
|
.id = 1, .type = TimelineItemActionTypeResponse,
|
|
.attr_list = {
|
|
.num_attributes = ARRAY_LENGTH(action2_attributes),
|
|
.attributes = action2_attributes
|
|
}
|
|
},
|
|
{
|
|
.id = 2,
|
|
.type = TimelineItemActionTypeResponse,
|
|
.attr_list = {
|
|
.num_attributes = ARRAY_LENGTH(action3_attributes),
|
|
.attributes = action3_attributes
|
|
}
|
|
},
|
|
};
|
|
|
|
static Attribute attributes[] = {
|
|
{.id = AttributeIdTitle, .cstring = "Sender"},
|
|
{.id = AttributeIdBody, .cstring = "Message"},
|
|
{.id = AttributeIdSubtitle, .cstring = "Subject"},
|
|
};
|
|
|
|
bool system_task_add_callback(SystemTaskEventCallback cb, void *data) {
|
|
return true;
|
|
}
|
|
|
|
PebblePhoneCaller* phone_call_util_create_caller(const char *number, const char *name) {
|
|
return NULL;
|
|
}
|
|
|
|
// Setup
|
|
////////////////////////////////////
|
|
|
|
void test_notification_storage__initialize(void) {
|
|
fake_spi_flash_init(0, 0x1000000);
|
|
pfs_init(false);
|
|
pfs_format(false /* write erase headers */);
|
|
notification_storage_reset();
|
|
}
|
|
|
|
void test_notification_storage__cleanup(void) {
|
|
}
|
|
|
|
static void compare_attr_list(AttributeList a, AttributeList b) {
|
|
cl_assert_equal_i(a.num_attributes, b.num_attributes);
|
|
for (int i = 0; i < a.num_attributes; i++) {
|
|
cl_assert_equal_i(a.attributes[i].id, b.attributes[i].id);
|
|
switch (a.attributes[i].id) {
|
|
case AttributeIdTitle:
|
|
case AttributeIdSubtitle:
|
|
case AttributeIdBody:
|
|
cl_assert_equal_s(a.attributes[i].cstring, b.attributes[i].cstring);
|
|
break;
|
|
case AttributeIdAncsAction:
|
|
cl_assert_equal_i(a.attributes[i].int8, b.attributes[i].int8);
|
|
break;
|
|
case AttributeIdCannedResponses: {
|
|
StringList *list_a = a.attributes[i].string_list;
|
|
StringList *list_b = b.attributes[i].string_list;
|
|
cl_assert_equal_i(list_a->serialized_byte_length, list_b->serialized_byte_length);
|
|
cl_assert_equal_i(
|
|
string_list_count(list_a),
|
|
string_list_count(list_b)
|
|
);
|
|
uint32_t count = string_list_count(list_a);
|
|
for (uint32_t idx = 0; i<count; i++) {
|
|
cl_assert_equal_s(
|
|
string_list_get_at(list_a, idx),
|
|
string_list_get_at(list_b, idx)
|
|
);
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
cl_assert(false);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void compare_notifications(TimelineItem *a, TimelineItem *b) {
|
|
cl_assert(uuid_equal(&a->header.id, &b->header.id));
|
|
cl_assert_equal_i(a->header.ancs_uid, b->header.ancs_uid);
|
|
cl_assert_equal_i(a->header.status, b->header.status);
|
|
cl_assert_equal_i(a->header.timestamp, b->header.timestamp);
|
|
cl_assert_equal_i(a->header.layout, b->header.layout);
|
|
compare_attr_list(a->attr_list, b->attr_list);
|
|
cl_assert_equal_i(a->action_group.num_actions, b->action_group.num_actions);
|
|
for (int i = 0; i < a->action_group.num_actions; i++) {
|
|
cl_assert_equal_i(a->action_group.actions[i].id, b->action_group.actions[i].id);
|
|
cl_assert_equal_i(a->action_group.actions[i].type, b->action_group.actions[i].type);
|
|
compare_attr_list(a->action_group.actions[i].attr_list, b->action_group.actions[i].attr_list);
|
|
}
|
|
}
|
|
|
|
// Tests
|
|
////////////////////////////////////
|
|
void test_notification_storage__basic(void) {
|
|
Uuid id = {0x6b, 0xf6, 0x21, 0x5b, 0xc9, 0x7f, 0x40, 0x9e,
|
|
0x8c, 0x31, 0x4f, 0x55, 0x65, 0x72, 0x22, 0xb4};
|
|
TimelineItem e = {
|
|
.header = {
|
|
.id = id,
|
|
.status = 0,
|
|
.layout = LayoutIdGeneric,
|
|
.type = TimelineItemTypeNotification,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = ARRAY_LENGTH(attributes),
|
|
.attributes = attributes,
|
|
},
|
|
.action_group = {
|
|
.num_actions = ARRAY_LENGTH(actions),
|
|
.actions = actions,
|
|
}
|
|
};
|
|
|
|
notification_storage_store(&e);
|
|
|
|
TimelineItem r;
|
|
cl_assert(notification_storage_get(&id, &r));
|
|
compare_notifications(&e, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
cl_assert(notification_storage_get(&id, &r));
|
|
compare_notifications(&e, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
Uuid invalid_uuid;
|
|
uuid_generate(&invalid_uuid);
|
|
cl_assert_equal_b(notification_storage_get(&invalid_uuid, &r), false);
|
|
}
|
|
|
|
void test_notification_storage__multiple(void) {
|
|
Uuid i1 ;
|
|
uuid_generate(&i1);
|
|
TimelineItem e1 = {
|
|
.header = {
|
|
.id = i1,
|
|
.type = TimelineItemTypeNotification,
|
|
.status = 0,
|
|
.ancs_uid = 0,
|
|
.layout = LayoutIdGeneric,
|
|
.timestamp = 0x53f0dda5,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = ARRAY_LENGTH(attributes),
|
|
.attributes = attributes,
|
|
},
|
|
.action_group = {
|
|
.num_actions = ARRAY_LENGTH(actions),
|
|
.actions = actions,
|
|
}
|
|
};
|
|
|
|
Uuid i2;
|
|
uuid_generate(&i2);
|
|
TimelineItem e2 = {
|
|
.header = {
|
|
.id = i2,
|
|
.type = TimelineItemTypeNotification,
|
|
.status = 0,
|
|
.ancs_uid = 0,
|
|
.layout = LayoutIdGeneric,
|
|
.timestamp = 0x53f0dda6,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = 2,
|
|
.attributes = attributes,
|
|
},
|
|
.action_group = {
|
|
.num_actions = 1,
|
|
.actions = &actions[2],
|
|
}
|
|
};
|
|
|
|
Uuid i3;
|
|
uuid_generate(&i3);
|
|
TimelineItem e3 = {
|
|
.header = {
|
|
.id = i3,
|
|
.type = TimelineItemTypeNotification,
|
|
.status = 0,
|
|
.ancs_uid = 0,
|
|
.layout = LayoutIdGeneric,
|
|
.timestamp = 0x53f0dda7,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = 1,
|
|
.attributes = &attributes[2],
|
|
},
|
|
.action_group = {
|
|
.num_actions = 2,
|
|
.actions = actions,
|
|
}
|
|
};
|
|
|
|
notification_storage_store(&e1);
|
|
|
|
TimelineItem r;
|
|
cl_assert(notification_storage_get(&i1, &r));
|
|
compare_notifications(&e1, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
notification_storage_store(&e2);
|
|
notification_storage_store(&e3);
|
|
|
|
cl_assert(notification_storage_get(&i1, &r));
|
|
compare_notifications(&e1, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
cl_assert(notification_storage_get(&i2, &r));
|
|
compare_notifications(&e2, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
cl_assert(notification_storage_get(&i3, &r));
|
|
compare_notifications(&e3, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
cl_assert(notification_storage_get(&i1, &r));
|
|
compare_notifications(&e1, &r);
|
|
free(r.allocated_buffer);
|
|
}
|
|
|
|
void test_notification_storage__remove_single(void) {
|
|
Uuid i;
|
|
uuid_generate(&i);
|
|
TimelineItem e = {
|
|
.header = {
|
|
.id = i,
|
|
.type = TimelineItemTypeNotification,
|
|
.status = 0,
|
|
.ancs_uid = 0,
|
|
.layout = LayoutIdGeneric,
|
|
.timestamp = 0x53f0dda5,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = ARRAY_LENGTH(attributes),
|
|
.attributes = attributes,
|
|
},
|
|
.action_group = {
|
|
.num_actions = ARRAY_LENGTH(actions),
|
|
.actions = actions,
|
|
}
|
|
};
|
|
|
|
notification_storage_store(&e);
|
|
|
|
TimelineItem r;
|
|
cl_assert(notification_storage_get(&i, &r));
|
|
compare_notifications(&e, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
notification_storage_remove(&i);
|
|
cl_assert_equal_b(notification_storage_get(&i, &r), false);
|
|
}
|
|
|
|
void test_notification_storage__set_actioned_flag(void) {
|
|
Uuid i;
|
|
uuid_generate(&i);
|
|
TimelineItem e = {
|
|
.header = {
|
|
.id = i,
|
|
.type = TimelineItemTypeNotification,
|
|
.status = 0,
|
|
.ancs_uid = 0,
|
|
.layout = LayoutIdGeneric,
|
|
.timestamp = 0x53f0dda5,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = ARRAY_LENGTH(attributes),
|
|
.attributes = attributes,
|
|
},
|
|
.action_group = {
|
|
.num_actions = ARRAY_LENGTH(actions),
|
|
.actions = actions,
|
|
}
|
|
};
|
|
|
|
notification_storage_store(&e);
|
|
|
|
TimelineItem r;
|
|
cl_assert(notification_storage_get(&i, &r));
|
|
compare_notifications(&e, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
notification_storage_set_status(&i, TimelineItemStatusActioned);
|
|
cl_assert(notification_storage_get(&i, &r));
|
|
cl_assert(uuid_equal(&e.header.id, &r.header.id));
|
|
cl_assert_equal_i(e.header.ancs_uid, r.header.ancs_uid);
|
|
cl_assert_equal_i(TimelineItemStatusActioned, r.header.status);
|
|
cl_assert_equal_i(e.header.timestamp, r.header.timestamp);
|
|
cl_assert_equal_i(e.header.layout, r.header.layout);
|
|
compare_attr_list(e.attr_list, r.attr_list);
|
|
}
|
|
|
|
void test_notification_storage__remove_multiple_first(void) {
|
|
Uuid i1;
|
|
uuid_generate(&i1);
|
|
TimelineItem e1 = {
|
|
.header = {
|
|
.id = i1,
|
|
.type = TimelineItemTypeNotification,
|
|
.status = 0,
|
|
.ancs_uid = 0,
|
|
.layout = LayoutIdGeneric,
|
|
.timestamp = 0x53f0dda5,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = ARRAY_LENGTH(attributes),
|
|
.attributes = attributes,
|
|
},
|
|
.action_group = {
|
|
.num_actions = ARRAY_LENGTH(actions),
|
|
.actions = actions,
|
|
}
|
|
};
|
|
|
|
Uuid i2;
|
|
uuid_generate(&i2);
|
|
TimelineItem e2 = {
|
|
.header = {
|
|
.id = i2,
|
|
.type = TimelineItemTypeNotification,
|
|
.status = 0,
|
|
.ancs_uid = 0,
|
|
.layout = LayoutIdGeneric,
|
|
.timestamp = 0x53f0dda6,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = 2,
|
|
.attributes = attributes,
|
|
},
|
|
.action_group = {
|
|
.num_actions = 1,
|
|
.actions = &actions[2],
|
|
}
|
|
};
|
|
|
|
notification_storage_store(&e1);
|
|
notification_storage_store(&e2);
|
|
|
|
notification_storage_remove(&i1);
|
|
|
|
TimelineItem r;
|
|
cl_assert_equal_b(notification_storage_get(&i1, &r), false);
|
|
|
|
cl_assert(notification_storage_get(&i2, &r));
|
|
compare_notifications(&e2, &r);
|
|
free(r.allocated_buffer);
|
|
}
|
|
|
|
void test_notification_storage__remove_add(void) {
|
|
Uuid i1;
|
|
uuid_generate(&i1);
|
|
TimelineItem e1 = {
|
|
.header = {
|
|
.id = i1,
|
|
.type = TimelineItemTypeNotification,
|
|
.status = 0,
|
|
.ancs_uid = 0,
|
|
.layout = LayoutIdGeneric,
|
|
.timestamp = 0x53f0dda5,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = ARRAY_LENGTH(attributes),
|
|
.attributes = attributes,
|
|
},
|
|
.action_group = {
|
|
.num_actions = ARRAY_LENGTH(actions),
|
|
.actions = actions,
|
|
}
|
|
};
|
|
|
|
Uuid i2;
|
|
uuid_generate(&i2);
|
|
TimelineItem e2 = {
|
|
.header = {
|
|
.id = i2,
|
|
.type = TimelineItemTypeNotification,
|
|
.status = 0,
|
|
.ancs_uid = 0,
|
|
.layout = LayoutIdGeneric,
|
|
.timestamp = 0x53f0dda6,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = 2,
|
|
.attributes = attributes,
|
|
},
|
|
.action_group = {
|
|
.num_actions = 1,
|
|
.actions = &actions[2],
|
|
}
|
|
};
|
|
|
|
Uuid i3;
|
|
uuid_generate(&i3);
|
|
TimelineItem e3 = {
|
|
.header = {
|
|
.id = i3,
|
|
.type = TimelineItemTypeNotification,
|
|
.status = 0,
|
|
.ancs_uid = 0,
|
|
.layout = LayoutIdGeneric,
|
|
.timestamp = 0x53f0dda7,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = 1,
|
|
.attributes = &attributes[2],
|
|
},
|
|
.action_group = {
|
|
.num_actions = 2,
|
|
.actions = actions,
|
|
}
|
|
};
|
|
|
|
notification_storage_store(&e1);
|
|
notification_storage_store(&e2);
|
|
|
|
notification_storage_remove(&i2);
|
|
|
|
TimelineItem r;
|
|
cl_assert(notification_storage_get(&i1, &r));
|
|
compare_notifications(&e1, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
cl_assert_equal_b(notification_storage_get(&i2, &r), false);
|
|
|
|
notification_storage_store(&e3);
|
|
|
|
cl_assert(notification_storage_get(&i1, &r));
|
|
compare_notifications(&e1, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
cl_assert_equal_b(notification_storage_get(&i2, &r), false);
|
|
|
|
cl_assert(notification_storage_get(&i3, &r));
|
|
compare_notifications(&e3, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
e2.header.timestamp = e3.header.timestamp + 1;
|
|
notification_storage_store(&e2);
|
|
|
|
cl_assert(notification_storage_get(&i1, &r));
|
|
compare_notifications(&e1, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
cl_assert(notification_storage_get(&i2, &r));
|
|
compare_notifications(&e2, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
cl_assert(notification_storage_get(&i3, &r));
|
|
compare_notifications(&e3, &r);
|
|
free(r.allocated_buffer);
|
|
}
|
|
|
|
void test_notification_storage__remove_add_compress(void) {
|
|
time_t timestamp = 0x10000000;
|
|
TimelineItem e = {
|
|
.header = {
|
|
.type = TimelineItemTypeNotification,
|
|
.status = 0,
|
|
.ancs_uid = 0,
|
|
.layout = LayoutIdGeneric,
|
|
.timestamp = 0x53f0dda5,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = ARRAY_LENGTH(attributes),
|
|
.attributes = attributes,
|
|
},
|
|
.action_group = {
|
|
.num_actions = ARRAY_LENGTH(actions),
|
|
.actions = actions,
|
|
}
|
|
};
|
|
|
|
|
|
const size_t notif_size = sizeof(SerializedTimelineItemHeader) +
|
|
timeline_item_get_serialized_payload_size(&e);
|
|
const size_t file_size = NOTIFICATION_STORAGE_FILE_SIZE;
|
|
const size_t count = file_size / notif_size;
|
|
Uuid uuids[count];
|
|
|
|
int i;
|
|
for (i = 0; i < count; i++) {
|
|
uuid_generate(&uuids[i]);
|
|
e.header.id = uuids[i];
|
|
e.header.timestamp = timestamp + i;
|
|
notification_storage_store(&e);
|
|
}
|
|
TimelineItem r;
|
|
cl_assert(notification_storage_get(&uuids[0], &r));
|
|
e.header.id = uuids[0];
|
|
e.header.timestamp = timestamp;
|
|
compare_notifications(&e, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
cl_assert(notification_storage_get(&uuids[i - 1], &r));
|
|
e.header.id = uuids[i - 1];
|
|
e.header.timestamp = timestamp + i - 1;
|
|
compare_notifications(&e, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
// Storage is now full and none have been removed.
|
|
// As more space is needed, blocks of 4k are freed up
|
|
Uuid uuid;
|
|
uuid_generate(&uuid);
|
|
e.header.id = uuid;
|
|
e.header.timestamp = timestamp + i;
|
|
notification_storage_store(&e);
|
|
cl_assert(notification_storage_get(&uuid, &r));
|
|
compare_notifications(&e, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
const size_t block_size = file_size / 4;
|
|
int erase_count = block_size / notif_size + (((block_size % notif_size) > 0) ? 1 : 0);
|
|
int j;
|
|
for (j = 0; j < erase_count; j++) {
|
|
e.header.id = uuids[j];
|
|
e.header.timestamp = timestamp + j;
|
|
cl_assert_equal_b(notification_storage_get(&uuids[j], &r), false);
|
|
}
|
|
e.header.id = uuids[j];
|
|
e.header.timestamp = timestamp + j;
|
|
cl_assert(notification_storage_get(&uuids[j], &r));
|
|
compare_notifications(&e, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
// Fill up storage again
|
|
for (++i; i < count + erase_count; i++) {
|
|
e.header.id = uuids[i % count];
|
|
e.header.timestamp = timestamp + i;
|
|
notification_storage_store(&e);
|
|
cl_assert(notification_storage_get(&uuids[i % count], &r));
|
|
compare_notifications(&e, &r);
|
|
free(r.allocated_buffer);
|
|
}
|
|
|
|
//Check that no notifications have been deleted
|
|
e.header.id = uuids[j];
|
|
e.header.timestamp = timestamp + j;
|
|
cl_assert(notification_storage_get(&uuids[j], &r));
|
|
compare_notifications(&e, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
//Free up enough space for one notification by removing one
|
|
notification_storage_remove(&uuids[i/2]);
|
|
e.header.id = uuids[i/2];
|
|
e.header.timestamp = timestamp + i/2;
|
|
cl_assert_equal_b(notification_storage_get(&uuids[i/2], &r), false);
|
|
|
|
//Add another notification. Compression should take place without freeing up a 4k block
|
|
e.header.id = uuids[i];
|
|
e.header.timestamp = timestamp + i;
|
|
notification_storage_store(&e);
|
|
cl_assert(notification_storage_get(&uuids[i], &r));
|
|
compare_notifications(&e, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
//Ensure that compression does not remove old notifications
|
|
e.header.id = uuids[j];
|
|
e.header.timestamp = timestamp + j;
|
|
cl_assert(notification_storage_get(&uuids[j], &r));
|
|
compare_notifications(&e, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
//Add another notification. Compression should free up another 4k block
|
|
e.header.id = uuids[i];
|
|
e.header.timestamp = timestamp + i;
|
|
notification_storage_store(&e);
|
|
cl_assert(notification_storage_get(&uuids[i], &r));
|
|
compare_notifications(&e, &r);
|
|
free(r.allocated_buffer);
|
|
|
|
// Check that an expected number of notifications were removed
|
|
erase_count += j;
|
|
for (; j < erase_count; j++) {
|
|
e.header.id = uuids[j];
|
|
e.header.timestamp = timestamp + j;
|
|
cl_assert_equal_b(notification_storage_get(&uuids[j], &r), false);
|
|
}
|
|
}
|
|
|
|
void test_notification_storage__find_ancs_id(void) {
|
|
Uuid i1;
|
|
uuid_generate(&i1);
|
|
TimelineItem e1 = {
|
|
.header = {
|
|
.id = i1,
|
|
.type = TimelineItemTypeNotification,
|
|
.status = 0,
|
|
.ancs_uid = 0,
|
|
.layout = LayoutIdGeneric,
|
|
.timestamp = 0x53f0dda5,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = ARRAY_LENGTH(attributes),
|
|
.attributes = attributes,
|
|
},
|
|
.action_group = {
|
|
.num_actions = ARRAY_LENGTH(actions),
|
|
.actions = actions,
|
|
}
|
|
};
|
|
|
|
Uuid i2;
|
|
uuid_generate(&i2);
|
|
TimelineItem e2 = {
|
|
.header = {
|
|
.id = i2,
|
|
.type = TimelineItemTypeNotification,
|
|
.status = 0,
|
|
.ancs_uid = 1,
|
|
.layout = LayoutIdGeneric,
|
|
.timestamp = 0x53f0dda6,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = 2,
|
|
.attributes = attributes,
|
|
},
|
|
.action_group = {
|
|
.num_actions = 1,
|
|
.actions = &actions[2],
|
|
}
|
|
};
|
|
|
|
Uuid i3;
|
|
uuid_generate(&i3);
|
|
TimelineItem e3 = {
|
|
.header = {
|
|
.id = i3,
|
|
.type = TimelineItemTypeNotification,
|
|
.status = 0,
|
|
.ancs_uid = 84,
|
|
.layout = LayoutIdGeneric,
|
|
.timestamp = 0x53f0dda7,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = 1,
|
|
.attributes = &attributes[2],
|
|
},
|
|
.action_group = {
|
|
.num_actions = 2,
|
|
.actions = actions,
|
|
}
|
|
};
|
|
|
|
notification_storage_store(&e1);
|
|
notification_storage_store(&e2);
|
|
notification_storage_store(&e3);
|
|
|
|
Uuid u;
|
|
cl_assert(notification_storage_find_ancs_notification_id(0, &u));
|
|
cl_assert(uuid_equal(&u, &e1.header.id));
|
|
cl_assert(notification_storage_find_ancs_notification_id(1, &u));
|
|
cl_assert(uuid_equal(&u, &e2.header.id));
|
|
cl_assert(notification_storage_find_ancs_notification_id(84, &u));
|
|
cl_assert(uuid_equal(&u, &e3.header.id));
|
|
|
|
// Add a new notification with the same ANCS UID as an existing notification to make sure we
|
|
// return the new notification instead of the old one
|
|
TimelineItem e4 = e3;
|
|
uuid_generate(&e4.header.id);
|
|
notification_storage_store(&e4);
|
|
cl_assert(notification_storage_find_ancs_notification_id(84, &u));
|
|
cl_assert(uuid_equal(&u, &e4.header.id));
|
|
}
|
|
|
|
void test_notification_storage__find_by_timestamp(void) {
|
|
Uuid i1;
|
|
uuid_generate(&i1);
|
|
TimelineItem e1 = {
|
|
.header = {
|
|
.id = i1,
|
|
.type = TimelineItemTypeNotification,
|
|
.status = 0,
|
|
.ancs_uid = 0,
|
|
.layout = LayoutIdGeneric,
|
|
.timestamp = 0x53f0dda5,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = ARRAY_LENGTH(attributes),
|
|
.attributes = attributes,
|
|
},
|
|
.action_group = {
|
|
.num_actions = ARRAY_LENGTH(actions),
|
|
.actions = actions,
|
|
}
|
|
};
|
|
|
|
Uuid i2;
|
|
uuid_generate(&i2);
|
|
TimelineItem e2 = {
|
|
.header = {
|
|
.id = i2,
|
|
.type = TimelineItemTypeNotification,
|
|
.status = 0,
|
|
.ancs_uid = 1,
|
|
.layout = LayoutIdGeneric,
|
|
.timestamp = 0x53f0dda6,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = 2,
|
|
.attributes = attributes,
|
|
},
|
|
.action_group = {
|
|
.num_actions = 1,
|
|
.actions = &actions[2],
|
|
}
|
|
};
|
|
|
|
Uuid i3;
|
|
uuid_generate(&i3);
|
|
TimelineItem e3 = {
|
|
.header = {
|
|
.id = i3,
|
|
.type = TimelineItemTypeNotification,
|
|
.status = 0,
|
|
.ancs_uid = 84,
|
|
.layout = LayoutIdGeneric,
|
|
.timestamp = 0x53f0dda7,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = 1,
|
|
.attributes = &attributes[2],
|
|
},
|
|
.action_group = {
|
|
.num_actions = 2,
|
|
.actions = actions,
|
|
}
|
|
};
|
|
|
|
notification_storage_store(&e1);
|
|
notification_storage_store(&e2);
|
|
notification_storage_store(&e3);
|
|
|
|
TimelineItem test = e1;
|
|
test.header.id = UUID_INVALID;
|
|
test.header.ancs_uid = 51;
|
|
|
|
CommonTimelineItemHeader h;
|
|
cl_assert(notification_storage_find_ancs_notification_by_timestamp(&test, &h));
|
|
cl_assert_equal_m(&e1.header, &h, sizeof(CommonTimelineItemHeader));
|
|
|
|
test.action_group.num_actions = 2;
|
|
cl_assert_equal_b(notification_storage_find_ancs_notification_by_timestamp(&test, &h),
|
|
false);
|
|
|
|
test = e2;
|
|
test.header.id = UUID_INVALID;
|
|
cl_assert(notification_storage_find_ancs_notification_by_timestamp(&test, &h));
|
|
cl_assert_equal_m(&e2.header, &h, sizeof(CommonTimelineItemHeader));
|
|
|
|
test = e3;
|
|
test.header.id = UUID_INVALID;
|
|
cl_assert(notification_storage_find_ancs_notification_by_timestamp(&test, &h));
|
|
cl_assert_equal_m(&e3.header, &h, sizeof(CommonTimelineItemHeader));
|
|
|
|
notification_storage_remove(&i2);
|
|
test = e2;
|
|
test.header.id = UUID_INVALID;
|
|
cl_assert_equal_b(notification_storage_find_ancs_notification_by_timestamp(&test, &h),
|
|
false);
|
|
|
|
test = e3;
|
|
test.header.id = UUID_INVALID;
|
|
cl_assert(notification_storage_find_ancs_notification_by_timestamp(&test, &h));
|
|
cl_assert_equal_m(&e3.header, &h, sizeof(CommonTimelineItemHeader));
|
|
}
|
|
|
|
void test_notification_storage__should_detect_corruption(void) {
|
|
Uuid i1;
|
|
uuid_generate(&i1);
|
|
TimelineItem e1 = {
|
|
.header = {
|
|
.id = i1,
|
|
.type = TimelineItemTypeNotification,
|
|
.status = TimelineItemStatusRead,
|
|
.ancs_uid = 0,
|
|
.layout = LayoutIdGeneric,
|
|
.timestamp = 0x53f0dda5,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = ARRAY_LENGTH(attributes),
|
|
.attributes = attributes,
|
|
},
|
|
.action_group = {
|
|
.num_actions = ARRAY_LENGTH(actions),
|
|
.actions = actions,
|
|
}
|
|
};
|
|
|
|
notification_storage_store(&e1);
|
|
TimelineItem r;
|
|
cl_assert(notification_storage_get(&i1, &r));
|
|
compare_notifications(&r, &e1);
|
|
|
|
TimelineItem e2 = e1;
|
|
Uuid i2;
|
|
uuid_generate(&i2);
|
|
e2.header.id = i2;
|
|
e2.header.status = 0xC0;
|
|
notification_storage_store(&e2);
|
|
cl_assert_equal_b(notification_storage_get(&i2, &r), false);
|
|
|
|
TimelineItem e3 = e1;
|
|
Uuid i3;
|
|
uuid_generate(&i3);
|
|
e3.header.id = i3;
|
|
e3.header.type = TimelineItemTypeOutOfRange;
|
|
notification_storage_store(&e3);
|
|
cl_assert_equal_b(notification_storage_get(&i3, &r), false);
|
|
|
|
Uuid i4;
|
|
uuid_generate(&i4);
|
|
TimelineItem e4 = e1;
|
|
e4.header.id = i4;
|
|
e4.header.layout = NumLayoutIds;
|
|
notification_storage_store(&e4);
|
|
cl_assert_equal_b(notification_storage_get(&i4, &r), false);
|
|
}
|