-- test/test-gall.commit.lua
--
-- Git Abstraction layer for Lua - Commit object tests
--
-- Copyright 2012 Daniel Silverstone <dsilvers@digital-scurf.org>
--
-- For Licence terms, see COPYING
--

-- This test includes object wibbling
dofile "test/withrepo.lua"

-- Step one, start coverage

pcall(require, 'luacov')

local gall = require 'gall'

local testnames = {}

local real_assert = assert
local total_asserts = 0
local function assert(...)
   local retval = real_assert(...)
   total_asserts = total_asserts + 1
   return retval
end

local function add_test(suite, name, value)
   rawset(suite, name, value)
   testnames[#testnames+1] = name
end

local suite = setmetatable({}, {__newindex = add_test})

function suite.commit_get()
   local repo = test_repo()
   local commit = repo:get("refs/heads/master").content
   assert(commit)
end

function suite.commit_tostring()
   local repo = test_repo()
   local commit = repo:get("refs/heads/master").content
   local commitstr = tostring(commit)
   assert(commitstr:find("GitCommit"))
end

function suite.commit_message()
   local repo = test_repo()
   local commit = repo:get("refs/heads/master").content
   local commitmsg = commit.message
   assert(commitmsg:find("Merge branch"))
end

function suite.commit_parents()
   local repo = test_repo()
   local commit = repo:get("refs/heads/master").content
   local parents = commit.parents
   assert(parents[1])
   assert(parents[2])
   assert(parents[1].type == "commit")
   assert(parents[2].type == "commit")
   assert(not parents[3])
end

function suite.commit_committer()
   local repo = test_repo()
   local commit = repo:get("refs/heads/master").content
   local person = commit.committer
   assert(person.realname:find("Committer"))
   assert(person.email:find("gall%-committer"))
   assert(person.unixtime == "1347114766")
   assert(person.timezone == "+0100")
end

function suite.commit_author()
   local repo = test_repo()
   local commit = repo:get("refs/heads/master").content
   local person = commit.author
   assert(person.realname:find("Author"))
   assert(person.email:find("gall%-author"))
   assert(person.unixtime == "1347114766")
   assert(person.timezone == "+0000")
end

function suite.commit_signature()
   local repo = test_repo()
   local commit = repo:get("refs/heads/signed").content
   local sig = commit.signature
   assert(sig)
end

function suite.commit_create()
   local repo = test_repo()
   local head = repo:get("HEAD").content
   local tree = head.tree
   local commitinfo = {
      tree = tree,
      author = {
	 realname = "Test Author",
	 email = "author@test"
      },
      committer = {
	 realname = "Test Committer",
	 email = "committer@test"
      },
      message = "NEWCOMMIT",
      parents = { head },
   }
   local newcommit = assert(gall.commit.create(repo, commitinfo))
end

function suite.commit_create_no_parents_ok()
   local repo = test_repo()
   local head = repo:get("HEAD").content
   local tree = head.tree
   local commitinfo = {
      tree = tree,
      author = {
	 realname = "Test Author",
	 email = "author@test"
      },
      committer = {
	 realname = "Test Committer",
	 email = "committer@test"
      },
      message = "NEWCOMMIT",
   }
   local newcommit = assert(gall.commit.create(repo, commitinfo))
end

function suite.commit_create_bad_no_tree()
   local repo = test_repo()
   local head = repo:get("HEAD").content
   local tree = head.tree
   local commitinfo = {
   }
   local ok, msg = gall.commit.create(repo, commitinfo)
   assert(not ok)
   assert(msg:find("No tree"))
end

function suite.commit_create_bad_no_author()
   local repo = test_repo()
   local head = repo:get("HEAD").content
   local tree = head.tree
   local commitinfo = {
      tree = tree,
   }
   local ok, msg = gall.commit.create(repo, commitinfo)
   assert(not ok)
   assert(msg:find("No author"))
end

function suite.commit_create_bad_no_committer()
   local repo = test_repo()
   local head = repo:get("HEAD").content
   local tree = head.tree
   local commitinfo = {
      tree = tree,
      author = {},
   }
   local ok, msg = gall.commit.create(repo, commitinfo)
   assert(not ok)
   assert(msg:find("No committer"))
end

function suite.commit_create_bad_no_author_name()
   local repo = test_repo()
   local head = repo:get("HEAD").content
   local tree = head.tree
   local commitinfo = {
      tree = tree,
      author = {},
      committer = {},
   }
   local ok, msg = gall.commit.create(repo, commitinfo)
   assert(not ok)
   assert(msg:find("No author name"))
end

function suite.commit_create_bad_no_author_email()
   local repo = test_repo()
   local head = repo:get("HEAD").content
   local tree = head.tree
   local commitinfo = {
      tree = tree,
      author = { realname = "Author" },
      committer = {},
   }
   local ok, msg = gall.commit.create(repo, commitinfo)
   assert(not ok)
   assert(msg:find("No author email"))
end

function suite.commit_create_bad_no_committer_name()
   local repo = test_repo()
   local head = repo:get("HEAD").content
   local tree = head.tree
   local commitinfo = {
      tree = tree,
      author = { realname = "Author", email = "author@foo" },
      committer = {},
   }
   local ok, msg = gall.commit.create(repo, commitinfo)
   assert(not ok)
   assert(msg:find("No committer name"))
end

function suite.commit_create_bad_no_committer_email()
   local repo = test_repo()
   local head = repo:get("HEAD").content
   local tree = head.tree
   local commitinfo = {
      tree = tree,
      author = { realname = "Author", email = "author@foo" },
      committer = { realname = "Committer" },
   }
   local ok, msg = gall.commit.create(repo, commitinfo)
   assert(not ok)
   assert(msg:find("No committer email"))
end

function suite.commit_create_bad_no_message()
   local repo = test_repo()
   local head = repo:get("HEAD").content
   local tree = head.tree
   local commitinfo = {
      tree = tree,
      author = {
	 realname = "Test Author",
	 email = "author@test"
      },
      committer = {
	 realname = "Test Committer",
	 email = "committer@test"
      },
      parents = { head },
   }
   local ok, msg = gall.commit.create(repo, commitinfo)
   assert(not ok)
   assert(msg:find("No message"))
end

function suite.commit_create_bad_parent_no_sha()
   local repo = test_repo()
   local head = repo:get("HEAD").content
   local tree = head.tree
   local commitinfo = {
      tree = tree,
      author = {
	 realname = "Test Author",
	 email = "author@test"
      },
      committer = {
	 realname = "Test Committer",
	 email = "committer@test"
      },
      message = "NEWCOMMIT",
      parents = { {} },
   }
   local ok, msg = gall.commit.create(repo, commitinfo)
   assert(not ok)
   assert(msg:find("had no sha"))
end

function suite.commit_create_bad_parent_bad_sha()
   local repo = test_repo()
   local head = repo:get("HEAD").content
   local tree = head.tree
   local commitinfo = {
      tree = tree,
      author = {
	 realname = "Test Author",
	 email = "author@test"
      },
      committer = {
	 realname = "Test Committer",
	 email = "committer@test"
      },
      message = "NEWCOMMIT",
      parents = { { sha = "BADSHA" } },
   }
   local ok, msg = gall.commit.create(repo, commitinfo)
   assert(not ok)
   assert(msg:find("BADSHA"))
end

local count_ok = 0
for _, testname in ipairs(testnames) do
--   print("Run: " .. testname)
   local ok, err = xpcall(suite[testname], debug.traceback)
   if not ok then
      print(err)
      print()
   else
      count_ok = count_ok + 1
   end
end

print(tostring(count_ok) .. "/" .. tostring(#testnames) .. " [" .. tostring(total_asserts) .. "] OK")

os.exit(count_ok == #testnames and 0 or 1)
