/**
 * @file test-utils.h
 * @author Peter Rockai (mornfall) <mornfall@danill.sk>
 * @brief Utility functions for the unit tests
 */
#include <tut.h>

#define TESTGRP(name) \
typedef test_group<name ## _shar> tg; \
typedef tg::object to; \
tg name ## _tg (#name);

namespace tut_guessnet {

inline static std::string __ensure_errmsg(std::string f, int l, std::string msg)
{
    char buf[64];
    snprintf(buf, 63, "%d", l);
    buf[63] = 0;
    std::string ln = buf;
    f.append(":");
    f.append(ln);
    f.append(": '");
    f.append(msg);
    f.append("'");
    return f;
}
#define gen_ensure(x) ensure (__ensure_errmsg(__FILE__, __LINE__, #x).c_str(), (x))

}

#if 0
#include <string>
#include <tagcoll/stringf.h>

#define TEST_TAGCOLL

#ifdef TEST_TAGCOLL
#include <tagcoll/Collection.h>
#include <tagcoll/Patches.h>
#endif
/*
#include <apt-front/cache.h>
#include <apt-pkg/configuration.h>
#include <apt-pkg/error.h>
#include <apt-pkg/pkgsystem.h>
#include <apt-pkg/init.h>
#include <iostream>
*/



namespace tut_tagcoll {
using namespace std;
using namespace stringf;
using namespace Tagcoll;
using namespace tut;

template<class ITEM, class TAG>
class TestConsumer : public Tagcoll::Consumer<ITEM, TAG>
{
protected:
	virtual void consumeItemUntagged(const ITEM& item) { items++; }

	virtual void consumeItem(const ITEM& item, const OpSet<TAG>& tags)
	{
		items++;
		this->tags += tags.size();
	}
	
public:
	int items;
	int tags;

	TestConsumer() : items(0), tags(0) {}
};

void outputCollection(const std::string& str, Tagcoll::Consumer<string, string>& cons);

void __tc_ensure_coll_equal(std::string f, int l, std::string s,
		const Tagcoll::Collection<string, string>& c1,
		const Tagcoll::Collection<string, string>& c2);
#define ensure_coll_equal(a, b) \
	__tc_ensure_coll_equal(__FILE__, __LINE__, #a " == " #b, a, b)


inline static std::string __tc_ensure_errmsg(std::string f, int l, std::string f1, int l1, std::string msg)
{
    return f + ":" + fmt(l) + ": '" + f1 + ":" + fmt(l1) + ": " + msg + "'";
}

#ifdef TEST_TAGCOLL
inline static void __test_tagged_collection(std::string f, int l, Collection<string, string>& tc)
{
#define ttc_ensure(x) ensure (__tc_ensure_errmsg(f, l, __FILE__, __LINE__, #x).c_str(), (x))
	// Test handling of untagged items (they are not stored)
	tc.consume("untagged");
	ttc_ensure(tc.getTags("untagged").empty());
	
	// Test handling of tagged items
	OpSet<string> tagset;
	tagset += "tag1"; tagset += "tag2";
	tc.consume("tagged", tagset);
	ttc_ensure(tc.getTaggedItems().contains("tagged"));
	//ttc_ensure(tc.hasTag("tag1"));
	//ttc_ensure(tc.hasTag("tag2"));
	tagset = tc.getTags("tagged");
	ttc_ensure(tagset.contains("tag1"));
	ttc_ensure(tagset.contains("tag2"));
	OpSet<string> itemset = tc.getItems("tag1");
	ttc_ensure(itemset.contains("tagged"));
	itemset = tc.getItems("tag2");
	ttc_ensure(itemset.contains("tagged"));
	tagset = tc.getAllTags();
	ttc_ensure(tagset.contains("tag1"));
	ttc_ensure(tagset.contains("tag2"));
	tagset.clear();
	tagset += "tag1";
	tagset = tc.getCompanionTags(tagset);
	ttc_ensure(!tagset.contains("tag1"));
	ttc_ensure(tagset.contains("tag2"));

	// Test handling of changes
	PatchList<string, string> change;
	Patch<string, string> p("tagged");
	tagset.clear();
	p.remove("tag1");
	p.remove("tag2");
	change.addPatch(p);

	tc.applyChange(change);
	
	// "tagged" should now be untagged
	ttc_ensure(tc.getTags("tagged").empty());

	tc.applyChange(change.getReverse());

	// "tagged" should now be as before
	//ttc_ensure(tc.hasTag("tag1"));
	//ttc_ensure(tc.hasTag("tag2"));
	tagset = tc.getTags("tagged");
	ttc_ensure(tagset.contains("tag1"));
	ttc_ensure(tagset.contains("tag2"));
	itemset = tc.getItems("tag1");
	ttc_ensure(itemset.contains("tagged"));
	itemset = tc.getItems("tag2");
	ttc_ensure(itemset.contains("tagged"));
	tagset = tc.getAllTags();
	ttc_ensure(tagset.contains("tag1"));
	ttc_ensure(tagset.contains("tag2"));
	tagset.clear();
	tagset += "tag1";
	tagset = tc.getCompanionTags(tagset);
	ttc_ensure(!tagset.contains("tag1"));
	ttc_ensure(tagset.contains("tag2"));

	// Try a patch that adds a tag
	change = PatchList<string, string>();
	p = Patch<string, string>("tagged");
	p.add("tag3");
	change.addPatch(p);
	tc.applyChange(change);

	//ttc_ensure(tc.hasTag("tag1"));
	//ttc_ensure(tc.hasTag("tag2"));
	//ttc_ensure(tc.hasTag("tag3"));
	tagset = tc.getTags("tagged");
	ttc_ensure(tagset.contains("tag1"));
	ttc_ensure(tagset.contains("tag2"));
	ttc_ensure(tagset.contains("tag3"));
	itemset = tc.getItems("tag1");
	ttc_ensure(itemset.contains("tagged"));
	itemset = tc.getItems("tag2");
	ttc_ensure(itemset.contains("tagged"));
	itemset = tc.getItems("tag3");
	ttc_ensure(itemset.contains("tagged"));
	tagset = tc.getAllTags();
	ttc_ensure(tagset.contains("tag1"));
	ttc_ensure(tagset.contains("tag2"));
	ttc_ensure(tagset.contains("tag3"));
	tagset.clear();
	tagset += "tag1";
	tagset = tc.getCompanionTags(tagset);
	ttc_ensure(!tagset.contains("tag1"));
	ttc_ensure(tagset.contains("tag2"));
	ttc_ensure(tagset.contains("tag3"));

	// Try a patch that adds some items
	change = PatchList<string, string>();
	p = Patch<string, string>("tagged1");
	p.add("tag1");
	p.add("tag2");
	p.add("tag4");
	change.addPatch(p);
	tc.applyChange(change);

	tagset = tc.getTags("tagged1");
	ttc_ensure(tagset.contains("tag1"));
	ttc_ensure(tagset.contains("tag2"));
	ttc_ensure(!tagset.contains("tag3"));
	ttc_ensure(tagset.contains("tag4"));
	itemset = tc.getItems("tag1");
	ttc_ensure(itemset.contains("tagged1"));
	itemset = tc.getItems("tag2");
	ttc_ensure(itemset.contains("tagged1"));
	itemset = tc.getItems("tag3");
	ttc_ensure(!itemset.contains("tagged1"));
	itemset = tc.getItems("tag4");
	ttc_ensure(!itemset.contains("tagged"));
	ttc_ensure(itemset.contains("tagged1"));
	tagset = tc.getAllTags();
	ttc_ensure(tagset.contains("tag1"));
	ttc_ensure(tagset.contains("tag2"));
	ttc_ensure(tagset.contains("tag3"));
	ttc_ensure(tagset.contains("tag4"));
	tagset.clear();
	tagset += "tag1";
	tagset = tc.getCompanionTags(tagset);
	ttc_ensure(!tagset.contains("tag1"));
	ttc_ensure(tagset.contains("tag2"));
	ttc_ensure(tagset.contains("tag3"));
	ttc_ensure(tagset.contains("tag4"));

	// And reverse it
	tc.applyChange(change.getReverse());

	itemset = tc.getItems("tag1");
	ttc_ensure(!itemset.contains("tagged1"));
	itemset = tc.getItems("tag2");
	ttc_ensure(!itemset.contains("tagged1"));
	itemset = tc.getItems("tag3");
	ttc_ensure(!itemset.contains("tagged1"));
	ttc_ensure(tc.getItems("tag4") == OpSet<string>());
	tagset = tc.getAllTags();
	ttc_ensure(tagset.contains("tag1"));
	ttc_ensure(tagset.contains("tag2"));
	ttc_ensure(tagset.contains("tag3"));
	ttc_ensure(!tagset.contains("tag4"));
	tagset.clear();
	tagset += "tag1";
	tagset = tc.getCompanionTags(tagset);
	ttc_ensure(!tagset.contains("tag1"));
	ttc_ensure(tagset.contains("tag2"));
	ttc_ensure(tagset.contains("tag3"));
	ttc_ensure(!tagset.contains("tag4"));
#undef ttc_ensure
}
#endif
}

#define test_tagged_collection(x) (__test_tagged_collection(__FILE__, __LINE__, (x)))

/*
namespace tut {
    static void aptInit () {
        pkgInitConfig (*_config);
        _config->Set("Dir", CACHE_DIR);
        _config->Set("Dir::Cache", "cache");
        _config->Set("Dir::State", "state");
        _config->Set("Dir::Etc", "etc");
        _config->Set("Dir::State::status", CACHE_DIR "dpkg-status");
        pkgInitSystem (*_config, _system);
        // _config -> Set ("Capture::Cache::UseExtState", extstate);
    }
}
*/

#endif
