blob: 676d6aa40375f1e2500effee2356ea2dcfc39f5d [file] [log] [blame]
// Copyright 2025 The Pigweed Authors
//
// 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
//
// https://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.
#![no_std]
#![no_main]
use core::mem::offset_of;
use list::*;
use unittest::test;
struct TestMember {
value: u32,
link: Link,
}
struct TestAdapter {}
impl Adapter for TestAdapter {
const LINK_OFFSET: usize = offset_of!(TestMember, link);
}
unsafe fn validate_list(
list: &UnsafeList<TestMember, TestAdapter>,
expected_values: &[u32],
) -> unittest::Result<()> {
let mut index = 0;
list.for_each(|element| {
unittest::assert_eq!(element.value, expected_values[index]);
index += 1;
Ok(())
})?;
unittest::assert_eq!(index, expected_values.len());
Ok(())
}
#[test]
fn new_link_is_not_linked() -> unittest::Result<()> {
let link = Link::new();
unittest::assert_false!(link.is_linked());
unittest::assert_true!(link.is_unlinked());
Ok(())
}
#[test]
fn new_list_is_empty() -> unittest::Result<()> {
let list = UnsafeList::<TestMember, TestAdapter>::new();
unittest::assert_true!(unsafe { list.is_empty() });
Ok(())
}
#[test]
fn push_front_adds_in_correct_order() -> unittest::Result<()> {
let mut element1 = TestMember {
value: 1,
link: Link::new(),
};
let mut element2 = TestMember {
value: 2,
link: Link::new(),
};
let mut list = UnsafeList::<TestMember, TestAdapter>::new();
unsafe { list.push_front_unchecked(&mut element2) };
unsafe { list.push_front_unchecked(&mut element1) };
unittest::assert_false!(unsafe { list.is_empty() });
unsafe { validate_list(&list, &[1, 2]) }
}
#[test]
fn unlink_removes_head_correctly() -> unittest::Result<()> {
let mut element1 = TestMember {
value: 1,
link: Link::new(),
};
let mut element2 = TestMember {
value: 2,
link: Link::new(),
};
let mut element3 = TestMember {
value: 3,
link: Link::new(),
};
let mut list = UnsafeList::<TestMember, TestAdapter>::new();
unsafe { list.push_front_unchecked(&mut element3) };
unsafe { list.push_front_unchecked(&mut element2) };
unsafe { list.push_front_unchecked(&mut element1) };
unsafe { list.unlink_element(&element1) };
unsafe { validate_list(&list, &[2, 3]) }
}
#[test]
fn unlink_removes_tail_correctly() -> unittest::Result<()> {
let mut element1 = TestMember {
value: 1,
link: Link::new(),
};
let mut element2 = TestMember {
value: 2,
link: Link::new(),
};
let mut element3 = TestMember {
value: 3,
link: Link::new(),
};
let mut list = UnsafeList::<TestMember, TestAdapter>::new();
unsafe { list.push_front_unchecked(&mut element3) };
unsafe { list.push_front_unchecked(&mut element2) };
unsafe { list.push_front_unchecked(&mut element1) };
unsafe { list.unlink_element(&element3) };
unsafe { validate_list(&list, &[1, 2]) }
}
#[test]
fn unlink_removes_middle_correctly() -> unittest::Result<()> {
let mut element1 = TestMember {
value: 1,
link: Link::new(),
};
let mut element2 = TestMember {
value: 2,
link: Link::new(),
};
let mut element3 = TestMember {
value: 3,
link: Link::new(),
};
let mut list = UnsafeList::<TestMember, TestAdapter>::new();
unsafe { list.push_front_unchecked(&mut element3) };
unsafe { list.push_front_unchecked(&mut element2) };
unsafe { list.push_front_unchecked(&mut element1) };
unsafe { list.unlink_element(&element2) };
unsafe { validate_list(&list, &[1, 3]) }
}
#[test]
fn filter_removes_nothing_correctly() -> unittest::Result<()> {
let mut element1 = TestMember {
value: 1,
link: Link::new(),
};
let mut element2 = TestMember {
value: 2,
link: Link::new(),
};
let mut element3 = TestMember {
value: 3,
link: Link::new(),
};
let mut list = UnsafeList::<TestMember, TestAdapter>::new();
unsafe { list.push_front_unchecked(&mut element3) };
unsafe { list.push_front_unchecked(&mut element2) };
unsafe { list.push_front_unchecked(&mut element1) };
unsafe { list.filter(|_| true) };
unsafe { validate_list(&list, &[1, 2, 3]) }
}
#[test]
fn filter_removes_everything_correctly() -> unittest::Result<()> {
let mut element1 = TestMember {
value: 1,
link: Link::new(),
};
let mut element2 = TestMember {
value: 2,
link: Link::new(),
};
let mut element3 = TestMember {
value: 3,
link: Link::new(),
};
let mut list = UnsafeList::<TestMember, TestAdapter>::new();
unsafe { list.push_front_unchecked(&mut element3) };
unsafe { list.push_front_unchecked(&mut element2) };
unsafe { list.push_front_unchecked(&mut element1) };
unsafe { list.filter(|_| false) };
unsafe { validate_list(&list, &[]) }
}
#[test]
fn filter_removes_head_correctly() -> unittest::Result<()> {
let mut element1 = TestMember {
value: 1,
link: Link::new(),
};
let mut element2 = TestMember {
value: 2,
link: Link::new(),
};
let mut element3 = TestMember {
value: 3,
link: Link::new(),
};
let mut list = UnsafeList::<TestMember, TestAdapter>::new();
unsafe { list.push_front_unchecked(&mut element3) };
unsafe { list.push_front_unchecked(&mut element2) };
unsafe { list.push_front_unchecked(&mut element1) };
unsafe { list.filter(|element| element.value != 1) };
unsafe { validate_list(&list, &[2, 3]) }
}
#[test]
fn filter_removes_middle_correctly() -> unittest::Result<()> {
let mut element1 = TestMember {
value: 1,
link: Link::new(),
};
let mut element2 = TestMember {
value: 2,
link: Link::new(),
};
let mut element3 = TestMember {
value: 3,
link: Link::new(),
};
let mut list = UnsafeList::<TestMember, TestAdapter>::new();
unsafe { list.push_front_unchecked(&mut element3) };
unsafe { list.push_front_unchecked(&mut element2) };
unsafe { list.push_front_unchecked(&mut element1) };
unsafe { list.filter(|element| element.value != 2) };
unsafe { validate_list(&list, &[1, 3]) }
}
#[test]
fn filter_removes_tail_correctly() -> unittest::Result<()> {
let mut element1 = TestMember {
value: 1,
link: Link::new(),
};
let mut element2 = TestMember {
value: 2,
link: Link::new(),
};
let mut element3 = TestMember {
value: 3,
link: Link::new(),
};
let mut list = UnsafeList::<TestMember, TestAdapter>::new();
unsafe { list.push_front_unchecked(&mut element3) };
unsafe { list.push_front_unchecked(&mut element2) };
unsafe { list.push_front_unchecked(&mut element1) };
unsafe { list.filter(|element| element.value != 3) };
unsafe { validate_list(&list, &[1, 2]) }
}