, ReadFunc, WriteFunc, ini_parser_error>
    (
        ReadFunc(), WriteFunc(), error_data_2, NULL,
        "testerr2.ini", NULL, "testerr2out.ini", 3
    );
}

void test_unmappable_trees()
{
    // Test too deep ptrees
    {
        ptree pt;
        pt.put_child("section.key.bogus", ptree());
        test_erroneous_write(pt);
    }

    // Test duplicate sections
    {
        ptree pt;
        pt.push_back(std::make_pair("section", ptree()));
        pt.push_back(std::make_pair("section", ptree()));
        test_erroneous_write(pt);
    }

    // Test duplicate keys
    {
        ptree pt;
        ptree &child = pt.put_child("section", ptree());
        child.push_back(std::make_pair("key", ptree()));
        child.push_back(std::make_pair("key", ptree()));
        test_erroneous_write(pt);
    }

    // Test mixed data and children.
    {
        ptree pt;
        ptree &child = pt.put_child("section", ptree("value"));
        child.push_back(std::make_pair("key", ptree()));
        child.push_back(std::make_pair("key", ptree()));
        test_erroneous_write(pt);
    }
}

void test_other_trees()
{
    // Top-level keys must be written before any section.
    {
        ptree pt;
        pt.put("section.innerkey", "v1");
        pt.put("nosection", "v2");
        std::stringstream s;
        write_ini(s, pt);
        s.clear();
        s.seekg(0, std::ios_base::beg);
        ptree result;
        read_ini(s, result);
        BOOST_CHECK(result.get("section.innerkey", "bad") == "v1");
        BOOST_CHECK(result.get("nosection", "bad") == "v2");
    }
}

int test_main(int argc, char *argv[])
{
    test_ini_parser<ptree>();
    test_ini_parser<iptree>();
#ifndef BOOST_NO_CWCHAR
    test_ini_parser<wptree>();
    test_ini_parser<wiptree>();
#endif

    test_unmappable_trees();
    test_other_trees();
 
    return 0;

}


// Package errors provides simple error handling primitives.
//
// The traditional error handling idiom in Go is roughly akin to
//
//     if err != nil {
//             return err
//     }
//
// 