PageRenderTime 41ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/core/src/test/java/com/google/bitcoin/uri/BitcoinURITest.java

https://code.google.com/
Java | 419 lines | 362 code | 24 blank | 33 comment | 0 complexity | 8ec65c20d817938551cca209d6b879cc MD5 | raw file
Possible License(s): Apache-2.0
  1. /*
  2. * Copyright 2012 the original author or authors.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. */
  18. package com.google.bitcoin.uri;
  19. import com.google.bitcoin.core.Address;
  20. import com.google.bitcoin.core.Utils;
  21. import com.google.bitcoin.params.MainNetParams;
  22. import com.google.bitcoin.params.TestNet3Params;
  23. import org.junit.Test;
  24. import java.io.UnsupportedEncodingException;
  25. import static org.junit.Assert.*;
  26. public class BitcoinURITest {
  27. private BitcoinURI testObject = null;
  28. private static final String MAINNET_GOOD_ADDRESS = "1KzTSfqjF2iKCduwz59nv2uqh1W2JsTxZH";
  29. @Test
  30. public void testConvertToBitcoinURI() throws Exception {
  31. Address goodAddress = new Address(MainNetParams.get(), MAINNET_GOOD_ADDRESS);
  32. // simple example
  33. assertEquals("bitcoin:" + MAINNET_GOOD_ADDRESS + "?amount=12.34&label=Hello&message=AMessage", BitcoinURI.convertToBitcoinURI(goodAddress, Utils.toNanoCoins("12.34"), "Hello", "AMessage"));
  34. // example with spaces, ampersand and plus
  35. assertEquals("bitcoin:" + MAINNET_GOOD_ADDRESS + "?amount=12.34&label=Hello%20World&message=Mess%20%26%20age%20%2B%20hope", BitcoinURI.convertToBitcoinURI(goodAddress, Utils.toNanoCoins("12.34"), "Hello World", "Mess & age + hope"));
  36. // no amount, label present, message present
  37. assertEquals("bitcoin:" + MAINNET_GOOD_ADDRESS + "?label=Hello&message=glory", BitcoinURI.convertToBitcoinURI(goodAddress, null, "Hello", "glory"));
  38. // amount present, no label, message present
  39. assertEquals("bitcoin:" + MAINNET_GOOD_ADDRESS + "?amount=0.1&message=glory", BitcoinURI.convertToBitcoinURI(goodAddress, Utils.toNanoCoins("0.1"), null, "glory"));
  40. assertEquals("bitcoin:" + MAINNET_GOOD_ADDRESS + "?amount=0.1&message=glory", BitcoinURI.convertToBitcoinURI(goodAddress, Utils.toNanoCoins("0.1"), "", "glory"));
  41. // amount present, label present, no message
  42. assertEquals("bitcoin:" + MAINNET_GOOD_ADDRESS + "?amount=12.34&label=Hello", BitcoinURI.convertToBitcoinURI(goodAddress, Utils.toNanoCoins("12.34"), "Hello", null));
  43. assertEquals("bitcoin:" + MAINNET_GOOD_ADDRESS + "?amount=12.34&label=Hello", BitcoinURI.convertToBitcoinURI(goodAddress, Utils.toNanoCoins("12.34"), "Hello", ""));
  44. // amount present, no label, no message
  45. assertEquals("bitcoin:" + MAINNET_GOOD_ADDRESS + "?amount=1000", BitcoinURI.convertToBitcoinURI(goodAddress, Utils.toNanoCoins("1000"), null, null));
  46. assertEquals("bitcoin:" + MAINNET_GOOD_ADDRESS + "?amount=1000", BitcoinURI.convertToBitcoinURI(goodAddress, Utils.toNanoCoins("1000"), "", ""));
  47. // no amount, label present, no message
  48. assertEquals("bitcoin:" + MAINNET_GOOD_ADDRESS + "?label=Hello", BitcoinURI.convertToBitcoinURI(goodAddress, null, "Hello", null));
  49. // no amount, no label, message present
  50. assertEquals("bitcoin:" + MAINNET_GOOD_ADDRESS + "?message=Agatha", BitcoinURI.convertToBitcoinURI(goodAddress, null, null, "Agatha"));
  51. assertEquals("bitcoin:" + MAINNET_GOOD_ADDRESS + "?message=Agatha", BitcoinURI.convertToBitcoinURI(goodAddress, null, "", "Agatha"));
  52. // no amount, no label, no message
  53. assertEquals("bitcoin:" + MAINNET_GOOD_ADDRESS, BitcoinURI.convertToBitcoinURI(goodAddress, null, null, null));
  54. assertEquals("bitcoin:" + MAINNET_GOOD_ADDRESS, BitcoinURI.convertToBitcoinURI(goodAddress, null, "", ""));
  55. }
  56. @Test
  57. public void testGood_Simple() throws BitcoinURIParseException {
  58. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS);
  59. assertNotNull(testObject);
  60. assertNull("Unexpected amount", testObject.getAmount());
  61. assertNull("Unexpected label", testObject.getLabel());
  62. assertEquals("Unexpected label", 20, testObject.getAddress().getHash160().length);
  63. }
  64. /**
  65. * Test a broken URI (bad scheme)
  66. */
  67. @Test
  68. public void testBad_Scheme() {
  69. try {
  70. testObject = new BitcoinURI(MainNetParams.get(), "blimpcoin:" + MAINNET_GOOD_ADDRESS);
  71. fail("Expecting BitcoinURIParseException");
  72. } catch (BitcoinURIParseException e) {
  73. }
  74. }
  75. /**
  76. * Test a broken URI (bad syntax)
  77. */
  78. @Test
  79. public void testBad_BadSyntax() {
  80. // Various illegal characters
  81. try {
  82. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + "|" + MAINNET_GOOD_ADDRESS);
  83. fail("Expecting BitcoinURIParseException");
  84. } catch (BitcoinURIParseException e) {
  85. assertTrue(e.getMessage().contains("Bad URI syntax"));
  86. }
  87. try {
  88. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS + "\\");
  89. fail("Expecting BitcoinURIParseException");
  90. } catch (BitcoinURIParseException e) {
  91. assertTrue(e.getMessage().contains("Bad URI syntax"));
  92. }
  93. // Separator without field
  94. try {
  95. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":");
  96. fail("Expecting BitcoinURIParseException");
  97. } catch (BitcoinURIParseException e) {
  98. assertTrue(e.getMessage().contains("Bad URI syntax"));
  99. }
  100. }
  101. /**
  102. * Test a broken URI (missing address)
  103. */
  104. @Test
  105. public void testBad_Address() {
  106. try {
  107. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME);
  108. fail("Expecting BitcoinURIParseException");
  109. } catch (BitcoinURIParseException e) {
  110. }
  111. }
  112. /**
  113. * Test a broken URI (bad address type)
  114. */
  115. @Test
  116. public void testBad_IncorrectAddressType() {
  117. try {
  118. testObject = new BitcoinURI(TestNet3Params.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS);
  119. fail("Expecting BitcoinURIParseException");
  120. } catch (BitcoinURIParseException e) {
  121. assertTrue(e.getMessage().contains("Bad address"));
  122. }
  123. }
  124. /**
  125. * Handles a simple amount
  126. *
  127. * @throws BitcoinURIParseException
  128. * If something goes wrong
  129. */
  130. @Test
  131. public void testGood_Amount() throws BitcoinURIParseException {
  132. // Test the decimal parsing
  133. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
  134. + "?amount=6543210.12345678");
  135. assertEquals("654321012345678", testObject.getAmount().toString());
  136. // Test the decimal parsing
  137. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
  138. + "?amount=.12345678");
  139. assertEquals("12345678", testObject.getAmount().toString());
  140. // Test the integer parsing
  141. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
  142. + "?amount=6543210");
  143. assertEquals("654321000000000", testObject.getAmount().toString());
  144. }
  145. /**
  146. * Handles a simple label
  147. *
  148. * @throws BitcoinURIParseException
  149. * If something goes wrong
  150. */
  151. @Test
  152. public void testGood_Label() throws BitcoinURIParseException {
  153. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
  154. + "?label=Hello%20World");
  155. assertEquals("Hello World", testObject.getLabel());
  156. }
  157. /**
  158. * Handles a simple label with an embedded ampersand and plus
  159. *
  160. * @throws BitcoinURIParseException
  161. * If something goes wrong
  162. * @throws UnsupportedEncodingException
  163. */
  164. @Test
  165. public void testGood_LabelWithAmpersandAndPlus() throws Exception {
  166. String testString = "Hello Earth & Mars + Venus";
  167. String encodedLabel = BitcoinURI.encodeURLString(testString);
  168. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS + "?label="
  169. + encodedLabel);
  170. assertEquals(testString, testObject.getLabel());
  171. }
  172. /**
  173. * Handles a Russian label (Unicode test)
  174. *
  175. * @throws BitcoinURIParseException
  176. * If something goes wrong
  177. * @throws UnsupportedEncodingException
  178. */
  179. @Test
  180. public void testGood_LabelWithRussian() throws Exception {
  181. // Moscow in Russian in Cyrillic
  182. String moscowString = "\u041c\u043e\u0441\u043a\u0432\u0430";
  183. String encodedLabel = BitcoinURI.encodeURLString(moscowString);
  184. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS + "?label="
  185. + encodedLabel);
  186. assertEquals(moscowString, testObject.getLabel());
  187. }
  188. /**
  189. * Handles a simple message
  190. *
  191. * @throws BitcoinURIParseException
  192. * If something goes wrong
  193. */
  194. @Test
  195. public void testGood_Message() throws BitcoinURIParseException {
  196. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
  197. + "?message=Hello%20World");
  198. assertEquals("Hello World", testObject.getMessage());
  199. }
  200. /**
  201. * Handles various well-formed combinations
  202. *
  203. * @throws BitcoinURIParseException
  204. * If something goes wrong
  205. */
  206. @Test
  207. public void testGood_Combinations() throws BitcoinURIParseException {
  208. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
  209. + "?amount=6543210&label=Hello%20World&message=Be%20well");
  210. assertEquals(
  211. "BitcoinURI['address'='1KzTSfqjF2iKCduwz59nv2uqh1W2JsTxZH','amount'='654321000000000','label'='Hello World','message'='Be well']",
  212. testObject.toString());
  213. }
  214. /**
  215. * Handles a badly formatted amount field
  216. *
  217. * @throws BitcoinURIParseException
  218. * If something goes wrong
  219. */
  220. @Test
  221. public void testBad_Amount() throws BitcoinURIParseException {
  222. // Missing
  223. try {
  224. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
  225. + "?amount=");
  226. fail("Expecting BitcoinURIParseException");
  227. } catch (BitcoinURIParseException e) {
  228. assertTrue(e.getMessage().contains("amount"));
  229. }
  230. // Non-decimal (BIP 21)
  231. try {
  232. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
  233. + "?amount=12X4");
  234. fail("Expecting BitcoinURIParseException");
  235. } catch (BitcoinURIParseException e) {
  236. assertTrue(e.getMessage().contains("amount"));
  237. }
  238. }
  239. /**
  240. * Handles a badly formatted label field
  241. *
  242. * @throws BitcoinURIParseException
  243. * If something goes wrong
  244. */
  245. @Test
  246. public void testBad_Label() throws BitcoinURIParseException {
  247. try {
  248. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
  249. + "?label=");
  250. fail("Expecting BitcoinURIParseException");
  251. } catch (BitcoinURIParseException e) {
  252. assertTrue(e.getMessage().contains("label"));
  253. }
  254. }
  255. /**
  256. * Handles a badly formatted message field
  257. *
  258. * @throws BitcoinURIParseException
  259. * If something goes wrong
  260. */
  261. @Test
  262. public void testBad_Message() throws BitcoinURIParseException {
  263. try {
  264. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
  265. + "?message=");
  266. fail("Expecting BitcoinURIParseException");
  267. } catch (BitcoinURIParseException e) {
  268. assertTrue(e.getMessage().contains("message"));
  269. }
  270. }
  271. /**
  272. * Handles duplicated fields (sneaky address overwrite attack)
  273. *
  274. * @throws BitcoinURIParseException
  275. * If something goes wrong
  276. */
  277. @Test
  278. public void testBad_Duplicated() throws BitcoinURIParseException {
  279. try {
  280. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
  281. + "?address=aardvark");
  282. fail("Expecting BitcoinURIParseException");
  283. } catch (BitcoinURIParseException e) {
  284. assertTrue(e.getMessage().contains("address"));
  285. }
  286. }
  287. /**
  288. * Handles case when there are too many equals
  289. *
  290. * @throws BitcoinURIParseException
  291. * If something goes wrong
  292. */
  293. @Test
  294. public void testBad_TooManyEquals() throws BitcoinURIParseException {
  295. try {
  296. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
  297. + "?label=aardvark=zebra");
  298. fail("Expecting BitcoinURIParseException");
  299. } catch (BitcoinURIParseException e) {
  300. assertTrue(e.getMessage().contains("cannot parse name value pair"));
  301. }
  302. }
  303. /**
  304. * Handles case when there are too many question marks
  305. *
  306. * @throws BitcoinURIParseException
  307. * If something goes wrong
  308. */
  309. @Test
  310. public void testBad_TooManyQuestionMarks() throws BitcoinURIParseException {
  311. try {
  312. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
  313. + "?label=aardvark?message=zebra");
  314. fail("Expecting BitcoinURIParseException");
  315. } catch (BitcoinURIParseException e) {
  316. assertTrue(e.getMessage().contains("Too many question marks"));
  317. }
  318. }
  319. /**
  320. * Handles unknown fields (required and not required)
  321. *
  322. * @throws BitcoinURIParseException
  323. * If something goes wrong
  324. */
  325. @Test
  326. public void testUnknown() throws BitcoinURIParseException {
  327. // Unknown not required field
  328. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
  329. + "?aardvark=true");
  330. assertEquals("BitcoinURI['address'='1KzTSfqjF2iKCduwz59nv2uqh1W2JsTxZH','aardvark'='true']", testObject.toString());
  331. assertEquals("true", (String) testObject.getParameterByName("aardvark"));
  332. // Unknown not required field (isolated)
  333. try {
  334. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
  335. + "?aardvark");
  336. fail("Expecting BitcoinURIParseException");
  337. } catch (BitcoinURIParseException e) {
  338. assertTrue(e.getMessage().contains("cannot parse name value pair"));
  339. }
  340. // Unknown and required field
  341. try {
  342. testObject = new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
  343. + "?req-aardvark=true");
  344. fail("Expecting BitcoinURIParseException");
  345. } catch (BitcoinURIParseException e) {
  346. assertTrue(e.getMessage().contains("req-aardvark"));
  347. }
  348. }
  349. @Test
  350. public void brokenURIs() throws BitcoinURIParseException {
  351. // Check we can parse the incorrectly formatted URIs produced by blockchain.info and its iPhone app.
  352. String str = "bitcoin://1KzTSfqjF2iKCduwz59nv2uqh1W2JsTxZH?amount=0.01000000";
  353. BitcoinURI uri = new BitcoinURI(str);
  354. assertEquals("1KzTSfqjF2iKCduwz59nv2uqh1W2JsTxZH", uri.getAddress().toString());
  355. assertEquals(Utils.toNanoCoins(0, 1), uri.getAmount());
  356. }
  357. @Test(expected = BitcoinURIParseException.class)
  358. public void testBad_AmountTooPrecise() throws BitcoinURIParseException {
  359. new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
  360. + "?amount=0.123456789");
  361. }
  362. @Test(expected = BitcoinURIParseException.class)
  363. public void testBad_NegativeAmount() throws BitcoinURIParseException {
  364. new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
  365. + "?amount=-1");
  366. }
  367. @Test(expected = BitcoinURIParseException.class)
  368. public void testBad_TooLargeAmount() throws BitcoinURIParseException {
  369. new BitcoinURI(MainNetParams.get(), BitcoinURI.BITCOIN_SCHEME + ":" + MAINNET_GOOD_ADDRESS
  370. + "?amount=100000000");
  371. }
  372. }