Bytes.t.sol 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.20;
  3. import {Test} from "forge-std/Test.sol";
  4. import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
  5. import {Bytes} from "@openzeppelin/contracts/utils/Bytes.sol";
  6. contract BytesTest is Test {
  7. using Bytes for bytes;
  8. function testSliceWithStartOnly(bytes memory buffer, uint256 start) public pure {
  9. bytes memory originalBuffer = bytes.concat(buffer);
  10. bytes memory result = buffer.slice(start);
  11. // Original buffer was not modified
  12. assertEq(buffer, originalBuffer);
  13. // Should return bytes from start to end
  14. assertEq(result.length, Math.saturatingSub(buffer.length, start));
  15. // Verify content matches
  16. for (uint256 i = 0; i < result.length; ++i) {
  17. assertEq(result[i], buffer[start + i]);
  18. }
  19. }
  20. function testSlice(bytes memory buffer, uint256 start, uint256 end) public pure {
  21. bytes memory originalBuffer = bytes.concat(buffer);
  22. bytes memory result = buffer.slice(start, end);
  23. // Original buffer was not modified
  24. assertEq(buffer, originalBuffer);
  25. // Calculate expected bounds after sanitization
  26. uint256 sanitizedEnd = Math.min(end, buffer.length);
  27. uint256 sanitizedStart = Math.min(start, sanitizedEnd);
  28. uint256 expectedLength = sanitizedEnd - sanitizedStart;
  29. assertEq(result.length, expectedLength);
  30. // Verify content matches when there's content to verify
  31. for (uint256 i = 0; i < result.length; ++i) {
  32. assertEq(result[i], buffer[sanitizedStart + i]);
  33. }
  34. }
  35. function testSpliceWithStartOnly(bytes memory buffer, uint256 start) public pure {
  36. bytes memory originalBuffer = bytes.concat(buffer);
  37. bytes memory result = buffer.splice(start);
  38. // Result should be the same object as input (modified in place)
  39. assertEq(result, buffer);
  40. // Should contain bytes from start to end, moved to beginning
  41. assertEq(result.length, Math.saturatingSub(originalBuffer.length, start));
  42. // Verify content matches moved content
  43. for (uint256 i = 0; i < result.length; ++i) {
  44. assertEq(result[i], originalBuffer[start + i]);
  45. }
  46. }
  47. function testSplice(bytes memory buffer, uint256 start, uint256 end) public pure {
  48. bytes memory originalBuffer = bytes.concat(buffer);
  49. bytes memory result = buffer.splice(start, end);
  50. // Result should be the same object as input (modified in place)
  51. assertEq(result, buffer);
  52. // Calculate expected bounds after sanitization
  53. uint256 sanitizedEnd = Math.min(end, originalBuffer.length);
  54. uint256 sanitizedStart = Math.min(start, sanitizedEnd);
  55. uint256 expectedLength = sanitizedEnd - sanitizedStart;
  56. assertEq(result.length, expectedLength);
  57. // Verify content matches moved content
  58. for (uint256 i = 0; i < result.length; ++i) {
  59. assertEq(result[i], originalBuffer[sanitizedStart + i]);
  60. }
  61. }
  62. // REVERSE BITS
  63. function testSymbolicReverseBytes32(bytes32 value) public pure {
  64. assertEq(Bytes.reverseBytes32(Bytes.reverseBytes32(value)), value);
  65. }
  66. function testSymbolicReverseBytes16(bytes16 value) public pure {
  67. assertEq(Bytes.reverseBytes16(Bytes.reverseBytes16(value)), value);
  68. }
  69. function testSymbolicReverseBytes16Dirty(bytes16 value) public pure {
  70. assertEq(Bytes.reverseBytes16(Bytes.reverseBytes16(_dirtyBytes16(value))), value);
  71. assertEq(Bytes.reverseBytes16(_dirtyBytes16(Bytes.reverseBytes16(value))), value);
  72. }
  73. function testSymbolicReverseBytes8(bytes8 value) public pure {
  74. assertEq(Bytes.reverseBytes8(Bytes.reverseBytes8(value)), value);
  75. }
  76. function testSymbolicReverseBytes8Dirty(bytes8 value) public pure {
  77. assertEq(Bytes.reverseBytes8(Bytes.reverseBytes8(_dirtyBytes8(value))), value);
  78. assertEq(Bytes.reverseBytes8(_dirtyBytes8(Bytes.reverseBytes8(value))), value);
  79. }
  80. function testSymbolicReverseBytes4(bytes4 value) public pure {
  81. assertEq(Bytes.reverseBytes4(Bytes.reverseBytes4(value)), value);
  82. }
  83. function testSymbolicReverseBytes4Dirty(bytes4 value) public pure {
  84. assertEq(Bytes.reverseBytes4(Bytes.reverseBytes4(_dirtyBytes4(value))), value);
  85. assertEq(Bytes.reverseBytes4(_dirtyBytes4(Bytes.reverseBytes4(value))), value);
  86. }
  87. function testSymbolicReverseBytes2(bytes2 value) public pure {
  88. assertEq(Bytes.reverseBytes2(Bytes.reverseBytes2(value)), value);
  89. }
  90. function testSymbolicReverseBytes2Dirty(bytes2 value) public pure {
  91. assertEq(Bytes.reverseBytes2(Bytes.reverseBytes2(_dirtyBytes2(value))), value);
  92. assertEq(Bytes.reverseBytes2(_dirtyBytes2(Bytes.reverseBytes2(value))), value);
  93. }
  94. // Helpers
  95. function _dirtyBytes16(bytes16 value) private pure returns (bytes16 dirty) {
  96. assembly ("memory-safe") {
  97. dirty := or(value, shr(128, not(0)))
  98. }
  99. }
  100. function _dirtyBytes8(bytes8 value) private pure returns (bytes8 dirty) {
  101. assembly ("memory-safe") {
  102. dirty := or(value, shr(192, not(0)))
  103. }
  104. }
  105. function _dirtyBytes4(bytes4 value) private pure returns (bytes4 dirty) {
  106. assembly ("memory-safe") {
  107. dirty := or(value, shr(224, not(0)))
  108. }
  109. }
  110. function _dirtyBytes2(bytes2 value) private pure returns (bytes2 dirty) {
  111. assembly ("memory-safe") {
  112. dirty := or(value, shr(240, not(0)))
  113. }
  114. }
  115. }