mirror of
https://github.com/google/pebble.git
synced 2025-03-15 16:51:21 +00:00
122 lines
3.5 KiB
C
122 lines
3.5 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.
|
|
*/
|
|
|
|
typedef struct MockListNode {
|
|
struct MockListNode *next;
|
|
struct MockListNode *prev;
|
|
const char *func;
|
|
uintmax_t value;
|
|
ssize_t count;
|
|
} MockListNode;
|
|
|
|
static MockListNode s_mock_list_head = {
|
|
&s_mock_list_head, &s_mock_list_head,
|
|
NULL, 0, -1,
|
|
};
|
|
|
|
uintmax_t clar__mock(const char *const func, const char *const file, const size_t line)
|
|
{
|
|
MockListNode *node;
|
|
// Walk the list backwards, for FIFO behavior.
|
|
for (node = s_mock_list_head.prev; node != &s_mock_list_head; node = node->prev) {
|
|
if (node->func == NULL) {
|
|
continue;
|
|
} else if (strcmp(node->func, func) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
char error_msg[128];
|
|
snprintf(error_msg, sizeof(error_msg), "No more mock values available for '%s'!", func);
|
|
cl_assert_(node != &s_mock_list_head, error_msg);
|
|
|
|
// Save the value.
|
|
uintmax_t value = node->value;
|
|
cl_assert_(node->count != 0, "Mock node count is invalid");
|
|
// If the node isn't permanent, lower its counter.
|
|
// If the result is zero, we need to remove this mock value.
|
|
if (node->count > 0 && --node->count == 0) {
|
|
node->prev->next = node->next;
|
|
node->next->prev = node->prev;
|
|
free(node);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
void clar__will_return(const char *const func, const char *const file, const size_t line,
|
|
const uintmax_t value, const ssize_t count)
|
|
{
|
|
MockListNode *node = calloc(1, sizeof(MockListNode));
|
|
cl_assert_(func != NULL, "cl_will_return with invalid function name");
|
|
node->func = func;
|
|
node->value = value;
|
|
node->count = count;
|
|
|
|
// Add to beginning of list
|
|
node->next = s_mock_list_head.next;
|
|
node->prev = &s_mock_list_head;
|
|
s_mock_list_head.next = node;
|
|
// Fixup the next entry.
|
|
// In the case that the list was empty before this call, this will make
|
|
// s_mock_list_head.prev point to the new node, which is what we want.
|
|
cl_assert_(node->next != NULL, "Mock list corrupted!");
|
|
node->next->prev = node;
|
|
}
|
|
|
|
static void clar_mock_reset(void)
|
|
{
|
|
s_mock_list_head.next = &s_mock_list_head;
|
|
s_mock_list_head.prev = &s_mock_list_head;
|
|
s_mock_list_head.func = NULL;
|
|
s_mock_list_head.value = 0;
|
|
s_mock_list_head.count = -1;
|
|
}
|
|
|
|
static void clar_mock_cleanup(void)
|
|
{
|
|
MockListNode *node, *next;
|
|
for (node = s_mock_list_head.next; node != &s_mock_list_head; node = next) {
|
|
next = node->next;
|
|
free(node);
|
|
}
|
|
clar_mock_reset();
|
|
}
|
|
|
|
// Who tests the test framework!
|
|
#if 0
|
|
int gack(void)
|
|
{
|
|
return cl_mock_type(int);
|
|
}
|
|
|
|
int main(int argc, const char *argv[])
|
|
{
|
|
cl_will_return(gack, 573);
|
|
printf("gack() = %d\n", gack()); // 573
|
|
cl_will_return(gack, 123);
|
|
cl_will_return(gack, 456);
|
|
cl_will_return(gack, 789);
|
|
printf("gack() = %d\n", gack()); // 123
|
|
printf("gack() = %d\n", gack()); // 456
|
|
printf("gack() = %d\n", gack()); // 789
|
|
cl_will_return_count(gack, 765, 3);
|
|
printf("gack() = %d\n", gack()); // 765
|
|
printf("gack() = %d\n", gack()); // 765
|
|
printf("gack() = %d\n", gack()); // 765
|
|
|
|
printf("gack() = %d\n", gack());
|
|
return 0;
|
|
}
|
|
#endif
|