From 505f5bf5d951a5c4342f7acce9bea5f260dc9d78 Mon Sep 17 00:00:00 2001
From: Albert Krewinkel <albert@zeitkraut.de>
Date: Sun, 19 May 2019 15:26:00 +0200
Subject: Lua: add Version type to simplify comparisons

Version specifiers like `PANDOC_VERSION` and `PANDOC_API_VERSION` are
turned into `Version` objects. The objects simplify version-appropriate
comparisons while maintaining backward-compatibility.

A function `pandoc.types.Version` is added as part of the newly
introduced module `pandoc.types`, allowing users to create version
objects in scripts.
---
 test/lua/module/pandoc-types.lua | 112 +++++++++++++++++++++++++++++++++++++++
 test/lua/module/pandoc-utils.lua |  96 +++++++++++++++++++++++++++++++++
 test/lua/module/pandoc.utils.lua |  96 ---------------------------------
 3 files changed, 208 insertions(+), 96 deletions(-)
 create mode 100644 test/lua/module/pandoc-types.lua
 create mode 100644 test/lua/module/pandoc-utils.lua
 delete mode 100644 test/lua/module/pandoc.utils.lua

(limited to 'test/lua/module')

diff --git a/test/lua/module/pandoc-types.lua b/test/lua/module/pandoc-types.lua
new file mode 100644
index 000000000..8c8d903d9
--- /dev/null
+++ b/test/lua/module/pandoc-types.lua
@@ -0,0 +1,112 @@
+local tasty = require 'tasty'
+local types = require 'pandoc.types'
+local Version = types.Version
+
+local assert = tasty.assert
+local test = tasty.test_case
+local group = tasty.test_group
+
+return {
+  group 'Version' {
+
+    group 'constructor' {
+      test('has type `userdata`', function ()
+        assert.are_same(type(Version {2}), 'userdata')
+      end),
+      test('accepts list of integers', function ()
+        assert.are_same(type(Version {2, 7, 3}), 'userdata')
+      end),
+      test('accepts a single integer', function ()
+        assert.are_same(Version(5), Version {5})
+      end),
+      test('accepts version as string', function ()
+        assert.are_same(
+          Version '4.45.1',
+          Version {4, 45, 1}
+        )
+      end),
+      test('non-version string is rejected', function ()
+        assert.error_matches(
+          function () Version '11friends' end,
+          '11friends'
+        )
+      end)
+    },
+
+    group 'comparison' {
+      test('smaller (equal) than', function ()
+        assert.is_truthy(Version {2, 58, 3} < Version {2, 58, 4})
+        assert.is_falsy(Version {2, 60, 1} < Version {2, 59, 2})
+        assert.is_truthy(Version {0, 14, 3} < Version {0, 14, 3, 1})
+        assert.is_truthy(Version {3, 58, 3} <= Version {4})
+        assert.is_truthy(Version {0, 14, 3} <= Version {0, 14, 3, 1})
+      end),
+      test('larger (equal) than', function ()
+        assert.is_truthy(Version{2,58,3} > Version {2, 57, 4})
+        assert.is_truthy(Version{2,58,3} > Version {2, 58, 2})
+        assert.is_truthy(Version {0, 8} >= Version {0, 8})
+        assert.is_falsy(Version {0, 8} >= Version {0, 8, 2})
+      end),
+      test('equality', function ()
+        assert.is_truthy(Version '8.8', Version {8, 8})
+      end),
+      test('second argument can be a version string', function ()
+        assert.is_truthy(Version '8' < '9.1')
+        assert.is_falsy(Version '8.8' < '8.7')
+      end),
+    },
+
+    group 'list-like behavior' {
+      test('can access version component numbers', function ()
+        local version = Version '2.7.3'
+        assert.is_nil(version[0])
+        assert.are_equal(version[1], 2)
+        assert.are_equal(version[2], 7)
+        assert.are_equal(version[3], 3)
+      end),
+      test('can be iterated over', function ()
+        local version_list = {2, 7, 3}
+        local final_index = 0
+        for i, v in pairs(Version(version_list)) do
+          assert.are_equal(v, version_list[i])
+          final_index = i
+        end
+        assert.are_equal(final_index, 3)
+      end),
+      test('length is the number of components', function ()
+        assert.are_equal(#(Version '0'), 1)
+        assert.are_equal(#(Version '1.6'), 2)
+        assert.are_equal(#(Version '8.7.5'), 3)
+        assert.are_equal(#(Version '2.9.1.5'), 4)
+      end)
+    },
+
+    group 'conversion to string' {
+      test('converting from and to string is a noop', function ()
+        local version_string = '1.19.4'
+        assert.are_equal(tostring(Version(version_string)), version_string)
+      end)
+    },
+
+    group 'convenience functions' {
+      test('throws error if version is too old', function ()
+        local actual = Version {2, 8}
+        local expected = Version {2, 9}
+        assert.error_matches(
+          function () actual:must_be_at_least(expected) end,
+          'version too old: expected version 2.9 or newer, got 2.8'
+        )
+      end),
+      test('does nothing if expected version is older than actual', function ()
+        local actual = Version '2.9'
+        local expected = Version '2.8'
+        actual:must_be_at_least(expected)
+      end),
+      test('does nothing if expected version equals to actual', function ()
+        local actual = Version '2.8'
+        local expected = Version '2.8'
+        actual:must_be_at_least(expected)
+      end)
+    }
+  }
+}
diff --git a/test/lua/module/pandoc-utils.lua b/test/lua/module/pandoc-utils.lua
new file mode 100644
index 000000000..dc37ec354
--- /dev/null
+++ b/test/lua/module/pandoc-utils.lua
@@ -0,0 +1,96 @@
+local tasty = require 'tasty'
+local utils = require 'pandoc.utils'
+
+local assert = tasty.assert
+local test = tasty.test_case
+local group = tasty.test_group
+
+return {
+  group 'blocks_to_inlines' {
+    test('default separator', function ()
+      local blocks = {
+        pandoc.Para { pandoc.Str 'Paragraph1' },
+        pandoc.Para { pandoc.Emph { pandoc.Str 'Paragraph2' } }
+      }
+      local expected = {
+        pandoc.Str 'Paragraph1',
+        pandoc.Space(), pandoc.Str '¶', pandoc.Space(),
+        pandoc.Emph { pandoc.Str 'Paragraph2' }
+      }
+      assert.are_same(
+        expected,
+        utils.blocks_to_inlines(blocks)
+      )
+    end),
+    test('custom separator', function ()
+      local blocks = {
+        pandoc.Para{ pandoc.Str 'Paragraph1' },
+        pandoc.Para{ pandoc.Emph 'Paragraph2' }
+      }
+      local expected = {
+        pandoc.Str 'Paragraph1',
+        pandoc.LineBreak(),
+        pandoc.Emph { pandoc.Str 'Paragraph2' }
+      }
+      assert.are_same(
+        expected,
+        utils.blocks_to_inlines(blocks, { pandoc.LineBreak() })
+      )
+    end)
+  },
+
+  group 'hierarchicalize' {
+    test('sanity check', function ()
+      local blks = {
+        pandoc.Header(1, {pandoc.Str 'First'}),
+        pandoc.Header(2, {pandoc.Str 'Second'}),
+        pandoc.Header(2, {pandoc.Str 'Third'}),
+      }
+      local hblks = utils.hierarchicalize(blks)
+      -- cannot create Elements directly; performing only an approximate
+      -- sanity checking instead of a full equality comparison.
+      assert.are_equal('Sec', hblks[1].t)
+      assert.are_equal('Sec', hblks[1].contents[1].t)
+      assert.are_equal(1, hblks[1].contents[2].numbering[1])
+      assert.are_equal(2, hblks[1].contents[2].numbering[2])
+    end)
+  },
+
+  group 'normalize_date' {
+    test('09 Nov 1989', function ()
+      assert.are_equal('1989-11-09', utils.normalize_date '09 Nov 1989')
+    end),
+    test('12/31/2017', function ()
+      assert.are_equal('2017-12-31', utils.normalize_date '12/31/2017')
+    end),
+  },
+
+  group 'sha1' {
+    test('hashing', function ()
+      local ref_hash = '0a0a9f2a6772942557ab5355d76af442f8f65e01'
+      assert.are_equal(ref_hash, utils.sha1 'Hello, World!')
+    end)
+  },
+
+  group 'stringify' {
+    test('inlines', function ()
+      local inline = pandoc.Emph{
+        pandoc.Str 'Cogito',
+        pandoc.Space(),
+        pandoc.Str 'ergo',
+        pandoc.Space(),
+        pandoc.Str 'sum.',
+      }
+      assert.are_equal('Cogito ergo sum.', utils.stringify(inline))
+    end)
+  },
+
+  group 'to_roman_numeral' {
+    test('convertes number', function ()
+      assert.are_equal('MDCCCLXXXVIII', utils.to_roman_numeral(1888))
+    end),
+    test('fails on non-convertible argument', function ()
+      assert.is_falsy(pcall(utils.to_roman_numeral, 'not a number'))
+    end)
+  },
+}
diff --git a/test/lua/module/pandoc.utils.lua b/test/lua/module/pandoc.utils.lua
deleted file mode 100644
index dc37ec354..000000000
--- a/test/lua/module/pandoc.utils.lua
+++ /dev/null
@@ -1,96 +0,0 @@
-local tasty = require 'tasty'
-local utils = require 'pandoc.utils'
-
-local assert = tasty.assert
-local test = tasty.test_case
-local group = tasty.test_group
-
-return {
-  group 'blocks_to_inlines' {
-    test('default separator', function ()
-      local blocks = {
-        pandoc.Para { pandoc.Str 'Paragraph1' },
-        pandoc.Para { pandoc.Emph { pandoc.Str 'Paragraph2' } }
-      }
-      local expected = {
-        pandoc.Str 'Paragraph1',
-        pandoc.Space(), pandoc.Str '¶', pandoc.Space(),
-        pandoc.Emph { pandoc.Str 'Paragraph2' }
-      }
-      assert.are_same(
-        expected,
-        utils.blocks_to_inlines(blocks)
-      )
-    end),
-    test('custom separator', function ()
-      local blocks = {
-        pandoc.Para{ pandoc.Str 'Paragraph1' },
-        pandoc.Para{ pandoc.Emph 'Paragraph2' }
-      }
-      local expected = {
-        pandoc.Str 'Paragraph1',
-        pandoc.LineBreak(),
-        pandoc.Emph { pandoc.Str 'Paragraph2' }
-      }
-      assert.are_same(
-        expected,
-        utils.blocks_to_inlines(blocks, { pandoc.LineBreak() })
-      )
-    end)
-  },
-
-  group 'hierarchicalize' {
-    test('sanity check', function ()
-      local blks = {
-        pandoc.Header(1, {pandoc.Str 'First'}),
-        pandoc.Header(2, {pandoc.Str 'Second'}),
-        pandoc.Header(2, {pandoc.Str 'Third'}),
-      }
-      local hblks = utils.hierarchicalize(blks)
-      -- cannot create Elements directly; performing only an approximate
-      -- sanity checking instead of a full equality comparison.
-      assert.are_equal('Sec', hblks[1].t)
-      assert.are_equal('Sec', hblks[1].contents[1].t)
-      assert.are_equal(1, hblks[1].contents[2].numbering[1])
-      assert.are_equal(2, hblks[1].contents[2].numbering[2])
-    end)
-  },
-
-  group 'normalize_date' {
-    test('09 Nov 1989', function ()
-      assert.are_equal('1989-11-09', utils.normalize_date '09 Nov 1989')
-    end),
-    test('12/31/2017', function ()
-      assert.are_equal('2017-12-31', utils.normalize_date '12/31/2017')
-    end),
-  },
-
-  group 'sha1' {
-    test('hashing', function ()
-      local ref_hash = '0a0a9f2a6772942557ab5355d76af442f8f65e01'
-      assert.are_equal(ref_hash, utils.sha1 'Hello, World!')
-    end)
-  },
-
-  group 'stringify' {
-    test('inlines', function ()
-      local inline = pandoc.Emph{
-        pandoc.Str 'Cogito',
-        pandoc.Space(),
-        pandoc.Str 'ergo',
-        pandoc.Space(),
-        pandoc.Str 'sum.',
-      }
-      assert.are_equal('Cogito ergo sum.', utils.stringify(inline))
-    end)
-  },
-
-  group 'to_roman_numeral' {
-    test('convertes number', function ()
-      assert.are_equal('MDCCCLXXXVIII', utils.to_roman_numeral(1888))
-    end),
-    test('fails on non-convertible argument', function ()
-      assert.is_falsy(pcall(utils.to_roman_numeral, 'not a number'))
-    end)
-  },
-}
-- 
cgit v1.2.3