test_utils.rs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. use crate::{parser::Propagate, AmlContext, AmlValue, Handler};
  2. use alloc::boxed::Box;
  3. struct TestHandler;
  4. impl Handler for TestHandler {
  5. fn read_u8(&self, _address: usize) -> u8 {
  6. unimplemented!()
  7. }
  8. fn read_u16(&self, _address: usize) -> u16 {
  9. unimplemented!()
  10. }
  11. fn read_u32(&self, _address: usize) -> u32 {
  12. unimplemented!()
  13. }
  14. fn read_u64(&self, _address: usize) -> u64 {
  15. unimplemented!()
  16. }
  17. fn write_u8(&mut self, _address: usize, _value: u8) {
  18. unimplemented!()
  19. }
  20. fn write_u16(&mut self, _address: usize, _value: u16) {
  21. unimplemented!()
  22. }
  23. fn write_u32(&mut self, _address: usize, _value: u32) {
  24. unimplemented!()
  25. }
  26. fn write_u64(&mut self, _address: usize, _value: u64) {
  27. unimplemented!()
  28. }
  29. fn read_io_u8(&self, _port: u16) -> u8 {
  30. unimplemented!()
  31. }
  32. fn read_io_u16(&self, _port: u16) -> u16 {
  33. unimplemented!()
  34. }
  35. fn read_io_u32(&self, _port: u16) -> u32 {
  36. unimplemented!()
  37. }
  38. fn write_io_u8(&self, _port: u16, _value: u8) {
  39. unimplemented!()
  40. }
  41. fn write_io_u16(&self, _port: u16, _value: u16) {
  42. unimplemented!()
  43. }
  44. fn write_io_u32(&self, _port: u16, _value: u32) {
  45. unimplemented!()
  46. }
  47. fn read_pci_u8(&self, _segment: u16, _bus: u8, device: u8, _function: u8, _offset: u16) -> u8 {
  48. unimplemented!()
  49. }
  50. fn read_pci_u16(&self, _segment: u16, _bus: u8, device: u8, _function: u8, _offset: u16) -> u16 {
  51. unimplemented!()
  52. }
  53. fn read_pci_u32(&self, _segment: u16, _bus: u8, device: u8, _function: u8, _offset: u16) -> u32 {
  54. unimplemented!()
  55. }
  56. fn write_pci_u8(&self, _segment: u16, _bus: u8, device: u8, _function: u8, _offset: u16, _value: u8) {
  57. unimplemented!()
  58. }
  59. fn write_pci_u16(&self, _segment: u16, _bus: u8, device: u8, _function: u8, _offset: u16, _value: u16) {
  60. unimplemented!()
  61. }
  62. fn write_pci_u32(&self, _segment: u16, _bus: u8, device: u8, _function: u8, _offset: u16, _value: u32) {
  63. unimplemented!()
  64. }
  65. }
  66. pub(crate) fn make_test_context() -> AmlContext {
  67. AmlContext::new(Box::new(TestHandler), crate::DebugVerbosity::None)
  68. }
  69. pub(crate) macro check_err($parse: expr, $error: pat, $remains: expr) {
  70. match $parse {
  71. Ok((remains, _, result)) => panic!("Expected Err, got {:#?}. Remaining = {:#x?}", result, remains),
  72. Err((remains, _, Propagate::Err($error))) if *remains == *$remains => (),
  73. Err((remains, _, Propagate::Err($error))) => {
  74. panic!("Correct error, incorrect stream returned: {:#x?}", remains)
  75. }
  76. Err((_, _, err)) => panic!("Got wrong error: {:?}", err),
  77. }
  78. }
  79. pub(crate) macro check_ok($parse: expr, $expected: expr, $remains: expr) {
  80. match $parse {
  81. Ok((remains, _, ref result)) if remains == *$remains && result == &$expected => (),
  82. Ok((remains, _, ref result)) if result == &$expected => {
  83. panic!("Correct result, incorrect slice returned: {:x?}", remains)
  84. }
  85. Ok((_, _, ref result)) => panic!("Successfully parsed Ok, but it was wrong: {:#?}", result),
  86. Err((_, _, err)) => panic!("Expected Ok, got {:#?}", err),
  87. }
  88. }
  89. pub(crate) macro check_ok_value($parse: expr, $expected: expr, $remains: expr) {
  90. match $parse {
  91. Ok((remains, _, ref result)) if remains == *$remains && crudely_cmp_values(result, &$expected) => (),
  92. Ok((remains, _, ref result)) if crudely_cmp_values(result, &$expected) => {
  93. panic!("Correct result, incorrect slice returned: {:x?}", remains)
  94. }
  95. Ok((_, _, ref result)) => panic!("Successfully parsed Ok, but it was wrong: {:#?}", result),
  96. Err((_, _, err)) => panic!("Expected Ok, got {:#?}", err),
  97. }
  98. }
  99. /// This is a bad (but good for testing) way of comparing `AmlValue`s, which tests that they're exactly the same if
  100. /// it can, and gives up if it can't. It's useful in tests to be able to see if you're getting the `AmlValue` that
  101. /// you're expecting.
  102. ///
  103. /// NOTE: almost all of the `AmlValue` variants are `Eq`, and so for a long time, `AmlValue` implemented `Eq`.
  104. /// However, this is a footgun as, in the real interpreter, you rarely want to directly compare values, as you need
  105. /// to apply the AML value conversion rules to compare them correctly. This is therefore only useful for artificial
  106. /// testing scenarios.
  107. pub(crate) fn crudely_cmp_values(a: &AmlValue, b: &AmlValue) -> bool {
  108. use crate::value::MethodCode;
  109. match a {
  110. AmlValue::Boolean(a) => match b {
  111. AmlValue::Boolean(b) => a == b,
  112. _ => false,
  113. },
  114. AmlValue::Integer(a) => match b {
  115. AmlValue::Integer(b) => a == b,
  116. _ => false,
  117. },
  118. AmlValue::String(ref a) => match b {
  119. AmlValue::String(ref b) => a == b,
  120. _ => false,
  121. },
  122. AmlValue::OpRegion { region, offset, length, parent_device } => match b {
  123. AmlValue::OpRegion {
  124. region: b_region,
  125. offset: b_offset,
  126. length: b_length,
  127. parent_device: b_parent_device,
  128. } => {
  129. region == b_region && offset == b_offset && length == b_length && parent_device == b_parent_device
  130. }
  131. _ => false,
  132. },
  133. AmlValue::Field { region, flags, offset, length } => match b {
  134. AmlValue::Field { region: b_region, flags: b_flags, offset: b_offset, length: b_length } => {
  135. region == b_region && flags == b_flags && offset == b_offset && length == b_length
  136. }
  137. _ => false,
  138. },
  139. AmlValue::Method { flags, code } => match b {
  140. AmlValue::Method { flags: b_flags, code: b_code } => {
  141. if flags != b_flags {
  142. return false;
  143. }
  144. match (code, b_code) {
  145. (MethodCode::Aml(a), MethodCode::Aml(b)) => a == b,
  146. (MethodCode::Aml(_), MethodCode::Native(_)) => false,
  147. (MethodCode::Native(_), MethodCode::Aml(_)) => false,
  148. (MethodCode::Native(_), MethodCode::Native(_)) => panic!("Can't compare two native methods"),
  149. }
  150. }
  151. _ => false,
  152. },
  153. AmlValue::Buffer(a) => match b {
  154. AmlValue::Buffer(b) => a == b,
  155. _ => false,
  156. },
  157. AmlValue::Processor { id, pblk_address, pblk_len } => match b {
  158. AmlValue::Processor { id: b_id, pblk_address: b_pblk_address, pblk_len: b_pblk_len } => {
  159. id == b_id && pblk_address == b_pblk_address && pblk_len == b_pblk_len
  160. }
  161. _ => false,
  162. },
  163. AmlValue::Mutex { sync_level } => match b {
  164. AmlValue::Mutex { sync_level: b_sync_level } => sync_level == b_sync_level,
  165. _ => false,
  166. },
  167. AmlValue::Package(a) => match b {
  168. AmlValue::Package(b) => {
  169. for (a, b) in a.iter().zip(b) {
  170. if crudely_cmp_values(a, b) == false {
  171. return false;
  172. }
  173. }
  174. true
  175. }
  176. _ => false,
  177. },
  178. }
  179. }