blob: 394191813c29d540dde58a03329e3371d2aa67ab [file] [log] [blame]
// 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..
use sgx_types::*;
use std::string::String;
use std::vec::Vec;
use sgx_trts::ascii::AsciiExt;
use sgx_trts::c_str::*;
use sgx_trts::enclave::*;
use sgx_trts::error;
use sgx_trts::libc;
use sgx_trts::memchr;
use sgx_trts::trts::*;
use sgx_trts::veh::*;
//Only during dev
//use core::mem;
global_ctors_object! {
VARNAME, func_name = {()}
}
// veh
extern "C" fn sample_exception_handler(_: *mut sgx_exception_info_t) -> int32_t {
0
}
pub fn test_rsgx_get_thread_policy() {
assert_eq!(rsgx_get_thread_policy(), SgxThreadPolicy::Bound);
}
pub fn test_trts_sizes() {
//Only during dev
//assert_eq!(mem::size_of::<global_data_t>(), 1488);
//assert_eq!(mem::size_of::<thread_data_t>(), 160);
}
pub fn test_register_first_exception_handler() {
let handle = rsgx_register_exception_handler(1, sample_exception_handler);
assert!(handle.is_some());
assert_eq!(rsgx_unregister_exception_handler(handle.unwrap()), true);
}
pub fn test_register_last_exception_handler() {
let handle = rsgx_register_exception_handler(0, sample_exception_handler);
assert!(handle.is_some());
assert_eq!(rsgx_unregister_exception_handler(handle.unwrap()), true);
}
pub fn test_register_multiple_exception_handler() {
let mut handler_vec: Vec<exception_handle> = Vec::new();
let ntest: usize = 100;
for i in 0..ntest {
let handle = rsgx_register_exception_handler(i as uint32_t % 2, sample_exception_handler);
assert!(handle.is_some());
handler_vec.push(handle.unwrap());
}
for i in 0..ntest {
let h = handler_vec[i];
assert_eq!(rsgx_unregister_exception_handler(h), true);
}
for i in 0..ntest {
let h = handler_vec[i];
assert_eq!(rsgx_unregister_exception_handler(h), false);
}
}
// trts
pub fn test_read_rand() {
let mut rand_arr = [0; 100];
assert_eq!(rsgx_read_rand(&mut rand_arr[..]), Ok(()));
// Cannot all be zero
let cmp = [0; 100].iter().zip(rand_arr.iter()).all(|(x, y)| x == y);
assert_ne!(cmp, true);
}
pub fn test_data_is_within_enclave() {
#[allow(dead_code)]
#[derive(Clone, Copy)]
struct SampleDs {
x: i32,
y: i32,
z: [i32; 100],
}
unsafe impl marker::ContiguousMemory for SampleDs {}
let mut sample_object: SampleDs = SampleDs {
x: 0,
y: 0,
z: [0; 100],
};
sample_object.x = 100;
sample_object.y = 100;
sample_object.z[0] = 100;
assert_eq!(rsgx_data_is_within_enclave(&sample_object), true);
let ooo;
unsafe {
let ppp = 0xdeadbeafdeadbeaf as *const u8;
ooo = &*ppp;
}
assert_eq!(rsgx_data_is_within_enclave(ooo), false);
}
pub fn test_slice_is_within_enlave() {
let one_array = [0; 100];
assert_eq!(rsgx_slice_is_within_enclave(&one_array[..]), true);
// TODO: Not compiling
//let mut ooo : &[u8];
//unsafe {
// let ppp = 0xdeadbeafdeadbeaf as * const [u8];
// ooo = &*ppp;
//}
//assert_eq!(rsgx_slice_is_within_enclave(ooo), false);
}
pub fn test_raw_is_within_enclave() {
assert_eq!(
rsgx_raw_is_within_enclave(test_raw_is_within_enclave as *const u8, 10),
true
);
assert_eq!(
rsgx_raw_is_within_enclave(0xdeadbeafdeadbeaf as *const u8, 10),
false
);
}
pub fn test_data_is_outside_enclave() {
#[allow(dead_code)]
#[derive(Clone, Copy)]
struct SampleDs {
x: i32,
y: i32,
z: [i32; 100],
}
unsafe impl marker::ContiguousMemory for SampleDs {}
let mut sample_object: SampleDs = SampleDs {
x: 0,
y: 0,
z: [0; 100],
};
sample_object.x = 100;
sample_object.y = 100;
sample_object.z[0] = 100;
assert_eq!(rsgx_data_is_outside_enclave(&sample_object), false);
let ooo;
unsafe {
let ppp = 0xdeadbeafdeadbeaf as *const u8;
ooo = &*ppp;
}
assert_eq!(rsgx_data_is_outside_enclave(ooo), true);
}
pub fn test_slice_is_outside_enclave() {
let one_array = [0; 100];
assert_eq!(rsgx_slice_is_outside_enclave(&one_array[..]), false);
// TODO: Not compiling
//let mut ooo : &[u8];
//unsafe {
// let ppp = 0xdeadbeafdeadbeaf as * const [u8];
// ooo = &*ppp;
//}
//assert_eq!(rsgx_slice_is_within_enclave(ooo), true);
}
pub fn test_raw_is_outside_enclave() {
assert_eq!(
rsgx_raw_is_outside_enclave(test_raw_is_outside_enclave as *const u8, 10),
false
);
assert_eq!(
rsgx_raw_is_outside_enclave(0xdeadbeafdeadbeaf as *const u8, 10),
true
);
}
// macros
pub fn test_global_ctors_object() {
assert_eq!(VARNAME(), ());
}
// oom
// I don't think we can test oom
// error
pub fn test_error() {
// XXX: Top 11 should be the same in all unix?
let errorinfo_vec: Vec<(i32, &'static str)> = vec![
(1, "Operation not permitted"),
(2, "No such file or directory"),
(3, "No such process"),
(4, "Interrupted system call"),
(5, "Input/output error"),
(6, "Device not configured"),
(7, "Argument list too long"),
(8, "Exec format error"),
(9, "Bad file descriptor"),
(10, "No child processes"),
(11, "Resource deadlock avoided"),
];
for case in errorinfo_vec {
let mut buf: [i8; 64] = [0; 64];
error::set_errno(case.0);
unsafe {
error::error_string(error::errno(), &mut buf[..]);
}
let answer: Vec<u8> = buf.iter().map(|&x| x as u8).collect();
let ans_str = String::from_utf8(answer).unwrap();
assert_eq!(ans_str.trim_matches('\0'), case.1);
}
}
// libc
pub fn test_rts_libc_memchr() {
let test_str = "abcdedfg";
assert_eq!(
unsafe { libc::memchr(test_str.as_ptr() as *const u8, 'd' as u8, test_str.len()) },
test_str[3..].as_ptr()
);
assert_eq!(
unsafe { libc::memchr("abcdefg".as_ptr() as *const u8, 'z' as u8, test_str.len()) },
0 as *const u8
);
}
pub fn test_rts_libc_memrchr() {
let test_str = "abcdedfg";
assert_eq!(
unsafe { libc::memrchr(test_str.as_ptr() as *const u8, 'd' as u8, test_str.len()) },
test_str[5..].as_ptr()
);
assert_eq!(
unsafe { libc::memrchr("abcdefg".as_ptr() as *const u8, 'z' as u8, test_str.len()) },
0 as *const u8
);
}
// memchr
pub fn test_rts_memchr_memchr() {
let test_str = "abcdedfg".as_bytes();
let needle = 'd' as u8;
assert_eq!(memchr::memchr(needle, test_str), Some(3));
let needle = 'z' as u8;
assert_eq!(memchr::memchr(needle, test_str), None);
}
pub fn test_rts_memchr_memrchr() {
let test_str = "abcdedfg".as_bytes();
let needle = 'd' as u8;
assert_eq!(memchr::memrchr(needle, test_str), Some(5));
let needle = 'z' as u8;
assert_eq!(memchr::memrchr(needle, test_str), None);
}
// ascii
pub fn test_ascii() {
assert_eq!("café".to_ascii_uppercase(), "CAFÉ");
assert_eq!("café".to_ascii_uppercase(), "CAFé");
let ascii = 'a';
let non_ascii = '❤';
let int_ascii = 97;
assert!(ascii.is_ascii());
assert!(!non_ascii.is_ascii());
assert!(int_ascii.is_ascii());
assert_eq!('A', ascii.to_ascii_uppercase());
assert_eq!('❤', non_ascii.to_ascii_uppercase());
assert_eq!(65, int_ascii.to_ascii_uppercase());
let ascii = 'A';
let non_ascii = '❤';
let int_ascii = 65;
assert_eq!('a', ascii.to_ascii_lowercase());
assert_eq!('❤', non_ascii.to_ascii_lowercase());
assert_eq!(97, int_ascii.to_ascii_lowercase());
let ascii1 = 'A';
let ascii2 = 'a';
let ascii3 = 'A';
let ascii4 = 'z';
assert!(ascii1.eq_ignore_ascii_case(&ascii2));
assert!(ascii1.eq_ignore_ascii_case(&ascii3));
assert!(!ascii1.eq_ignore_ascii_case(&ascii4));
let mut ascii = 'a';
ascii.make_ascii_uppercase();
assert_eq!('A', ascii);
let mut ascii = 'A';
ascii.make_ascii_lowercase();
assert_eq!('a', ascii);
}
// c_str
pub fn test_cstr() {
let c_string = CString::new("foo").unwrap();
let ptr = c_string.into_raw();
unsafe {
assert_eq!(b'f', *ptr as u8);
assert_eq!(b'o', *ptr.offset(1) as u8);
assert_eq!(b'o', *ptr.offset(2) as u8);
assert_eq!(b'\0', *ptr.offset(3) as u8);
// retake pointer to free memory
let _ = CString::from_raw(ptr);
}
let c_string = CString::new("foo").unwrap();
let bytes = c_string.into_bytes();
assert_eq!(bytes, vec![b'f', b'o', b'o']);
let c_string = CString::new("foo").unwrap();
let bytes = c_string.into_bytes_with_nul();
assert_eq!(bytes, vec![b'f', b'o', b'o', b'\0']);
let c_string = CString::new("foo").unwrap();
let bytes = c_string.as_bytes();
assert_eq!(bytes, &[b'f', b'o', b'o']);
let c_string = CString::new("foo").unwrap();
let bytes = c_string.as_bytes_with_nul();
assert_eq!(bytes, &[b'f', b'o', b'o', b'\0']);
let c_string = CString::new(b"foo".to_vec()).unwrap();
let c_str = c_string.as_c_str();
assert_eq!(c_str, CStr::from_bytes_with_nul(b"foo\0").unwrap());
let c_string = CString::new(b"foo".to_vec()).unwrap();
let boxed = c_string.into_boxed_c_str();
assert_eq!(&*boxed, CStr::from_bytes_with_nul(b"foo\0").unwrap());
let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap();
assert_eq!(c_str.to_bytes(), b"foo");
let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap();
assert_eq!(c_str.to_bytes_with_nul(), b"foo\0");
let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap();
assert_eq!(c_str.to_str(), Ok("foo"));
let c_str = CStr::from_bytes_with_nul(b"Hello World\0").unwrap();
assert_eq!(c_str.to_string_lossy(), Cow::Borrowed("Hello World"));
use std::borrow::Cow;
let c_str = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0").unwrap();
assert_eq!(
c_str.to_string_lossy(),
Cow::Owned(String::from("Hello �World")) as Cow<str>
);
}