#! /usr/bin/env ruby

# Read a file with a test description, run augtool against it and
# look at the diff between the original file and the .augnew file
# The test description can contain the following:
# commands - a string that is fed to augtool
# diff     - a hash mapping file names to the diff between that
#            file and the .augnew file
# echo     - boolean, when true show the whole ouput of augtool
# refresh  - boolean, when true print bad diffs in a form
#            that can be easily cut&pasted back into the test description

require 'find'
require 'fileutils'

def augnew?(path)
    File::file?(path) && File::fnmatch?("*.augnew", File::basename(path))
end

TOP_DIR=File::join(File::dirname(__FILE__), "..")
TOP_BUILDDIR=ENV["abs_top_builddir"] || TOP_DIR
TOP_SRCDIR=ENV["abs_top_srcdir"] || TOP_DIR

TEST_DIR=File::join(TOP_SRCDIR, "tests")

AUGEAS_ROOT=File::join(TOP_BUILDDIR, "build", "augtest")
AUGEAS_LENS_LIB=File::join(TOP_SRCDIR, "lenses")

ENV["AUGEAS_ROOT"] = AUGEAS_ROOT
ENV["AUGEAS_LENS_LIB"] = AUGEAS_LENS_LIB

args=ARGV
if args.size == 0
    args = Dir::glob("#{TEST_DIR}/*.rb").sort
end

WIDTH = args.inject(0) do |max, arg|
  s = File::basename(arg, ".rb").size
  (s > max) ? s : max
end
status = 0

args.each do |test|
    if File::directory?(AUGEAS_ROOT)
        FileUtils::rm_rf(AUGEAS_ROOT)
    end
    FileUtils::mkdir_p(AUGEAS_ROOT)
    FileUtils::cp_r(File::join(TEST_DIR, "root", "."), AUGEAS_ROOT)
    Find.find(AUGEAS_ROOT) do |path|
        if augnew?(path)
            File::delete(path)
        end
    end
    commands = nil
    diff = {}
    echo=false
    refresh=false
    skip=false

    eval(IO::read(test))
    redir = echo ? "" : "> /dev/null"
    printf("Test %-#{WIDTH}s ... ", File::basename(test, ".rb"))
    unless skip
        IO.popen("augtool --nostdinc -n #{redir}", "w") do |io|
            io.print(commands)
            io.puts("\nquit")
        end
        success=$?.success?
        msgs = []
        diff.each do |file, exp|
            file = File::join(AUGEAS_ROOT, file).gsub(%r{//}, '/')
            if ! File::exist?("#{file}.augnew")
                msgs << "Expected file #{file}.augnew"
                success=false
            else
                act=`diff -u #{file} #{file}.augnew | sed -e 's/^ $//'`
                act.gsub!(/^(--- #{file}).*$/, '\1')
                act.gsub!(/^(\+\+\+ #{file}\.augnew).*$/, '\1')
                act.gsub!(/^(---|\+\+\+) (#{AUGEAS_ROOT})/, '\1 ');
                if ! exp.nil? && act != exp
                    success=false
                    if ! refresh
                        msgs << act
                    else
                        msgs << act.gsub(/\t/, '\\t')
                    end
                end
            end
        end
        files = diff.keys.collect { |f| File::join(AUGEAS_ROOT, "#{f}.augnew").gsub(%r{//}, '/') }
        Find.find(AUGEAS_ROOT) do |path|
            if augnew?(path) && ! files.include?(path)
                success=false
                msgs << "Unexpected file #{path}"
            end
        end
    end
    if skip
        puts "SKIPPED"
    elsif success
        puts "OK"
    else
        puts "FAIL"
        status = 1
        msgs.each { |m| puts m }
    end
end

exit(status)
