rfc4287_test.ml 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. (*
  2. * _ _ ____ _
  3. * _| || |_/ ___| ___ _ __ _ __ ___ | |
  4. * |_ .. _\___ \ / _ \ '_ \| '_ \ / _ \| |
  5. * |_ _|___) | __/ |_) | |_) | (_) |_|
  6. * |_||_| |____/ \___| .__/| .__/ \___/(_)
  7. * |_| |_|
  8. *
  9. * Personal Social Web.
  10. *
  11. * Copyright (C) The #Seppo contributors. All rights reserved.
  12. *
  13. * This program is free software: you can redistribute it and/or modify
  14. * it under the terms of the GNU General Public License as published by
  15. * the Free Software Foundation, either version 3 of the License, or
  16. * (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  25. *)
  26. open Seppo_lib
  27. open Rfc4287
  28. let mk_sample () =
  29. let tag path = Category.((Label (Single path)), (Term (Single path)), tagu) in
  30. let e : Entry.t = {
  31. id = "o/p-12/#23" |> Uri.of_string;
  32. in_reply_to= [Uri.empty |> Inreplyto.make];
  33. lang = Rfc4646 "en";
  34. author = Uri.make ~userinfo:"fediverse" ~host:"mro.name" ();
  35. title = "#Announce Seppo.Social v0.1 and Request for Comments.";
  36. published = Rfc3339.T "2023-02-11T11:07:23+01:00";
  37. updated = Rfc3339.T "2023-02-11T11:07:23+01:00";
  38. links = [ "https://seppo.social/en/downloads/seppo-Linux-x86_64-0.1/" |> Uri.of_string |> Link.make ];
  39. categories = [
  40. tag "ActivityPub";
  41. tag "Announce";
  42. tag "Fediverse";
  43. tag "Media";
  44. tag "permacomputing";
  45. tag "Seppo";
  46. tag "Social";
  47. tag "webfinger";
  48. ];
  49. content = {|I am happy to announce the premiere release of #Seppo!, Personal #Social #Media under funding of NLnet.nl.
  50. Find it at https://Seppo.Social/downloads/
  51. It has no notable user facing #ActivityPub features so far, but
  52. - easy setup of instance & account,
  53. - #webfinger discoverability (from e.g. mastodon search),
  54. - a welcoming, long-term reliable website.
  55. I made this embarrassingly limited release to build awareness for low-barrier-entry internet services in general and especially in the field of personal communication as well as letting the #fediverse and #permacomputing communities know.
  56. Your comments are very much appreciated.|};
  57. } in
  58. e
  59. let tail x =
  60. Assrt.equals_string __LOC__ "ok" (if x |> Result.is_ok then "ok" else "no")
  61. let test_compute_links () =
  62. let base = "https://example.com/sub/" |> Uri.of_string in
  63. let self,first,last,prev,next = ("o/p",2) |> Rfc4287.Feed.compute_links ~max:7 ~base in
  64. self |> Uri.to_string |> Assrt.equals_string __LOC__ "https://example.com/sub/o/p-2/";
  65. first |> Uri.to_string |> Assrt.equals_string __LOC__ "https://example.com/sub/o/p/";
  66. last |> Uri.to_string |> Assrt.equals_string __LOC__ "https://example.com/sub/o/p-0/";
  67. prev |> Option.get |> Uri.to_string |> Assrt.equals_string __LOC__ "https://example.com/sub/o/p-3/";
  68. next |> Option.get |> Uri.to_string |> Assrt.equals_string __LOC__ "https://example.com/sub/o/p-1/";
  69. assert true
  70. let test_encode () =
  71. Logr.info (fun m -> m "rfc4287_test.test_encode");
  72. let e = mk_sample () in
  73. e
  74. |> Entry.encode
  75. |> Csexp.to_string
  76. |> Assrt.equals_string __LOC__ {|(2:id10:o/p-12/#2311:in-reply-to((3:ref0:))4:lang2:en5:title53:#Announce Seppo.Social v0.1 and Request for Comments.6:author20://fediverse@mro.name9:published25:2023-02-11T11:07:23+01:007:updated25:2023-02-11T11:07:23+01:005:links((4:href57:https://seppo.social/en/downloads/seppo-Linux-x86_64-0.1/))10:categories((5:label11:ActivityPub4:term11:ActivityPub6:scheme4:o/t/)(5:label8:Announce4:term8:Announce6:scheme4:o/t/)(5:label9:Fediverse4:term9:Fediverse6:scheme4:o/t/)(5:label5:Media4:term5:Media6:scheme4:o/t/)(5:label14:permacomputing4:term14:permacomputing6:scheme4:o/t/)(5:label5:Seppo4:term5:Seppo6:scheme4:o/t/)(5:label6:Social4:term6:Social6:scheme4:o/t/)(5:label9:webfinger4:term9:webfinger6:scheme4:o/t/))7:content635:I am happy to announce the premiere release of #Seppo!, Personal #Social #Media under funding of NLnet.nl.
  77. Find it at https://Seppo.Social/downloads/
  78. It has no notable user facing #ActivityPub features so far, but
  79. - easy setup of instance & account,
  80. - #webfinger discoverability (from e.g. mastodon search),
  81. - a welcoming, long-term reliable website.
  82. I made this embarrassingly limited release to build awareness for low-barrier-entry internet services in general and especially in the field of personal communication as well as letting the #fediverse and #permacomputing communities know.
  83. Your comments are very much appreciated.)|};
  84. e |> Entry.encode |> Csexp.to_string |> String.length |> Assrt.equals_int __LOC__ 1366;
  85. match e
  86. |> Entry.encode
  87. |> Entry.decode with
  88. | Error e -> e |> Assrt.equals_string __LOC__ ""
  89. | Ok e ->
  90. let Rfc4646 lang = e.lang
  91. and titl = e.title
  92. and Rfc3339.T publ = e.published
  93. and Rfc3339.T upda = e.updated
  94. and cont = e.content
  95. and li_a, li_b = match e.links with
  96. | [ {href; rel=None; title=None; rfc7033=None} ] -> (href,"")
  97. | _ -> (Uri.make (), "ouch 301")
  98. and ca_a, ca_b, ca_c = match e.categories with
  99. | (Label (Single a), Term (Single b), c) :: _ -> (a,b,c)
  100. | _ -> ("ouch 302", "", Uri.make ())
  101. in
  102. lang |> Assrt.equals_string __LOC__ "en";
  103. titl |> Assrt.equals_string __LOC__ "#Announce Seppo.Social v0.1 and Request for Comments.";
  104. publ |> Assrt.equals_string __LOC__ "2023-02-11T11:07:23+01:00";
  105. upda |> Assrt.equals_string __LOC__ "2023-02-11T11:07:23+01:00";
  106. e.links |> List.length |> Assrt.equals_int __LOC__ 1;
  107. li_a |> Uri.to_string |> Assrt.equals_string __LOC__ "https://seppo.social/en/downloads/seppo-Linux-x86_64-0.1/";
  108. li_b |> Assrt.equals_string __LOC__ "";
  109. e.categories |> List.length |> Assrt.equals_int __LOC__ 8;
  110. ca_a |> Assrt.equals_string __LOC__ "webfinger";
  111. ca_b |> Assrt.equals_string __LOC__ "webfinger";
  112. ca_c |> Uri.to_string |> Assrt.equals_string __LOC__ "o/t/";
  113. cont |> Assrt.equals_string __LOC__ {|I am happy to announce the premiere release of #Seppo!, Personal #Social #Media under funding of NLnet.nl.
  114. Find it at https://Seppo.Social/downloads/
  115. It has no notable user facing #ActivityPub features so far, but
  116. - easy setup of instance & account,
  117. - #webfinger discoverability (from e.g. mastodon search),
  118. - a welcoming, long-term reliable website.
  119. I made this embarrassingly limited release to build awareness for low-barrier-entry internet services in general and especially in the field of personal communication as well as letting the #fediverse and #permacomputing communities know.
  120. Your comments are very much appreciated.|} ;
  121. e |> Storage.feed_urls
  122. |> List.map Uri.to_string |> String.concat " ; "
  123. |> Assrt.equals_string __LOC__ "o/p/ ; activitypub/outbox/ ; o/d/2023-02-11/ ; o/t/webfinger/ ; o/t/Social/ ; o/t/Seppo/ ; o/t/permacomputing/ ; o/t/Media/ ; o/t/Fediverse/ ; o/t/Announce/ ; o/t/ActivityPub/";
  124. assert true
  125. let test_from_plain_text () =
  126. Logr.info (fun m -> m "rfc4287_test.test_from_plain_text");
  127. let published = Rfc3339.T "2023-02-14T01:23:45+01:00" in
  128. let author = Uri.make ~userinfo:"uhu" () in
  129. let lang = Rfc4646 "nl" in
  130. let uri = Uri.of_string "https://nlnet.nl/projects/Seppo/" in
  131. (let* n = Entry.from_text_plain ~published ~author ~lang ~uri "Hello, world!" "a new Note." in
  132. let ti = n.title in
  133. let co = n.content in
  134. ti |> Assrt.equals_string __LOC__ "Hello, world!";
  135. n.links |> List.length |> Assrt.equals_int __LOC__ 1;
  136. n.categories |> List.length |> Assrt.equals_int __LOC__ 0;
  137. co |> Assrt.equals_string __LOC__ "a new Note.";
  138. n |> Entry.encode
  139. |> Csexp.to_string
  140. |> Assrt.equals_string __LOC__ {|(2:id7:aseggdb11:in-reply-to()4:lang2:nl5:title13:Hello, world!6:author6://uhu@9:published25:2023-02-14T01:23:45+01:007:updated25:2023-02-14T01:23:45+01:005:links((4:href32:https://nlnet.nl/projects/Seppo/))10:categories()7:content11:a new Note.)|};
  141. Ok n)
  142. |> tail
  143. (**
  144. * inspired by https://code.mro.name/mro/ShaarliGo/src/cb798ebfae17431732e37a94ee80b29bd3b78911/atom.go#L302
  145. * https://opam.ocaml.org/packages/base32/
  146. * https://opam.ocaml.org/packages/base64/
  147. *)
  148. let test_id_make () =
  149. Logr.info (fun m -> m "rfc4287_test.test_id_make");
  150. let assrt l id iso =
  151. match iso |> Ptime.of_rfc3339 with
  152. | Ok (t,_,_) ->
  153. let f = Entry.id_make t |> Uri.to_string in
  154. Assrt.equals_string l id f
  155. | _ -> "" |> Assrt.equals_string "" "-"
  156. in
  157. "1970-01-01T00:00:00+00:00" |> assrt "rfc4287_test.test_id_make 0" "2222222";
  158. "2023-01-01T00:00:00+00:00" |> assrt "rfc4287_test.test_id_make 1" "as35e22";
  159. "2081-01-01T00:00:00+00:00" |> assrt "rfc4287_test.test_id_make 2" "s9y3s22";
  160. "2120-01-01T00:00:00+00:00" |> assrt "rfc4287_test.test_id_make 4" "2sd6e22";
  161. assert true
  162. let test_entry_atom () =
  163. Logr.info (fun m -> m "rfc4287_test.test_entry_atom");
  164. let base = Uri.of_string "https://example.com/sub/" in
  165. let published = Rfc3339.T "2023-02-14T01:23:45+01:00" in
  166. let author = Uri.make ~userinfo:"uhu" () in
  167. let lang = Rfc4646 "nl" in
  168. let uri = Uri.of_string "https://nlnet.nl/projects/Seppo/" in
  169. let e0 = Entry.from_text_plain ~published ~author ~lang ~uri "Hello, world!" "a new Note."
  170. |> Result.get_ok in
  171. let buf = Buffer.create 1024 in
  172. let attr = [
  173. ((Xmlm.ns_xmlns,"xmlns"), Xml.ns_a);
  174. ((Xmlm.ns_xmlns,"wf"), Xml.ns_rfc7033);
  175. ] in
  176. let e = Entry.to_atom ~attr ~base e0 in
  177. Xml.to_buf e buf;
  178. buf |> Buffer.to_bytes |> Bytes.to_string
  179. |> Assrt.equals_string __LOC__ {|<?xml version="1.0"?>
  180. <entry xml:lang="nl" xmlns="http://www.w3.org/2005/Atom" xmlns:wf="urn:ietf:rfc:7033">
  181. <id>https://example.com/sub/aseggdb</id>
  182. <title type="text">Hello, world!</title>
  183. <updated>2023-02-14T01:23:45+01:00</updated>
  184. <published>2023-02-14T01:23:45+01:00</published>
  185. <author>
  186. <name>@uhu@example.com</name>
  187. <wf:uri>acct:uhu@example.com</wf:uri>
  188. <uri>https://example.com/sub/</uri></author>
  189. <link rel="self" href="https://example.com/sub/aseggdb"/>
  190. <link href="https://nlnet.nl/projects/Seppo/"/>
  191. <content type="text">a new Note.</content>
  192. </entry>|}
  193. let test_feed_atom () =
  194. Logr.info (fun m -> m "rfc4287_test.test_feed_atom");
  195. let published = Rfc3339.T "2023-02-14T01:23:45+01:00" in
  196. let author = Uri.make ~userinfo:"uhu" () in
  197. let lang = Rfc4646 "nl" in
  198. let uri = Uri.of_string "https://nlnet.nl/projects/Seppo/" in
  199. let e0 = Entry.from_text_plain ~published ~author ~lang ~uri "Hello, world!" "a new Note."
  200. |> Result.get_ok in
  201. let fe = Feed.to_atom
  202. ~author:(Uri.make ~userinfo:"sepp" ())
  203. ~base:(Uri.make ~scheme:"https" ~host:"example.com" ~path:"/sub/" ())
  204. ~lang:(Rfc4646 "nl")
  205. ~self:(Uri.make ~path:"o/p-11/" ())
  206. ~prev:(Some (Uri.make ~path:"o/p-10/" ()))
  207. ~next:None
  208. ~first:(Uri.make ~path:"o/p/" ())
  209. ~last:(Uri.make ~path:"o/p-0/" ())
  210. ~title:"My fancy #Seppo!"
  211. ~updated:(Rfc3339.T "2023-02-27T12:34:56+01:00")
  212. [e0] in
  213. let buf = Buffer.create 1024 in
  214. Xml.to_buf fe buf;
  215. buf |> Buffer.to_bytes |> Bytes.to_string
  216. |> Assrt.equals_string __LOC__ {|<?xml version="1.0"?>
  217. <feed xmlns="http://www.w3.org/2005/Atom" xmlns:wf="urn:ietf:rfc:7033" xml:lang="nl" xml:base="https://example.com/sub/">
  218. <id>https://example.com/sub/o/p-11/</id>
  219. <title type="text">My fancy #Seppo!</title>
  220. <updated>2023-02-27T12:34:56+01:00</updated>
  221. <generator uri="Seppo.Social">Seppo - Personal Social Web</generator>
  222. <link rel="self" href="o/p-11/" title="12"/>
  223. <link rel="first" href="o/p/" title="last"/>
  224. <link rel="last" href="o/p-0/" title="1"/>
  225. <link rel="previous" href="o/p-10/" title="11"/>
  226. <entry xml:lang="nl">
  227. <id>https://example.com/sub/aseggdb</id>
  228. <title type="text">Hello, world!</title>
  229. <updated>2023-02-14T01:23:45+01:00</updated>
  230. <published>2023-02-14T01:23:45+01:00</published>
  231. <author>
  232. <name>@uhu@example.com</name>
  233. <wf:uri>acct:uhu@example.com</wf:uri>
  234. <uri>https://example.com/sub/</uri></author>
  235. <link rel="self" href="https://example.com/sub/aseggdb"/>
  236. <link href="https://nlnet.nl/projects/Seppo/"/>
  237. <content type="text">a new Note.</content>
  238. </entry>
  239. </feed>|}
  240. let test_xsl () =
  241. "o/p-1/index.xml"
  242. |> Rfc4287.xsl "posts.xsl"
  243. |> Option.value ~default:"?"
  244. |> Assrt.equals_string __LOC__ "../../themes/current/posts.xsl"
  245. let () =
  246. Unix.chdir "../../../test/";
  247. test_compute_links ();
  248. test_encode ();
  249. test_from_plain_text ();
  250. test_id_make ();
  251. test_entry_atom ();
  252. test_feed_atom ();
  253. test_xsl ();
  254. assert true