int64_test.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /**
  2. * @fileoverview Tests for Int64.
  3. */
  4. goog.module('protobuf.Int64Test');
  5. goog.setTestOnly();
  6. const Int64 = goog.require('protobuf.Int64');
  7. const Long = goog.require('goog.math.Long');
  8. describe('Int64', () => {
  9. it('can be constructed from bits', () => {
  10. const int64 = Int64.fromBits(0, 1);
  11. expect(int64.getLowBits()).toEqual(0);
  12. expect(int64.getHighBits()).toEqual(1);
  13. });
  14. it('zero is defined', () => {
  15. const int64 = Int64.getZero();
  16. expect(int64.getLowBits()).toEqual(0);
  17. expect(int64.getHighBits()).toEqual(0);
  18. });
  19. it('max value is defined', () => {
  20. const int64 = Int64.getMaxValue();
  21. expect(int64).toEqual(Int64.fromBits(0xFFFFFFFF, 0x7FFFFFFF));
  22. expect(int64.asLong()).toEqual(Long.getMaxValue());
  23. });
  24. it('min value is defined', () => {
  25. const int64 = Int64.getMinValue();
  26. expect(int64).toEqual(Int64.fromBits(0, 0x80000000));
  27. expect(int64.asLong()).toEqual(Long.getMinValue());
  28. });
  29. it('Can be converted to long', () => {
  30. const int64 = Int64.fromInt(1);
  31. expect(int64.asLong()).toEqual(Long.fromInt(1));
  32. });
  33. it('Negative value can be converted to long', () => {
  34. const int64 = Int64.fromInt(-1);
  35. expect(int64.getLowBits()).toEqual(0xFFFFFFFF | 0);
  36. expect(int64.getHighBits()).toEqual(0xFFFFFFFF | 0);
  37. expect(int64.asLong()).toEqual(Long.fromInt(-1));
  38. });
  39. it('Can be converted to number', () => {
  40. const int64 = Int64.fromInt(1);
  41. expect(int64.asNumber()).toEqual(1);
  42. });
  43. it('Can convert negative value to number', () => {
  44. const int64 = Int64.fromInt(-1);
  45. expect(int64.asNumber()).toEqual(-1);
  46. });
  47. it('MAX_SAFE_INTEGER can be used.', () => {
  48. const int64 = Int64.fromNumber(Number.MAX_SAFE_INTEGER);
  49. expect(int64.getLowBitsUnsigned()).toEqual(0xFFFFFFFF);
  50. expect(int64.getHighBits()).toEqual(0x1FFFFF);
  51. expect(int64.asNumber()).toEqual(Number.MAX_SAFE_INTEGER);
  52. });
  53. it('MIN_SAFE_INTEGER can be used.', () => {
  54. const int64 = Int64.fromNumber(Number.MIN_SAFE_INTEGER);
  55. expect(int64.asNumber()).toEqual(Number.MIN_SAFE_INTEGER);
  56. });
  57. it('constructs fromInt', () => {
  58. const int64 = Int64.fromInt(1);
  59. expect(int64.getLowBits()).toEqual(1);
  60. expect(int64.getHighBits()).toEqual(0);
  61. });
  62. it('constructs fromLong', () => {
  63. const int64 = Int64.fromLong(Long.fromInt(1));
  64. expect(int64.getLowBits()).toEqual(1);
  65. expect(int64.getHighBits()).toEqual(0);
  66. });
  67. // TODO: Use our own checking system here.
  68. if (goog.DEBUG) {
  69. it('asNumber throws for MAX_SAFE_INTEGER + 1', () => {
  70. expect(() => Int64.fromNumber(Number.MAX_SAFE_INTEGER + 1).asNumber())
  71. .toThrow();
  72. });
  73. it('fromInt(MAX_SAFE_INTEGER) throws', () => {
  74. expect(() => Int64.fromInt(Number.MAX_SAFE_INTEGER)).toThrow();
  75. });
  76. it('fromInt(1.5) throws', () => {
  77. expect(() => Int64.fromInt(1.5)).toThrow();
  78. });
  79. }
  80. const decimalHexPairs = {
  81. '0x0000000000000000': {signed: '0'},
  82. '0x0000000000000001': {signed: '1'},
  83. '0x00000000ffffffff': {signed: '4294967295'},
  84. '0x0000000100000000': {signed: '4294967296'},
  85. '0xffffffffffffffff': {signed: '-1', unsigned: '18446744073709551615'},
  86. '0x8000000000000000':
  87. {signed: '-9223372036854775808', unsigned: '9223372036854775808'},
  88. '0x8000000080000000':
  89. {signed: '-9223372034707292160', unsigned: '9223372039002259456'},
  90. '0x01b69b4bacd05f15': {signed: '123456789123456789'},
  91. '0xfe4964b4532fa0eb':
  92. {signed: '-123456789123456789', unsigned: '18323287284586094827'},
  93. '0xa5a5a5a5a5a5a5a5':
  94. {signed: '-6510615555426900571', unsigned: '11936128518282651045'},
  95. '0x5a5a5a5a5a5a5a5a': {signed: '6510615555426900570'},
  96. '0xffffffff00000000':
  97. {signed: '-4294967296', unsigned: '18446744069414584320'},
  98. };
  99. it('serializes to signed decimal strings', () => {
  100. for (const [hex, decimals] of Object.entries(decimalHexPairs)) {
  101. const int64 = hexToInt64(hex);
  102. expect(int64.toSignedDecimalString()).toEqual(decimals.signed);
  103. }
  104. });
  105. it('serializes to unsigned decimal strings', () => {
  106. for (const [hex, decimals] of Object.entries(decimalHexPairs)) {
  107. const int64 = hexToInt64(hex);
  108. expect(int64.toUnsignedDecimalString())
  109. .toEqual(decimals.unsigned || decimals.signed);
  110. }
  111. });
  112. it('serializes to unsigned hex strings', () => {
  113. for (const [hex, decimals] of Object.entries(decimalHexPairs)) {
  114. const int64 = hexToInt64(hex);
  115. let shortHex = hex.replace(/0x0*/, '0x');
  116. if (shortHex == '0x') {
  117. shortHex = '0x0';
  118. }
  119. expect(int64.toHexString()).toEqual(shortHex);
  120. }
  121. });
  122. it('parses decimal strings', () => {
  123. for (const [hex, decimals] of Object.entries(decimalHexPairs)) {
  124. const signed = Int64.fromDecimalString(decimals.signed);
  125. expect(int64ToHex(signed)).toEqual(hex);
  126. if (decimals.unsigned) {
  127. const unsigned = Int64.fromDecimalString(decimals.unsigned);
  128. expect(int64ToHex(unsigned)).toEqual(hex);
  129. }
  130. }
  131. });
  132. it('parses hex strings', () => {
  133. for (const [hex, decimals] of Object.entries(decimalHexPairs)) {
  134. expect(int64ToHex(Int64.fromHexString(hex))).toEqual(hex);
  135. }
  136. expect(int64ToHex(Int64.fromHexString('-0x1')))
  137. .toEqual('0xffffffffffffffff');
  138. });
  139. // TODO: Use our own checking system here.
  140. if (goog.DEBUG) {
  141. it('throws when parsing empty string', () => {
  142. expect(() => Int64.fromDecimalString('')).toThrow();
  143. });
  144. it('throws when parsing float string', () => {
  145. expect(() => Int64.fromDecimalString('1.5')).toThrow();
  146. });
  147. it('throws when parsing non-numeric string', () => {
  148. expect(() => Int64.fromDecimalString('0xa')).toThrow();
  149. });
  150. }
  151. it('checks if equal', () => {
  152. const low = Int64.fromInt(1);
  153. const high = Int64.getMaxValue();
  154. expect(low.equals(Int64.fromInt(1))).toEqual(true);
  155. expect(low.equals(high)).toEqual(false);
  156. expect(high.equals(Int64.getMaxValue())).toEqual(true);
  157. });
  158. it('returns unique hashcode', () => {
  159. expect(Int64.fromInt(1).hashCode()).toEqual(Int64.fromInt(1).hashCode());
  160. expect(Int64.fromInt(1).hashCode())
  161. .not.toEqual(Int64.fromInt(2).hashCode());
  162. });
  163. });
  164. /**
  165. * @param {string} hexString
  166. * @return {!Int64}
  167. */
  168. function hexToInt64(hexString) {
  169. const high = hexString.slice(2, 10);
  170. const low = hexString.slice(10);
  171. return Int64.fromBits(parseInt(low, 16), parseInt(high, 16));
  172. }
  173. /**
  174. * @param {!Int64} int64
  175. * @return {string}
  176. */
  177. function int64ToHex(int64) {
  178. const ZEROS_32_BIT = '00000000';
  179. const highPartialHex = int64.getHighBitsUnsigned().toString(16);
  180. const lowPartialHex = int64.getLowBitsUnsigned().toString(16);
  181. const highHex = ZEROS_32_BIT.slice(highPartialHex.length) + highPartialHex;
  182. const lowHex = ZEROS_32_BIT.slice(lowPartialHex.length) + lowPartialHex;
  183. return `0x${highHex}${lowHex}`;
  184. }