crate.scm 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2014 David Thompson <davet@gnu.org>
  3. ;;; Copyright © 2016 David Craven <david@craven.ch>
  4. ;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
  5. ;;;
  6. ;;; This file is part of GNU Guix.
  7. ;;;
  8. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  9. ;;; under the terms of the GNU General Public License as published by
  10. ;;; the Free Software Foundation; either version 3 of the License, or (at
  11. ;;; your option) any later version.
  12. ;;;
  13. ;;; GNU Guix is distributed in the hope that it will be useful, but
  14. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. ;;; GNU General Public License for more details.
  17. ;;;
  18. ;;; You should have received a copy of the GNU General Public License
  19. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  20. (define-module (test-crate)
  21. #:use-module (guix import crate)
  22. #:use-module (guix base32)
  23. #:use-module (guix build-system cargo)
  24. #:use-module (gcrypt hash)
  25. #:use-module (guix tests)
  26. #:use-module (ice-9 iconv)
  27. #:use-module (ice-9 match)
  28. #:use-module (srfi srfi-64))
  29. (define test-foo-crate
  30. "{
  31. \"crate\": {
  32. \"max_version\": \"1.0.0\",
  33. \"name\": \"foo\",
  34. \"description\": \"summary\",
  35. \"homepage\": \"http://example.com\",
  36. \"repository\": \"http://example.com\",
  37. \"keywords\": [\"dummy\" \"test\"],
  38. \"categories\": [\"test\"]
  39. \"actual_versions\": [
  40. { \"id\": \"foo\",
  41. \"num\": \"1.0.0\",
  42. \"license\": \"MIT OR Apache-2.0\",
  43. \"links\": {
  44. \"dependencies\": \"/api/v1/crates/foo/1.0.0/dependencies\"
  45. }
  46. }
  47. ]
  48. }
  49. }")
  50. (define test-foo-dependencies
  51. "{
  52. \"dependencies\": [
  53. {
  54. \"crate_id\": \"bar\",
  55. \"kind\": \"normal\",
  56. }
  57. ]
  58. }")
  59. (define test-root-crate
  60. "{
  61. \"crate\": {
  62. \"max_version\": \"1.0.0\",
  63. \"name\": \"root\",
  64. \"description\": \"summary\",
  65. \"homepage\": \"http://example.com\",
  66. \"repository\": \"http://example.com\",
  67. \"keywords\": [\"dummy\" \"test\"],
  68. \"categories\": [\"test\"]
  69. \"actual_versions\": [
  70. { \"id\": \"foo\",
  71. \"num\": \"1.0.0\",
  72. \"license\": \"MIT OR Apache-2.0\",
  73. \"links\": {
  74. \"dependencies\": \"/api/v1/crates/root/1.0.0/dependencies\"
  75. }
  76. }
  77. ]
  78. }
  79. }")
  80. (define test-root-dependencies
  81. "{
  82. \"dependencies\": [
  83. {
  84. \"crate_id\": \"intermediate-1\",
  85. \"kind\": \"normal\",
  86. },
  87. {
  88. \"crate_id\": \"intermediate-2\",
  89. \"kind\": \"normal\",
  90. }
  91. {
  92. \"crate_id\": \"leaf-alice\",
  93. \"kind\": \"normal\",
  94. },
  95. {
  96. \"crate_id\": \"leaf-bob\",
  97. \"kind\": \"normal\",
  98. },
  99. ]
  100. }")
  101. (define test-intermediate-1-crate
  102. "{
  103. \"crate\": {
  104. \"max_version\": \"1.0.0\",
  105. \"name\": \"intermediate-1\",
  106. \"description\": \"summary\",
  107. \"homepage\": \"http://example.com\",
  108. \"repository\": \"http://example.com\",
  109. \"keywords\": [\"dummy\" \"test\"],
  110. \"categories\": [\"test\"]
  111. \"actual_versions\": [
  112. { \"id\": \"intermediate-1\",
  113. \"num\": \"1.0.0\",
  114. \"license\": \"MIT OR Apache-2.0\",
  115. \"links\": {
  116. \"dependencies\": \"/api/v1/crates/intermediate-1/1.0.0/dependencies\"
  117. }
  118. }
  119. ]
  120. }
  121. }")
  122. (define test-intermediate-1-dependencies
  123. "{
  124. \"dependencies\": [
  125. {
  126. \"crate_id\": \"intermediate-2\",
  127. \"kind\": \"normal\",
  128. },
  129. {
  130. \"crate_id\": \"leaf-alice\",
  131. \"kind\": \"normal\",
  132. },
  133. {
  134. \"crate_id\": \"leaf-bob\",
  135. \"kind\": \"normal\",
  136. }
  137. ]
  138. }")
  139. (define test-intermediate-2-crate
  140. "{
  141. \"crate\": {
  142. \"max_version\": \"1.0.0\",
  143. \"name\": \"intermediate-2\",
  144. \"description\": \"summary\",
  145. \"homepage\": \"http://example.com\",
  146. \"repository\": \"http://example.com\",
  147. \"keywords\": [\"dummy\" \"test\"],
  148. \"categories\": [\"test\"]
  149. \"actual_versions\": [
  150. { \"id\": \"intermediate-2\",
  151. \"num\": \"1.0.0\",
  152. \"license\": \"MIT OR Apache-2.0\",
  153. \"links\": {
  154. \"dependencies\": \"/api/v1/crates/intermediate-2/1.0.0/dependencies\"
  155. }
  156. }
  157. ]
  158. }
  159. }")
  160. (define test-intermediate-2-dependencies
  161. "{
  162. \"dependencies\": [
  163. {
  164. \"crate_id\": \"leaf-bob\",
  165. \"kind\": \"normal\",
  166. },
  167. ]
  168. }")
  169. (define test-leaf-alice-crate
  170. "{
  171. \"crate\": {
  172. \"max_version\": \"1.0.0\",
  173. \"name\": \"leaf-alice\",
  174. \"description\": \"summary\",
  175. \"homepage\": \"http://example.com\",
  176. \"repository\": \"http://example.com\",
  177. \"keywords\": [\"dummy\" \"test\"],
  178. \"categories\": [\"test\"]
  179. \"actual_versions\": [
  180. { \"id\": \"leaf-alice\",
  181. \"num\": \"1.0.0\",
  182. \"license\": \"MIT OR Apache-2.0\",
  183. \"links\": {
  184. \"dependencies\": \"/api/v1/crates/leaf-alice/1.0.0/dependencies\"
  185. }
  186. }
  187. ]
  188. }
  189. }")
  190. (define test-leaf-alice-dependencies
  191. "{
  192. \"dependencies\": []
  193. }")
  194. (define test-leaf-bob-crate
  195. "{
  196. \"crate\": {
  197. \"max_version\": \"1.0.0\",
  198. \"name\": \"leaf-bob\",
  199. \"description\": \"summary\",
  200. \"homepage\": \"http://example.com\",
  201. \"repository\": \"http://example.com\",
  202. \"keywords\": [\"dummy\" \"test\"],
  203. \"categories\": [\"test\"]
  204. \"actual_versions\": [
  205. { \"id\": \"leaf-bob\",
  206. \"num\": \"1.0.0\",
  207. \"license\": \"MIT OR Apache-2.0\",
  208. \"links\": {
  209. \"dependencies\": \"/api/v1/crates/leaf-bob/1.0.0/dependencies\"
  210. }
  211. }
  212. ]
  213. }
  214. }")
  215. (define test-leaf-bob-dependencies
  216. "{
  217. \"dependencies\": []
  218. }")
  219. (define test-source-hash
  220. "")
  221. (define string->license
  222. (@@ (guix import crate) string->license))
  223. (test-begin "crate")
  224. (test-equal "guix-package->crate-name"
  225. "rustc-serialize"
  226. (guix-package->crate-name
  227. (dummy-package
  228. "rust-rustc-serialize"
  229. (source (dummy-origin
  230. (uri (crate-uri "rustc-serialize" "1.0")))))))
  231. (test-assert "crate->guix-package"
  232. ;; Replace network resources with sample data.
  233. (mock ((guix http-client) http-fetch
  234. (lambda (url . rest)
  235. (match url
  236. ("https://crates.io/api/v1/crates/foo"
  237. (open-input-string test-foo-crate))
  238. ("https://crates.io/api/v1/crates/foo/1.0.0/download"
  239. (set! test-source-hash
  240. (bytevector->nix-base32-string
  241. (sha256 (string->bytevector "empty file\n" "utf-8"))))
  242. (open-input-string "empty file\n"))
  243. ("https://crates.io/api/v1/crates/foo/1.0.0/dependencies"
  244. (open-input-string test-foo-dependencies))
  245. (_ (error "Unexpected URL: " url)))))
  246. (match (crate->guix-package "foo")
  247. (('package
  248. ('name "rust-foo")
  249. ('version "1.0.0")
  250. ('source ('origin
  251. ('method 'url-fetch)
  252. ('uri ('crate-uri "foo" 'version))
  253. ('file-name ('string-append 'name "-" 'version ".tar.gz"))
  254. ('sha256
  255. ('base32
  256. (? string? hash)))))
  257. ('build-system 'cargo-build-system)
  258. ('arguments
  259. ('quasiquote
  260. ('#:cargo-inputs (("rust-bar" ('unquote rust-bar))))))
  261. ('home-page "http://example.com")
  262. ('synopsis "summary")
  263. ('description "summary")
  264. ('license ('list 'license:expat 'license:asl2.0)))
  265. (string=? test-source-hash hash))
  266. (x
  267. (pk 'fail x #f)))))
  268. (test-assert "cargo-recursive-import"
  269. ;; Replace network resources with sample data.
  270. (mock ((guix http-client) http-fetch
  271. (lambda (url . rest)
  272. (match url
  273. ("https://crates.io/api/v1/crates/root"
  274. (open-input-string test-root-crate))
  275. ("https://crates.io/api/v1/crates/root/1.0.0/download"
  276. (set! test-source-hash
  277. (bytevector->nix-base32-string
  278. (sha256 (string->bytevector "empty file\n" "utf-8"))))
  279. (open-input-string "empty file\n"))
  280. ("https://crates.io/api/v1/crates/root/1.0.0/dependencies"
  281. (open-input-string test-root-dependencies))
  282. ("https://crates.io/api/v1/crates/intermediate-1"
  283. (open-input-string test-intermediate-1-crate))
  284. ("https://crates.io/api/v1/crates/intermediate-1/1.0.0/download"
  285. (set! test-source-hash
  286. (bytevector->nix-base32-string
  287. (sha256 (string->bytevector "empty file\n" "utf-8"))))
  288. (open-input-string "empty file\n"))
  289. ("https://crates.io/api/v1/crates/intermediate-1/1.0.0/dependencies"
  290. (open-input-string test-intermediate-1-dependencies))
  291. ("https://crates.io/api/v1/crates/intermediate-2"
  292. (open-input-string test-intermediate-2-crate))
  293. ("https://crates.io/api/v1/crates/intermediate-2/1.0.0/download"
  294. (set! test-source-hash
  295. (bytevector->nix-base32-string
  296. (sha256 (string->bytevector "empty file\n" "utf-8"))))
  297. (open-input-string "empty file\n"))
  298. ("https://crates.io/api/v1/crates/intermediate-2/1.0.0/dependencies"
  299. (open-input-string test-intermediate-2-dependencies))
  300. ("https://crates.io/api/v1/crates/leaf-alice"
  301. (open-input-string test-leaf-alice-crate))
  302. ("https://crates.io/api/v1/crates/leaf-alice/1.0.0/download"
  303. (set! test-source-hash
  304. (bytevector->nix-base32-string
  305. (sha256 (string->bytevector "empty file\n" "utf-8"))))
  306. (open-input-string "empty file\n"))
  307. ("https://crates.io/api/v1/crates/leaf-alice/1.0.0/dependencies"
  308. (open-input-string test-leaf-alice-dependencies))
  309. ("https://crates.io/api/v1/crates/leaf-bob"
  310. (open-input-string test-leaf-bob-crate))
  311. ("https://crates.io/api/v1/crates/leaf-bob/1.0.0/download"
  312. (set! test-source-hash
  313. (bytevector->nix-base32-string
  314. (sha256 (string->bytevector "empty file\n" "utf-8"))))
  315. (open-input-string "empty file\n"))
  316. ("https://crates.io/api/v1/crates/leaf-bob/1.0.0/dependencies"
  317. (open-input-string test-leaf-bob-dependencies))
  318. (_ (error "Unexpected URL: " url)))))
  319. (match (crate-recursive-import "root")
  320. ;; rust-intermediate-2 has no dependency on the rust-leaf-alice package, so this is a valid ordering
  321. ((('package
  322. ('name "rust-leaf-alice")
  323. ('version (? string? ver))
  324. ('source
  325. ('origin
  326. ('method 'url-fetch)
  327. ('uri ('crate-uri "leaf-alice" 'version))
  328. ('file-name
  329. ('string-append 'name "-" 'version ".tar.gz"))
  330. ('sha256
  331. ('base32
  332. (? string? hash)))))
  333. ('build-system 'cargo-build-system)
  334. ('home-page "http://example.com")
  335. ('synopsis "summary")
  336. ('description "summary")
  337. ('license ('list 'license:expat 'license:asl2.0)))
  338. ('package
  339. ('name "rust-leaf-bob")
  340. ('version (? string? ver))
  341. ('source
  342. ('origin
  343. ('method 'url-fetch)
  344. ('uri ('crate-uri "leaf-bob" 'version))
  345. ('file-name
  346. ('string-append 'name "-" 'version ".tar.gz"))
  347. ('sha256
  348. ('base32
  349. (? string? hash)))))
  350. ('build-system 'cargo-build-system)
  351. ('home-page "http://example.com")
  352. ('synopsis "summary")
  353. ('description "summary")
  354. ('license ('list 'license:expat 'license:asl2.0)))
  355. ('package
  356. ('name "rust-intermediate-2")
  357. ('version (? string? ver))
  358. ('source
  359. ('origin
  360. ('method 'url-fetch)
  361. ('uri ('crate-uri "intermediate-2" 'version))
  362. ('file-name
  363. ('string-append 'name "-" 'version ".tar.gz"))
  364. ('sha256
  365. ('base32
  366. (? string? hash)))))
  367. ('build-system 'cargo-build-system)
  368. ('arguments
  369. ('quasiquote
  370. ('#:cargo-inputs (("rust-leaf-bob" ('unquote rust-leaf-bob))))))
  371. ('home-page "http://example.com")
  372. ('synopsis "summary")
  373. ('description "summary")
  374. ('license ('list 'license:expat 'license:asl2.0)))
  375. ('package
  376. ('name "rust-intermediate-1")
  377. ('version (? string? ver))
  378. ('source
  379. ('origin
  380. ('method 'url-fetch)
  381. ('uri ('crate-uri "intermediate-1" 'version))
  382. ('file-name
  383. ('string-append 'name "-" 'version ".tar.gz"))
  384. ('sha256
  385. ('base32
  386. (? string? hash)))))
  387. ('build-system 'cargo-build-system)
  388. ('arguments
  389. ('quasiquote
  390. ('#:cargo-inputs (("rust-intermediate-2" ('unquote rust-intermediate-2))
  391. ("rust-leaf-alice" ('unquote rust-leaf-alice))
  392. ("rust-leaf-bob" ('unquote rust-leaf-bob))))))
  393. ('home-page "http://example.com")
  394. ('synopsis "summary")
  395. ('description "summary")
  396. ('license ('list 'license:expat 'license:asl2.0)))
  397. ('package
  398. ('name "rust-root")
  399. ('version (? string? ver))
  400. ('source
  401. ('origin
  402. ('method 'url-fetch)
  403. ('uri ('crate-uri "root" 'version))
  404. ('file-name
  405. ('string-append 'name "-" 'version ".tar.gz"))
  406. ('sha256
  407. ('base32
  408. (? string? hash)))))
  409. ('build-system 'cargo-build-system)
  410. ('arguments
  411. ('quasiquote
  412. ('#:cargo-inputs (("rust-intermediate-1" ('unquote rust-intermediate-1))
  413. ("rust-intermediate-2" ('unquote rust-intermediate-2))
  414. ("rust-leaf-alice" ('unquote rust-leaf-alice))
  415. ("rust-leaf-bob" ('unquote rust-leaf-bob))))))
  416. ('home-page "http://example.com")
  417. ('synopsis "summary")
  418. ('description "summary")
  419. ('license ('list 'license:expat 'license:asl2.0))))
  420. #t)
  421. (x
  422. (pk 'fail x #f)))))
  423. (test-equal "licenses: MIT OR Apache-2.0"
  424. '(license:expat license:asl2.0)
  425. (string->license "MIT OR Apache-2.0"))
  426. (test-equal "licenses: Apache-2.0 / MIT"
  427. '(license:asl2.0 license:expat)
  428. (string->license "Apache-2.0 / MIT"))
  429. (test-equal "licenses: Apache-2.0 WITH LLVM-exception"
  430. '(license:asl2.0 unknown-license!)
  431. (string->license "Apache-2.0 WITH LLVM-exception"))
  432. (test-equal "licenses: MIT/Apache-2.0 AND BSD-2-Clause"
  433. '(license:expat license:asl2.0 unknown-license!)
  434. (string->license "MIT/Apache-2.0 AND BSD-2-Clause"))
  435. (test-equal "licenses: MIT/Apache-2.0"
  436. '(license:expat license:asl2.0)
  437. (string->license "MIT/Apache-2.0"))
  438. (test-end "crate")