[DebianGIS-dev] r2520 - in liblas/trunk: . debian debian/patches
frankie at alioth.debian.org
frankie at alioth.debian.org
Tue Oct 6 16:51:32 UTC 2009
Author: frankie
Date: 2009-10-06 16:51:32 +0000 (Tue, 06 Oct 2009)
New Revision: 2520
Added:
liblas/trunk/debian/
liblas/trunk/debian/README.source
liblas/trunk/debian/changelog
liblas/trunk/debian/compat
liblas/trunk/debian/control
liblas/trunk/debian/copyright
liblas/trunk/debian/docs
liblas/trunk/debian/liblas-bin.install
liblas/trunk/debian/liblas-dev.install
liblas/trunk/debian/liblas1.install
liblas/trunk/debian/patches/
liblas/trunk/debian/patches/missing.diff
liblas/trunk/debian/patches/series
liblas/trunk/debian/rules
liblas/trunk/debian/watch
Log:
[svn-inject] Applying Debian modifications to trunk
Property changes on: liblas/trunk/debian
___________________________________________________________________
Added: mergeWithUpstream
+ 1
Added: liblas/trunk/debian/README.source
===================================================================
--- liblas/trunk/debian/README.source (rev 0)
+++ liblas/trunk/debian/README.source 2009-10-06 16:51:32 UTC (rev 2520)
@@ -0,0 +1,18 @@
+liblas for Debian
+-----------------
+
+This package uses quilt to manage all modifications to the upstream
+source. Changes are stored in the source package as diffs in
+debian/patches and applied during the build. Please see:
+
+ /usr/share/doc/quilt/README.source
+
+for more information on how to apply the patches, modify patches, or
+remove a patch.
+
+Currently libLAS is taken from the mercurial repository by
+hg clone http://hg.liblas.org/main
+and using the stable branch to create a suitable snapshot tarball.
+Note that you will need autotools to generate required additional
+files by autogen.sh. Occasionally, Howard Butler takes snapshots
+and publish them as libLAS and PyPI.
Added: liblas/trunk/debian/changelog
===================================================================
--- liblas/trunk/debian/changelog (rev 0)
+++ liblas/trunk/debian/changelog 2009-10-06 16:51:32 UTC (rev 2520)
@@ -0,0 +1,6 @@
+liblas (1.2.1-1) unstable; urgency=low
+
+ * Initial release.
+ (closes: #532415)
+
+ -- Francesco Paolo Lovergine <frankie at debian.org> Fri, 02 Oct 2009 12:36:21 +0200
Added: liblas/trunk/debian/compat
===================================================================
--- liblas/trunk/debian/compat (rev 0)
+++ liblas/trunk/debian/compat 2009-10-06 16:51:32 UTC (rev 2520)
@@ -0,0 +1 @@
+7
Added: liblas/trunk/debian/control
===================================================================
--- liblas/trunk/debian/control (rev 0)
+++ liblas/trunk/debian/control 2009-10-06 16:51:32 UTC (rev 2520)
@@ -0,0 +1,60 @@
+Source: liblas
+Section: science
+Priority: extra
+Maintainer: Debian GIS Project <pkg-grass-devel at lists.alioth.debian.org>
+Uploaders: Francesco Paolo Lovergine <frankie at debian.org>
+Build-Depends: cdbs (>= 0.4.49), debhelper (>= 7), autotools-dev, libgeotiff-dev, libgdal1-dev
+Standards-Version: 3.8.3
+Homepage: http://liblas.org/
+Vcs-Browser: http://svn.debian.org/viewsvn/pkg-grass/packages/liblas/trunk
+Vcs-Svn: svn://svn.debian.org/svn/pkg-grass/packages/liblas/trunk
+
+Package: liblas1
+Architecture: any
+Section: libs
+Suggests: libgeotiff-epsg
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: ASPRS LiDAR data translation library
+ libLAS is a C/C++ library for reading and writing ASPRS LAS versions
+ 1.0, 1.1 and 1.2 data. The LAS format is a sequential binary format
+ used to store data from sensors and as intermediate processing storage
+ by some LiDAR-related applications. LiDAR (Light Detection and Ranging)
+ is an optical remote sensing technology that measures properties of
+ scattered light to find range and/or other information of a distant
+ target. The prevalent method to determine distance to an object or
+ surface is to use laser pulses.
+ .
+ This package contains the shared library used by applications.
+
+Package: liblas-dev
+Architecture: any
+Section: libdevel
+Depends: liblas1 (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
+Description: ASPRS LiDAR data translation library - development
+ libLAS is a C/C++ library for reading and writing ASPRS LAS versions
+ 1.0, 1.1 and 1.2 data. The LAS format is a sequential binary format
+ used to store data from sensors and as intermediate processing storage
+ by some LiDAR-related applications. LiDAR (Light Detection and Ranging)
+ is an optical remote sensing technology that measures properties of
+ scattered light to find range and/or other information of a distant
+ target. The prevalent method to determine distance to an object or
+ surface is to use laser pulses.
+ .
+ This package contains the development files to build applications.
+
+Package: liblas-bin
+Architecture: any
+Depends: liblas1 (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
+Suggests: libgeotiff-epsg
+Description: ASPRS LiDAR data translation toolset
+ libLAS is a C/C++ library for reading and writing ASPRS LAS versions
+ 1.0, 1.1 and 1.2 data. The LAS format is a sequential binary format
+ used to store data from sensors and as intermediate processing storage
+ by some LiDAR-related applications. LiDAR (Light Detection and Ranging)
+ is an optical remote sensing technology that measures properties of
+ scattered light to find range and/or other information of a distant
+ target. The prevalent method to determine distance to an object or
+ surface is to use laser pulses.
+ .
+ This package contains the essential toolset to manage LiDAR data:
+ lasinfo, lasmerge, las2las, las2txt, txt2las, las2ogr.
Added: liblas/trunk/debian/copyright
===================================================================
--- liblas/trunk/debian/copyright (rev 0)
+++ liblas/trunk/debian/copyright 2009-10-06 16:51:32 UTC (rev 2520)
@@ -0,0 +1,53 @@
+This work was packaged for Debian by:
+
+ Francesco Paolo Lovergine <frankie at debian.org> on Fri, 02 Oct 2009 12:36:21 +0200
+
+It was downloaded from http://liblas.org/
+
+Upstream Authors:
+
+ Martin Isenburg and Jonathan Shewchuk <isenburg at cs.unc.edu> (original authors)
+ Mateusz Loskot <mateusz at loskot.net>
+ Howard Butler <hobu.inc at gmail.com>
+ Martin Vales <mrodriguez at stereocarto.com>
+ Phillipe Vachon <philippe at cowpig.ca>
+ Frank Warmerdam <warmerdam at pobox.com>
+ Martin Rodriguez <mrodriguez at stereocarto.com>
+
+Copyrights:
+
+ Copyright (c) 2008, Xiuguang Zhou (ESRI)
+ Copyright (c) 1999, Frank Warmerdam
+ Copyright (c) 2008, Mateusz Loskot
+ Copyright (c) 2008, Howard Butler
+ Copyright (c) 2008, Phil Vachon
+ Copyright (c) 2007, Martin Isenburg
+ Copyright (c) 2008, Martin Rodriguez
+
+License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted under the terms of the BSD License.
+
+ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+On Debian systems, the complete text of the BSD License can be
+found in `/usr/share/common-licenses/BSD'.
+
+The Debian packaging is:
+
+ Copyright (C) 2009 Francesco Paolo Lovergine <frankie at debian.org>
+
+and is licensed under the GPL version 3,
+see `/usr/share/common-licenses/GPL-3'.
+
Added: liblas/trunk/debian/docs
===================================================================
--- liblas/trunk/debian/docs (rev 0)
+++ liblas/trunk/debian/docs 2009-10-06 16:51:32 UTC (rev 2520)
@@ -0,0 +1,3 @@
+NEWS
+README
+AUTHORS
Added: liblas/trunk/debian/liblas-bin.install
===================================================================
--- liblas/trunk/debian/liblas-bin.install (rev 0)
+++ liblas/trunk/debian/liblas-bin.install 2009-10-06 16:51:32 UTC (rev 2520)
@@ -0,0 +1,6 @@
+/usr/bin/las2las
+/usr/bin/las2ogr
+/usr/bin/las2txt
+/usr/bin/lasinfo
+/usr/bin/txt2las
+/usr/bin/lasmerge
Added: liblas/trunk/debian/liblas-dev.install
===================================================================
--- liblas/trunk/debian/liblas-dev.install (rev 0)
+++ liblas/trunk/debian/liblas-dev.install 2009-10-06 16:51:32 UTC (rev 2520)
@@ -0,0 +1,4 @@
+usr/lib/liblas.a
+usr/lib/liblas.so
+usr/include
+usr/bin/liblas-config
Added: liblas/trunk/debian/liblas1.install
===================================================================
--- liblas/trunk/debian/liblas1.install (rev 0)
+++ liblas/trunk/debian/liblas1.install 2009-10-06 16:51:32 UTC (rev 2520)
@@ -0,0 +1,2 @@
+usr/lib/liblas.so.1
+usr/lib/liblas.so.1.0.0
Added: liblas/trunk/debian/patches/missing.diff
===================================================================
--- liblas/trunk/debian/patches/missing.diff (rev 0)
+++ liblas/trunk/debian/patches/missing.diff 2009-10-06 16:51:32 UTC (rev 2520)
@@ -0,0 +1,2481 @@
+
+This patch adds missing files to 1.2.1 tarball.
+
+diff -urN liblas-1.2.1/test/unit/common.hpp main/test/unit/common.hpp
+--- liblas-1.2.1/test/unit/common.hpp 1970-01-01 01:00:00.000000000 +0100
++++ main/test/unit/common.hpp 2009-10-02 16:46:22.000000000 +0200
+@@ -0,0 +1,88 @@
++// $Id$
++//
++// (C) Copyright Mateusz Loskot 2008, mateusz at loskot.net
++// Distributed under the BSD License
++// (See accompanying file LICENSE.txt or copy at
++// http://www.opensource.org/licenses/bsd-license.php)
++//
++#include <liblas/liblas.hpp>
++#include <liblas/laspoint.hpp>
++#include <liblas/lasheader.hpp>
++
++
++namespace tut
++{
++
++// Predicate testing LASPoint against given XY coordinates
++// and tolerance.
++struct is_xy
++{
++ is_xy(double x, double y, double tolerance)
++ : x(x), y(y), t(tolerance)
++ {}
++
++ bool operator()(liblas::LASPoint const& p)
++ {
++ double const dx = x - p.GetX();
++ double const dy = y - p.GetY();
++
++ return ((dx <= t && dx >= -t) && (dy <= t && dy >= -t));
++ }
++
++ double x;
++ double y;
++ double t;
++};
++
++// Functor to calculate bounding box of a set of points
++struct bbox_calculator
++{
++ // bbox object will store operation result
++ bbox_calculator(liblas::detail::Extents<double>& bbox)
++ : empty(true), bbox(bbox)
++ {}
++
++ void operator()(liblas::LASPoint const& p)
++ {
++ // Box initialization during first iteration only
++ if (empty)
++ {
++ bbox.min.x = bbox.max.x = p.GetX();
++ bbox.min.y = bbox.max.y = p.GetY();
++ bbox.min.z = bbox.max.z = p.GetZ();
++ empty = false;
++ }
++
++ // Expand bounding box to include given point
++ bbox.min.x = std::min(bbox.min.x, p.GetX());
++ bbox.min.y = std::min(bbox.min.y, p.GetY());
++ bbox.min.z = std::min(bbox.min.z, p.GetZ());
++ bbox.max.x = std::max(bbox.max.x, p.GetX());
++ bbox.max.y = std::max(bbox.max.y, p.GetY());
++ bbox.max.z = std::max(bbox.max.z, p.GetZ());
++ }
++
++ bool empty;
++ liblas::detail::Extents<double>& bbox;
++};
++
++// Common test procedure for default constructed point data.
++void test_default_point(liblas::LASPoint const& p);
++
++// Common test procedure for default constructed header data.
++void test_default_header(liblas::LASHeader const& h);
++
++// Test of header data in trunk/test/data/TO_core_last_clip.las file
++void test_file10_header(liblas::LASHeader const& h);
++
++// Test of 1st point record in trunk/test/data/TO_core_last_clip.las file
++void test_file10_point1(liblas::LASPoint const& p);
++
++// Test of 2nd point record in trunk/test/data/TO_core_last_clip.las file
++void test_file10_point2(liblas::LASPoint const& p);
++
++// Test of 4th point record in trunk/test/data/TO_core_last_clip.las file
++void test_file10_point4(liblas::LASPoint const& p);
++
++} // namespace tut
++
+diff -urN liblas-1.2.1/test/unit/liblas_test.hpp main/test/unit/liblas_test.hpp
+--- liblas-1.2.1/test/unit/liblas_test.hpp 1970-01-01 01:00:00.000000000 +0100
++++ main/test/unit/liblas_test.hpp 2009-10-02 16:46:22.000000000 +0200
+@@ -0,0 +1,18 @@
++// $Id$
++//
++// (C) Copyright Mateusz Loskot 2008, mateusz at loskot.net
++// Distributed under the BSD License
++// (See accompanying file LICENSE.txt or copy at
++// http://www.opensource.org/licenses/bsd-license.php)
++//
++#ifndef LIBLAS_TEST_HPP_INCLUDED
++#define LIBLAS_TEST_HPP_INCLUDED
++
++namespace tut
++{
++ // full path to trunk/test/data
++ extern std::string g_test_data_path;
++}
++
++#endif // LIBLAS_TEST_HPP_INCLUDED
++
+diff -urN liblas-1.2.1/test/unit/tut/README main/test/unit/tut/README
+--- liblas-1.2.1/test/unit/tut/README 1970-01-01 01:00:00.000000000 +0100
++++ main/test/unit/tut/README 2009-10-02 16:46:36.000000000 +0200
+@@ -0,0 +1,516 @@
++--------------------------------------------------------------------
++TUT: C++ Template Unit Test Framework
++
++Version: TUT-2007-07-06
++Homepage: http://tut-framework.sourceforge.net/
++--------------------------------------------------------------------
++
++Documentation TUT How-To minimum steps to make TUT work for you
++
++What is TUT
++
++TUT is a pure C++ unit test framework. Its name - TUT - stands for
++Template Unit Tests.
++
++Features
++
++TUT provides all features required for unit testing:
++
++ * Similar tests can be grouped together into test groups. Each
++ test group has its unique name and is located in a separate
++ compilation unit. One group can contain almost unlimited number
++ of tests (actually, the limit is the compiler template
++ recursion depth).
++ * User can run all the tests (regression), or just some selected
++ groups or even some tests in these groups.
++ * TUT provides special template functions to check the condition
++ validity at run-time and to force test failure if required.
++ Since C++ doesn't provide a facility for obtaining stack trace
++ of the throwed exception and TUT avoids macros, those functions
++ accept string marker to allow users easely determine the source
++ of exception.
++ * TUT contains callback that can be implemented by the calling code
++ to integrate with an IDE, for example. Callbacks tell listener
++ when a new test run started, when test runner switches to the
++ next tests group, when a test was completed (and what result it
++ has), and when test run was finished. The callbacks allow users
++ to produce their own visualization format for test process and results.
++ * Being a template library, it doesn't need compilation; just
++ include the <tut.h> header into the test modules.
++
++TUT tests organization
++
++Test application
++
++C++ produces executable code, so tests have to be compiled into a single
++binary called test application. The application can be built in automated
++mode to perform nightly tests. They also can be built manually when a
++developer hunts for bugs.
++
++The test application contains tests, organized into test groups.
++
++Test groups
++
++The functionality of a tested application can be divided into a few separate
++function blocks (e.g. User Rights, Export, Processing, ...). It is natural
++to group together tests for each block. TUT invokes this test group. Each
++test group has a unique human-readable name and normally is located in a
++separate file.
++
++Tests
++
++Each single test usually checks only one specific element of functionality.
++For example, for a container a test could check whether size() call
++returns zero after the successful call to the clear() method.
++
++Writing simple test
++
++Preamble
++
++You are going to create a new class for your application. You decided to
++write tests for the class to be sure it works while you are developing or,
++possibly, enhancing it. Let's consider your class is shared pointer:
++std::auto_ptr-alike type that shares the same object among instances.
++
++Prior to test writing, you should decide what to test. Maximalist's
++approach requires to write so many tests that altering any single
++line of your production code will break at least one of them.
++Minimalist's approach allows one to write tests only for the most
++general or the most complex use cases. The truth lies somewhere in
++between, but only you, developer, know where. You should prepare
++common successful and unsuccessful scenarios, and the scenarios for
++testing any other functionality you believe might be broken in some way.
++
++For our shared_ptr we obviosly should test constructors, assignment operators, referencing and passing ownership.
++
++Skeleton
++
++If you don't have any implemented class to test yet, it would be good to
++implement it as a set of stubs for a first time. Thus you'll get an
++interface, and be able to write your tests. Yes, that's correct: you
++should write your tests before writing code! First of all, writing tests
++often helps to understand oddities in the current interface, and fix it.
++Secondly, with the stubs all your tests will fail, so you'll be sure
++they do their job.
++
++Creating Test Group
++
++Since we're writing unit tests, it would be a good idea to group the
++tests for our class in one place to be able to run them separately.
++It's also natural in C++ to place all the grouped tests into one
++compilation unit (i.e. source file). So, to begin, we should create
++a new file. Let's call it test_shared_ptr.cpp. (Final variant of the
++test group can be found in examples/shared_ptr subdirectory of the
++distribution package)
++
++// test_shared_ptr.cpp
++#include <tut.h>
++
++namespace tut
++{
++};
++
++
++As you see, you need to include TUT header file (as expected) and
++use namespace tut for tests. You may also use anonymous namespace if
++your compiler allows it (you will need to instantiate methods from
++tut namespace and some compilers refuse to place such instantiations
++into the anonymous namespace).
++
++A test group in TUT framework is described by the special template
++test_group<T>. The template parameter T is a type that will hold all
++test-specific data during the test execution. Actually, the data
++stored in T are member data of the test. Test object is inherited
++from T, so any test can refer to the data in T as its member data.
++
++For simple test groups (where all data are stored in test local
++variables) type T is an empty struct.
++
++#include <tut.h>
++
++namespace tut
++{
++ struct shared_ptr_data
++ {
++ };
++}
++
++But when tests have complex or repeating creation phase, you may put
++data members into the T and provide constructor (and, if required,
++destructor) for it. For each test, a new instance of T will be
++created. To prepare your test for execution TUT will use default
++constructor. Similarly, after the test has been finished, TUT
++calls the destructor to clean up T. I.e.:
++
++#include <tut.h>
++
++namespace tut
++{
++ struct complex_data
++ {
++ connection* con;
++ complex_data(){ con = db_pool.get_connection(); }
++ ~complex_data(){ db_pool.release_connection(con); }
++ };
++
++ // each test from now will have con data member initialized
++ // by constructor:
++ ...
++ con->commit();
++ ...
++
++
++What will happen if the constructor throws an exception? TUT will treat
++it as if test itself failed with exception, so this test will
++not be executed. You'll see an exception mark near the test, and
++if the constructor throwed something printable, a certain message will appear.
++
++Exception in destructor is threated a bit different. Reaching destruction
++phase means that the test is passed, so TUT marks test with warning
++status meaning that test itself was OK, but something bad has happend
++after the test.
++
++Well, all we have written so far is just a type declaration. To work
++with a group we have to have an object, so we must create the test group
++object. Since we need only one test group object for each unit, we can
++(and should, actually) make this object static. To prevent name clash with
++other test group objects in the namespace tut, we should provide a
++descriptive name, or, alternatively, we may put it into the anonymous
++namespace. The former is more correct, but a descriptive name usually works
++well too, unless you're too terse in giving names to objects.
++
++#include <tut.h>
++
++namespace tut
++{
++ struct shared_ptr_data
++ {
++
++ };
++
++ typedef test_group<shared_ptr_data> tg;
++ tg shared_ptr_group("shared_ptr");
++};
++
++As you see, any test group accepts a single parameter - its human-readable
++name. This name is used to identify the group when a programmer wants to
++execute all tests or a single test within the group. So this name shall
++also be descriptive enough to avoid clashes. Since we're writing tests
++for a specific unit, it's enough to name it after the unit name.
++
++Test group constructor will be called at unspecified moment at the test
++application startup. The constructor performs self-registration; it calls
++tut::runner and asks it to store the test group object name and location.
++Any other test group in the system undergoes the same processing, i.e.
++each test group object registers itself. Thus, test runner can iterate
++all test groups or execute any test group by its name.
++
++Newly created group has no tests associated with it. To be more precise,
++it has predefined set of dummy tests. By default, there are 50 tests in a
++group, including dummy ones. To create a test group with higher volume
++(e.g. when tests are generated by a script and their number is higher)
++we must provide a higher border of test group size when it is instantiated:
++
++#include <tut.h>
++
++namespace tut
++{
++ struct huge_test_data
++ {
++ };
++
++ // test group with maximum 500 tests
++ typedef test_group<huge_test_data,500> testgroup;
++ testgroup huge_test_testgroup("huge group");
++};
++
++
++Note also, that your compiler will possibly need a command-line switch
++or pragma to enlarge recursive instantiation depth. For g++, for
++example, you should specify at least --ftemplate-depth-501 to increase
++the depth. For more information see your compiler documentation.
++
++Creating Tests
++
++Now it's time to fill our test group with content.
++
++In TUT, all tests have unique numbers inside the test group. Some
++people believe that textual names better describe failed tests in
++reports. I agree; but in reality C++ templates work good with numbers
++because they are compile-time constants and refuse to do the same
++with strings, since strings are in fact addresses of character
++buffers, i.e. run-time data.
++
++As I mentioned above, our test group already has a few dummy tests;
++and we can replace any of them with something real just by writing
++our own version:
++
++#include <tut.h>
++
++namespace tut
++{
++ struct shared_ptr_data{};
++
++ typedef test_group<shared_ptr_data> testgroup;
++ typedef testgroup::object testobject;
++ testgroup shared_ptr_testgroup("shared_ptr");
++
++ template<>
++ template<>
++ void testobject::test<1>()
++ {
++ // do nothing test
++ }
++};
++
++
++So far this test does nothing, but it's enough to illustrate the concept.
++
++All tests in the group belong to the type test_group<T>::object. This
++class is directly inherited from our test data structure. In our case, it is
++
++class object : public shared_ptr_data { ... }
++
++This allows to access members of the data structure directly, since at
++the same time they are members of the object type. We also typedef the
++type with testobject for brevity.
++
++We mark our test with number 1. Previously, test group had a dummy test
++with the same number, but now, since we've defined our own version, it
++replaces the dummy test as more specialized one. It's how C++ template
++ordering works.
++
++The test we've written always succeeds. Successful test returns with no
++exceptions. Unsuccessful one either throws an exception, or fails at
++fail() or ensure() methods (which anyway just throw the exception when failed).
++
++First real test
++
++Well, now we know enough to write the first real working test. This test
++will create shared_ptr instances and check their state. We will define a
++small structure (keepee) to use it as shared_ptr stored object type.
++
++#include <tut.h>
++#include <shared_ptr.h>
++
++namespace tut
++{
++ struct shared_ptr_data
++ {
++ struct keepee{ int data; };
++ };
++
++ typedef test_group<shared_ptr_data> testgroup;
++ typedef testgroup::object testobject;
++ testgroup shared_ptr_testgroup("shared_ptr");
++
++ /**
++ * Checks default constructor.
++ */
++ template<>
++ template<>
++ void testobject::test<1>()
++ {
++ shared_ptr<keepee> def;
++ ensure("null",def.get() == 0);
++ }
++};
++
++
++That's all! The first line creates shared_ptr. If constructor throws
++an exception, test will fail (exceptions, including '...', are catched
++by the TUT framework). If the first line succeeds, we must check
++whether the kept object is null one. To do this, we use test object
++member function ensure(), which throws std::logic_error with a given
++message if its second argument is not true. Finally, if destructor of
++shared_ptr fails with exception, TUT also will report this test as failed.
++
++It's equally easy to write a test for the scenario where we expect to get
++an exception: let's consider our class should throw an exception if it
++has no stored object, and the operator -> is called.
++
++/**
++ * Checks operator -> throws instead of returning null.
++ */
++template<>
++template<>
++void testobject::test<2>()
++{
++ try
++ {
++ shared_ptr<keepee> sp;
++ sp->data = 0;
++ fail("exception expected");
++ }
++ catch( const std::runtime_error& ex )
++ {
++ // ok
++ }
++}
++
++
++Here we expect the std::runtime_error. If operator doesn't throw it,
++we'll force the test to fail using another member function: fail(). It
++just throws std::logic_error with a given message. If operator throws
++anything else, our test will fail too, since we intercept only
++std::runtime_error, and any other exception means the test has failed.
++
++NB: our second test has number 2 in its name; it can, actually, be any
++in range 1..Max; the only requirement is not to write tests with the
++same numbers. If you did, compiler will force you to fix them anyway.
++
++And finally, one more test to demonstrate how to use the
++ensure_equals template member function:
++
++/**
++ * Checks keepee counting.
++ */
++template<>
++template<>
++void testobject::test<3>()
++{
++ shared_ptr<keepee> sp1(new keepee());
++ shared_ptr<keepee> sp2(sp1);
++ ensure_equals("second copy at sp1",sp1.count(),2);
++ ensure_equals("second copy at sp2",sp2.count(),2);
++}
++
++
++The test checks if the shared_ptr correctly counts references during
++copy construction. What's interesting here is the template member
++ensure_equals. It has an additional functionality comparing with similar
++call ensure("second_copy",sp1.count()==2); it uses operator == to check
++the equality of the two passed parameters and, what's more important, it
++uses std::stream to format the passed parameters into a human-readable
++message (smth like: "second copy: expected 2, got 1"). It means that
++ensure_equals cannot be used with the types that don't have operator <<;
++but for those having the operator it provides much more informational message.
++
++In contrast to JUnit assertEquals, where the expected value goes before
++the actual one, ensure_equals() accepts the expected after the actual
++value. I believe it's more natural to read ensure_equals("msg", count, 5)
++as "ensure that count equals to 5" rather than JUnit's
++"assert that 5 is the value of the count".
++
++Running tests
++
++Tests are already written, but an attempt to run them will be unsuccessful.
++We need a few other bits to complete the test application.
++
++First of all, we need a main() method, simply because it must be in all
++applications. Secondly, we need a test runner singleton. Remember I said
++each test group should register itself in singleton? So, we need that
++singleton. And, finally, we need a kind of a callback handler to visualize
++our test results.
++
++The design of TUT doesn't strictly set a way the tests are visualized;
++instead, it provides an opportunity to get the test results by means of
++callbacks. Moreover it allows user to output the results in any format he
++prefers. Of course, there is a "reference implementation" in the
++example/subdirectory of the project.
++
++Test runner singleton is defined in tut.h, so all we need to activate it
++is to declare an object of the type tut::test_runner_singleton in the main
++module with a special name tut::runner.
++
++Now, with the test_runner we can run tests. Singleton has method get()
++returning a reference to an instance of the test_runner class, which in
++turn has methods run_tests() to run all tests in all groups,
++run_tests(const std::string& groupname) to run all tests in a given group
++and run_test(const std::string& grp,int n) to run one test in the specified group.
++
++// main.cpp
++#include <tut.h>
++
++namespace tut
++{
++ test_runner_singleton runner;
++}
++
++int main()
++{
++ // run all tests in all groups
++ runner.get().run_tests();
++
++ // run all tests in group "shared_ptr"
++ runner.get().run_tests("shared_ptr");
++
++ // run test number 5 in group "shared_ptr"
++ runner.get().run_test("shared_ptr",5);
++
++ return 0;
++}
++
++It's up to user to handle command-line arguments or GUI messages and map those
++arguments/messages to actual calls to test runner. Again, as you see, TUT
++doesn't restrict user here.
++
++But, the last question is still unanswered: how do we get our test results?
++The answer lies inside tut::callback interface. User shall create its subclass,
++and write up to three simple methods. He also can omit any method since they
++have default no-op implementation. Each corresponding method is called in the
++following cases:
++
++ * a new test run started;
++ * test finished;
++ * test run finished.
++
++Here is a minimal implementation:
++
++class visualizator : public tut::callback
++{
++public:
++ void run_started(){ }
++
++ void test_completed(const tut::test_result& tr)
++ {
++ // ... show test result here ...
++ }
++
++ void run_completed(){ }
++};
++
++The most important is the test_completed() method; its parameter has type
++test_result, and contains everything about the finished test, from its group
++name and number to the exception message, if any. Member result is an enum
++that contains status of the test: ok, fail or ex. Take a look at the
++examples/basic/main.cpp for more complete visualizator.
++
++Visualizator should be passed to the test_runner before run. Knowing that,
++we are ready to write the final version of our main module:
++
++// main.cpp
++#include <tut.h>
++
++namespace tut
++{
++ test_runner_singleton runner;
++}
++
++class callback : public tut::callback
++{
++public:
++ void run_started(){ std::cout << "\nbegin"; }
++
++ void test_completed(const tut::test_result& tr)
++ {
++ std::cout << tr.test_pos << "=" << tr.result << std::flush;
++ }
++
++ void run_completed(){ std::cout << "\nend"; }
++};
++
++int main()
++{
++ callback clbk;
++ runner.get().set_callback(&clbk);
++
++ // run all tests in all groups
++ runner.get().run_tests();
++ return 0;
++}
++
++That's it. You are now ready to link and run our test application. Do it as often as possible;
++once a day is a definite must. I hope, TUT will help you to make your application more
++robust and relieve your testing pain. Feel free to send your questions, suggestions and
++critical opinions to me; I'll do my best to address them asap.
+diff -urN liblas-1.2.1/test/unit/tut/tut.hpp main/test/unit/tut/tut.hpp
+--- liblas-1.2.1/test/unit/tut/tut.hpp 1970-01-01 01:00:00.000000000 +0100
++++ main/test/unit/tut/tut.hpp 2009-10-02 16:46:36.000000000 +0200
+@@ -0,0 +1,1211 @@
++#ifndef TUT_H_GUARD
++#define TUT_H_GUARD
++
++#include <iostream>
++#include <map>
++#include <vector>
++#include <string>
++#include <sstream>
++#include <typeinfo>
++// NOTE: mloskot added for ensure_equals<double,double> specialization
++#include <iomanip>
++#include <limits>
++
++#if defined(TUT_USE_SEH)
++#include <windows.h>
++#include <winbase.h>
++#endif
++
++/**
++ * Template Unit Tests Framework for C++.
++ * http://tut.dozen.ru
++ *
++ * @author Vladimir Dyuzhev, Vladimir.Dyuzhev at gmail.com
++ */
++namespace tut
++{
++
++/**
++ * The base for all TUT exceptions.
++ */
++struct tut_error : public std::exception
++{
++ tut_error(const std::string& msg)
++ : err_msg(msg)
++ {
++ }
++
++ ~tut_error() throw()
++ {
++ }
++
++ const char* what() const throw()
++ {
++ return err_msg.c_str();
++ }
++
++private:
++
++ std::string err_msg;
++};
++
++/**
++ * Exception to be throwed when attempted to execute
++ * missed test by number.
++ */
++struct no_such_test : public tut_error
++{
++ no_such_test()
++ : tut_error("no such test")
++ {
++ }
++
++ ~no_such_test() throw()
++ {
++ }
++};
++
++/**
++ * No such test and passed test number is higher than
++ * any test number in current group. Used in one-by-one
++ * test running when upper bound is not known.
++ */
++struct beyond_last_test : public no_such_test
++{
++ beyond_last_test()
++ {
++ }
++
++ ~beyond_last_test() throw()
++ {
++ }
++};
++
++/**
++ * Group not found exception.
++ */
++struct no_such_group : public tut_error
++{
++ no_such_group(const std::string& grp)
++ : tut_error(grp)
++ {
++ }
++
++ ~no_such_group() throw()
++ {
++ }
++};
++
++/**
++ * Internal exception to be throwed when
++ * no more tests left in group or journal.
++ */
++struct no_more_tests
++{
++ no_more_tests()
++ {
++ }
++
++ ~no_more_tests() throw()
++ {
++ }
++};
++
++/**
++ * Internal exception to be throwed when
++ * test constructor has failed.
++ */
++struct bad_ctor : public tut_error
++{
++ bad_ctor(const std::string& msg)
++ : tut_error(msg)
++ {
++ }
++
++ ~bad_ctor() throw()
++ {
++ }
++};
++
++/**
++ * Exception to be throwed when ensure() fails or fail() called.
++ */
++struct failure : public tut_error
++{
++ failure(const std::string& msg)
++ : tut_error(msg)
++ {
++ }
++
++ ~failure() throw()
++ {
++ }
++};
++
++/**
++ * Exception to be throwed when test desctructor throwed an exception.
++ */
++struct warning : public tut_error
++{
++ warning(const std::string& msg)
++ : tut_error(msg)
++ {
++ }
++
++ ~warning() throw()
++ {
++ }
++};
++
++/**
++ * Exception to be throwed when test issued SEH (Win32)
++ */
++struct seh : public tut_error
++{
++ seh(const std::string& msg)
++ : tut_error(msg)
++ {
++ }
++
++ ~seh() throw()
++ {
++ }
++};
++
++/**
++ * Return type of runned test/test group.
++ *
++ * For test: contains result of test and, possible, message
++ * for failure or exception.
++ */
++struct test_result
++{
++ /**
++ * Test group name.
++ */
++ std::string group;
++
++ /**
++ * Test number in group.
++ */
++ int test;
++
++ /**
++ * Test name (optional)
++ */
++ std::string name;
++
++ /**
++ * ok - test finished successfully
++ * fail - test failed with ensure() or fail() methods
++ * ex - test throwed an exceptions
++ * warn - test finished successfully, but test destructor throwed
++ * term - test forced test application to terminate abnormally
++ */
++ enum result_type
++ {
++ ok,
++ fail,
++ ex,
++ warn,
++ term,
++ ex_ctor
++ };
++
++ result_type result;
++
++ /**
++ * Exception message for failed test.
++ */
++ std::string message;
++ std::string exception_typeid;
++
++ /**
++ * Default constructor.
++ */
++ test_result()
++ : test(0),
++ result(ok)
++ {
++ }
++
++ /**
++ * Constructor.
++ */
++ test_result(const std::string& grp, int pos,
++ const std::string& test_name, result_type res)
++ : group(grp),
++ test(pos),
++ name(test_name),
++ result(res)
++ {
++ }
++
++ /**
++ * Constructor with exception.
++ */
++ test_result(const std::string& grp,int pos,
++ const std::string& test_name, result_type res,
++ const std::exception& ex)
++ : group(grp),
++ test(pos),
++ name(test_name),
++ result(res),
++ message(ex.what()),
++ exception_typeid(typeid(ex).name())
++ {
++ }
++};
++
++/**
++ * Interface.
++ * Test group operations.
++ */
++struct group_base
++{
++ virtual ~group_base()
++ {
++ }
++
++ // execute tests iteratively
++ virtual void rewind() = 0;
++ virtual test_result run_next() = 0;
++
++ // execute one test
++ virtual test_result run_test(int n) = 0;
++};
++
++/**
++ * Test runner callback interface.
++ * Can be implemented by caller to update
++ * tests results in real-time. User can implement
++ * any of callback methods, and leave unused
++ * in default implementation.
++ */
++struct callback
++{
++ /**
++ * Virtual destructor is a must for subclassed types.
++ */
++ virtual ~callback()
++ {
++ }
++
++ /**
++ * Called when new test run started.
++ */
++ virtual void run_started()
++ {
++ }
++
++ /**
++ * Called when a group started
++ * @param name Name of the group
++ */
++ virtual void group_started(const std::string& /*name*/)
++ {
++ }
++
++ /**
++ * Called when a test finished.
++ * @param tr Test results.
++ */
++ virtual void test_completed(const test_result& /*tr*/)
++ {
++ }
++
++ /**
++ * Called when a group is completed
++ * @param name Name of the group
++ */
++ virtual void group_completed(const std::string& /*name*/)
++ {
++ }
++
++ /**
++ * Called when all tests in run completed.
++ */
++ virtual void run_completed()
++ {
++ }
++};
++
++/**
++ * Typedef for runner::list_groups()
++ */
++typedef std::vector<std::string> groupnames;
++
++/**
++ * Test runner.
++ */
++class test_runner
++{
++
++public:
++
++ /**
++ * Constructor
++ */
++ test_runner()
++ : callback_(&default_callback_)
++ {
++ }
++
++ /**
++ * Stores another group for getting by name.
++ */
++ void register_group(const std::string& name, group_base* gr)
++ {
++ if (gr == 0)
++ {
++ throw tut_error("group shall be non-null");
++ }
++
++ // TODO: inline variable
++ groups::iterator found = groups_.find(name);
++ if (found != groups_.end())
++ {
++ std::string msg("attempt to add already existent group " + name);
++ // this exception terminates application so we use cerr also
++ // TODO: should this message appear in stream?
++ std::cerr << msg << std::endl;
++ throw tut_error(msg);
++ }
++
++ groups_[name] = gr;
++ }
++
++ /**
++ * Stores callback object.
++ */
++ void set_callback(callback* cb)
++ {
++ callback_ = cb == 0 ? &default_callback_ : cb;
++ }
++
++ /**
++ * Returns callback object.
++ */
++ callback& get_callback() const
++ {
++ return *callback_;
++ }
++
++ /**
++ * Returns list of known test groups.
++ */
++ const groupnames list_groups() const
++ {
++ groupnames ret;
++ const_iterator i = groups_.begin();
++ const_iterator e = groups_.end();
++ while (i != e)
++ {
++ ret.push_back(i->first);
++ ++i;
++ }
++ return ret;
++ }
++
++ /**
++ * Runs all tests in all groups.
++ * @param callback Callback object if exists; null otherwise
++ */
++ void run_tests() const
++ {
++ callback_->run_started();
++
++ const_iterator i = groups_.begin();
++ const_iterator e = groups_.end();
++ while (i != e)
++ {
++ callback_->group_started(i->first);
++ try
++ {
++ run_all_tests_in_group_(i);
++ }
++ catch (const no_more_tests&)
++ {
++ callback_->group_completed(i->first);
++ }
++
++ ++i;
++ }
++
++ callback_->run_completed();
++ }
++
++ /**
++ * Runs all tests in specified group.
++ */
++ void run_tests(const std::string& group_name) const
++ {
++ callback_->run_started();
++
++ const_iterator i = groups_.find(group_name);
++ if (i == groups_.end())
++ {
++ callback_->run_completed();
++ throw no_such_group(group_name);
++ }
++
++ callback_->group_started(group_name);
++ try
++ {
++ run_all_tests_in_group_(i);
++ }
++ catch (const no_more_tests&)
++ {
++ // ok
++ }
++
++ callback_->group_completed(group_name);
++ callback_->run_completed();
++ }
++
++ /**
++ * Runs one test in specified group.
++ */
++ test_result run_test(const std::string& group_name, int n) const
++ {
++ callback_->run_started();
++
++ const_iterator i = groups_.find(group_name);
++ if (i == groups_.end())
++ {
++ callback_->run_completed();
++ throw no_such_group(group_name);
++ }
++
++ callback_->group_started(group_name);
++ try
++ {
++ test_result tr = i->second->run_test(n);
++ callback_->test_completed(tr);
++ callback_->group_completed(group_name);
++ callback_->run_completed();
++ return tr;
++ }
++ catch (const beyond_last_test&)
++ {
++ callback_->group_completed(group_name);
++ callback_->run_completed();
++ throw;
++ }
++ catch (const no_such_test&)
++ {
++ callback_->group_completed(group_name);
++ callback_->run_completed();
++ throw;
++ }
++ }
++
++protected:
++
++ typedef std::map<std::string, group_base*> groups;
++ typedef groups::iterator iterator;
++ typedef groups::const_iterator const_iterator;
++ groups groups_;
++
++ callback default_callback_;
++ callback* callback_;
++
++
++private:
++
++ void run_all_tests_in_group_(const_iterator i) const
++ {
++ i->second->rewind();
++ for ( ;; )
++ {
++ test_result tr = i->second->run_next();
++ callback_->test_completed(tr);
++
++ if (tr.result == test_result::ex_ctor)
++ {
++ throw no_more_tests();
++ }
++ }
++ }
++};
++
++/**
++ * Singleton for test_runner implementation.
++ * Instance with name runner_singleton shall be implemented
++ * by user.
++ */
++class test_runner_singleton
++{
++public:
++
++ static test_runner& get()
++ {
++ static test_runner tr;
++ return tr;
++ }
++};
++
++extern test_runner_singleton runner;
++
++/**
++ * Test object. Contains data test run upon and default test method
++ * implementation. Inherited from Data to allow tests to
++ * access test data as members.
++ */
++template <class Data>
++class test_object : public Data
++{
++public:
++
++ /**
++ * Default constructor
++ */
++ test_object()
++ {
++ }
++
++ void set_test_name(const std::string& current_test_name)
++ {
++ current_test_name_ = current_test_name;
++ }
++
++ const std::string& get_test_name() const
++ {
++ return current_test_name_;
++ }
++
++ /**
++ * Default do-nothing test.
++ */
++ template <int n>
++ void test()
++ {
++ called_method_was_a_dummy_test_ = true;
++ }
++
++ /**
++ * The flag is set to true by default (dummy) test.
++ * Used to detect usused test numbers and avoid unnecessary
++ * test object creation which may be time-consuming depending
++ * on operations described in Data::Data() and Data::~Data().
++ * TODO: replace with throwing special exception from default test.
++ */
++ bool called_method_was_a_dummy_test_;
++
++private:
++
++ std::string current_test_name_;
++};
++
++namespace
++{
++
++/**
++ * Tests provided condition.
++ * Throws if false.
++ */
++void ensure(bool cond)
++{
++ if (!cond)
++ {
++ // TODO: default ctor?
++ throw failure("");
++ }
++}
++
++/**
++ * Tests provided condition.
++ * Throws if true.
++ */
++void ensure_not(bool cond)
++{
++ ensure(!cond);
++}
++
++/**
++ * Tests provided condition.
++ * Throws if false.
++ */
++template <typename T>
++void ensure(const T msg, bool cond)
++{
++ if (!cond)
++ {
++ throw failure(msg);
++ }
++}
++
++/**
++ * Tests provided condition.
++ * Throws if true.
++ */
++template <typename T>
++void ensure_not(const T msg, bool cond)
++{
++ ensure(msg, !cond);
++}
++
++/**
++ * Tests two objects for being equal.
++ * Throws if false.
++ *
++ * NB: both T and Q must have operator << defined somewhere, or
++ * client code will not compile at all!
++ */
++template <class T, class Q>
++void ensure_equals(const char* msg, const Q& actual, const T& expected)
++{
++ if (expected != actual)
++ {
++ std::stringstream ss;
++ ss << (msg ? msg : "")
++ << (msg ? ":" : "")
++ << " expected '"
++ << expected
++ << "' actual '"
++ << actual
++ << '\'';
++ throw failure(ss.str().c_str());
++ }
++}
++
++template <class T, class Q>
++void ensure_equals(const Q& actual, const T& expected)
++{
++ ensure_equals<>(0, actual, expected);
++}
++
++/**
++ * Specialization of ensure_equals for double type.
++ * NOTE: unofficial extension added by mloskot
++ */
++template <>
++void ensure_equals<double, double>(const char* msg, const double& actual, const double& expected)
++{
++ const double epsilon = std::numeric_limits<double>::epsilon();
++ const double diff = actual - expected;
++
++ if ( !((diff <= epsilon) && (diff >= -epsilon )) )
++ {
++ std::stringstream ss;
++ ss << (msg?msg:"") << (msg?": ":"")
++ << std::scientific << std::showpoint << std::setprecision(16)
++ << "expected " << expected
++ << " actual " << actual
++ << " with precision " << epsilon;
++ throw failure(ss.str().c_str());
++ }
++}
++
++template <>
++void ensure_equals<double, double>(const double& actual, const double& expected)
++{
++ ensure_equals<>(0, actual, expected);
++}
++
++/**
++ * Tests two objects for being at most in given distance one from another.
++ * Borders are excluded.
++ * Throws if false.
++ *
++ * NB: T must have operator << defined somewhere, or
++ * client code will not compile at all! Also, T shall have
++ * operators + and -, and be comparable.
++ */
++template <class T>
++void ensure_distance(const char* msg, const T& actual, const T& expected,
++ const T& distance)
++{
++ if (expected-distance >= actual || expected+distance <= actual)
++ {
++ std::stringstream ss;
++ ss << (msg ? msg : "")
++ << (msg? ":" : "")
++ << " expected ("
++ << expected-distance
++ << " - "
++ << expected+distance
++ << ") actual '"
++ << actual
++ << '\'';
++ throw failure(ss.str().c_str());
++ }
++}
++
++template <class T>
++void ensure_distance(const T& actual, const T& expected, const T& distance)
++{
++ ensure_distance<>(0, actual, expected, distance);
++}
++
++/**
++ * Unconditionally fails with message.
++ */
++void fail(const char* msg = "")
++{
++ throw failure(msg);
++}
++
++} // end of namespace
++
++/**
++ * Walks through test tree and stores address of each
++ * test method in group. Instantiation stops at 0.
++ */
++template <class Test, class Group, int n>
++struct tests_registerer
++{
++ static void reg(Group& group)
++ {
++ group.reg(n, &Test::template test<n>);
++ tests_registerer<Test, Group, n - 1>::reg(group);
++ }
++};
++
++template <class Test, class Group>
++struct tests_registerer<Test, Group, 0>
++{
++ static void reg(Group&)
++ {
++ }
++};
++
++/**
++ * Test group; used to recreate test object instance for
++ * each new test since we have to have reinitialized
++ * Data base class.
++ */
++template <class Data, int MaxTestsInGroup = 50>
++class test_group : public group_base
++{
++ const char* name_;
++
++ typedef void (test_object<Data>::*testmethod)();
++ typedef std::map<int, testmethod> tests;
++ typedef typename tests::iterator tests_iterator;
++ typedef typename tests::const_iterator tests_const_iterator;
++ typedef typename tests::const_reverse_iterator
++ tests_const_reverse_iterator;
++ typedef typename tests::size_type size_type;
++
++ tests tests_;
++ tests_iterator current_test_;
++
++ /**
++ * Exception-in-destructor-safe smart-pointer class.
++ */
++ template <class T>
++ class safe_holder
++ {
++ T* p_;
++ bool permit_throw_in_dtor;
++
++ safe_holder(const safe_holder&);
++ safe_holder& operator=(const safe_holder&);
++
++ public:
++ safe_holder()
++ : p_(0),
++ permit_throw_in_dtor(false)
++ {
++ }
++
++ ~safe_holder()
++ {
++ release();
++ }
++
++ T* operator->() const
++ {
++ return p_;
++ }
++
++ T* get() const
++ {
++ return p_;
++ }
++
++ /**
++ * Tell ptr it can throw from destructor. Right way is to
++ * use std::uncaught_exception(), but some compilers lack
++ * correct implementation of the function.
++ */
++ void permit_throw()
++ {
++ permit_throw_in_dtor = true;
++ }
++
++ /**
++ * Specially treats exceptions in test object destructor;
++ * if test itself failed, exceptions in destructor
++ * are ignored; if test was successful and destructor failed,
++ * warning exception throwed.
++ */
++ void release()
++ {
++ try
++ {
++ if (delete_obj() == false)
++ {
++ throw warning("destructor of test object raised"
++ " an SEH exception");
++ }
++ }
++ catch (const std::exception& ex)
++ {
++ if (permit_throw_in_dtor)
++ {
++ std::string msg = "destructor of test object raised"
++ " exception: ";
++ msg += ex.what();
++ throw warning(msg);
++ }
++ }
++ catch( ... )
++ {
++ if (permit_throw_in_dtor)
++ {
++ throw warning("destructor of test object raised an"
++ " exception");
++ }
++ }
++ }
++
++ /**
++ * Re-init holder to get brand new object.
++ */
++ void reset()
++ {
++ release();
++ permit_throw_in_dtor = false;
++ p_ = new T();
++ }
++
++ bool delete_obj()
++ {
++#if defined(TUT_USE_SEH)
++ __try
++ {
++#endif
++ T* p = p_;
++ p_ = 0;
++ delete p;
++#if defined(TUT_USE_SEH)
++ }
++ __except(handle_seh_(::GetExceptionCode()))
++ {
++ if (permit_throw_in_dtor)
++ {
++ return false;
++ }
++ }
++#endif
++ return true;
++ }
++ };
++
++public:
++
++ typedef test_object<Data> object;
++
++ /**
++ * Creates and registers test group with specified name.
++ */
++ test_group(const char* name)
++ : name_(name)
++ {
++ // register itself
++ runner.get().register_group(name_,this);
++
++ // register all tests
++ tests_registerer<object, test_group, MaxTestsInGroup>::reg(*this);
++ }
++
++ /**
++ * This constructor is used in self-test run only.
++ */
++ test_group(const char* name, test_runner& another_runner)
++ : name_(name)
++ {
++ // register itself
++ another_runner.register_group(name_, this);
++
++ // register all tests
++ tests_registerer<test_object<Data>, test_group,
++ MaxTestsInGroup>::reg(*this);
++ };
++
++ /**
++ * Registers test method under given number.
++ */
++ void reg(int n, testmethod tm)
++ {
++ tests_[n] = tm;
++ }
++
++ /**
++ * Reset test position before first test.
++ */
++ void rewind()
++ {
++ current_test_ = tests_.begin();
++ }
++
++ /**
++ * Runs next test.
++ */
++ test_result run_next()
++ {
++ if (current_test_ == tests_.end())
++ {
++ throw no_more_tests();
++ }
++
++ // find next user-specialized test
++ safe_holder<object> obj;
++ while (current_test_ != tests_.end())
++ {
++ try
++ {
++ return run_test_(current_test_++, obj);
++ }
++ catch (const no_such_test&)
++ {
++ continue;
++ }
++ }
++
++ throw no_more_tests();
++ }
++
++ /**
++ * Runs one test by position.
++ */
++ test_result run_test(int n)
++ {
++ // beyond tests is special case to discover upper limit
++ if (tests_.rbegin() == tests_.rend())
++ {
++ throw beyond_last_test();
++ }
++
++ if (tests_.rbegin()->first < n)
++ {
++ throw beyond_last_test();
++ }
++
++ // withing scope; check if given test exists
++ tests_iterator ti = tests_.find(n);
++ if (ti == tests_.end())
++ {
++ throw no_such_test();
++ }
++
++ safe_holder<object> obj;
++ return run_test_(ti, obj);
++ }
++
++private:
++
++ /**
++ * VC allows only one exception handling type per function,
++ * so I have to split the method.
++ *
++ * TODO: refactoring needed!
++ */
++ test_result run_test_(const tests_iterator& ti, safe_holder<object>& obj)
++ {
++ std::string current_test_name;
++ try
++ {
++ if (run_test_seh_(ti->second,obj, current_test_name) == false)
++ {
++ throw seh("seh");
++ }
++ }
++ catch (const no_such_test&)
++ {
++ throw;
++ }
++ catch (const warning& ex)
++ {
++ // test ok, but destructor failed
++ if (obj.get())
++ {
++ current_test_name = obj->get_test_name();
++ }
++ test_result tr(name_,ti->first, current_test_name,
++ test_result::warn, ex);
++ return tr;
++ }
++ catch (const failure& ex)
++ {
++ // test failed because of ensure() or similar method
++ if (obj.get())
++ {
++ current_test_name = obj->get_test_name();
++ }
++ test_result tr(name_,ti->first, current_test_name,
++ test_result::fail, ex);
++ return tr;
++ }
++ catch (const seh& ex)
++ {
++ // test failed with sigsegv, divide by zero, etc
++ if (obj.get())
++ {
++ current_test_name = obj->get_test_name();
++ }
++ test_result tr(name_, ti->first, current_test_name,
++ test_result::term, ex);
++ return tr;
++ }
++ catch (const bad_ctor& ex)
++ {
++ // test failed because test ctor failed; stop the whole group
++ if (obj.get())
++ {
++ current_test_name = obj->get_test_name();
++ }
++ test_result tr(name_, ti->first, current_test_name,
++ test_result::ex_ctor, ex);
++ return tr;
++ }
++ catch (const std::exception& ex)
++ {
++ // test failed with std::exception
++ if (obj.get())
++ {
++ current_test_name = obj->get_test_name();
++ }
++ test_result tr(name_, ti->first, current_test_name,
++ test_result::ex, ex);
++ return tr;
++ }
++ catch (...)
++ {
++ // test failed with unknown exception
++ if (obj.get())
++ {
++ current_test_name = obj->get_test_name();
++ }
++ test_result tr(name_, ti->first, current_test_name,
++ test_result::ex);
++ return tr;
++ }
++
++ // test passed
++ test_result tr(name_,ti->first, current_test_name, test_result::ok);
++ return tr;
++ }
++
++ /**
++ * Runs one under SEH if platform supports it.
++ */
++ bool run_test_seh_(testmethod tm, safe_holder<object>& obj,
++ std::string& current_test_name)
++ {
++#if defined(TUT_USE_SEH)
++ __try
++ {
++#endif
++ if (obj.get() == 0)
++ {
++ reset_holder_(obj);
++ }
++
++ obj->called_method_was_a_dummy_test_ = false;
++
++#if defined(TUT_USE_SEH)
++
++ __try
++ {
++#endif
++ (obj.get()->*tm)();
++#if defined(TUT_USE_SEH)
++ }
++ __except(handle_seh_(::GetExceptionCode()))
++ {
++ // throw seh("SEH");
++ current_test_name = obj->get_test_name();
++ return false;
++ }
++#endif
++
++ if (obj->called_method_was_a_dummy_test_)
++ {
++ // do not call obj.release(); reuse object
++ throw no_such_test();
++ }
++
++ current_test_name = obj->get_test_name();
++ obj.permit_throw();
++ obj.release();
++#if defined(TUT_USE_SEH)
++ }
++ __except(handle_seh_(::GetExceptionCode()))
++ {
++ return false;
++ }
++#endif
++ return true;
++ }
++
++ void reset_holder_(safe_holder<object>& obj)
++ {
++ try
++ {
++ obj.reset();
++ }
++ catch (const std::exception& ex)
++ {
++ throw bad_ctor(ex.what());
++ }
++ catch (...)
++ {
++ throw bad_ctor("test constructor has generated an exception;"
++ " group execution is terminated");
++ }
++ }
++};
++
++#if defined(TUT_USE_SEH)
++/**
++ * Decides should we execute handler or ignore SE.
++ */
++inline int handle_seh_(DWORD excode)
++{
++ switch(excode)
++ {
++ case EXCEPTION_ACCESS_VIOLATION:
++ case EXCEPTION_DATATYPE_MISALIGNMENT:
++ case EXCEPTION_BREAKPOINT:
++ case EXCEPTION_SINGLE_STEP:
++ case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
++ case EXCEPTION_FLT_DENORMAL_OPERAND:
++ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
++ case EXCEPTION_FLT_INEXACT_RESULT:
++ case EXCEPTION_FLT_INVALID_OPERATION:
++ case EXCEPTION_FLT_OVERFLOW:
++ case EXCEPTION_FLT_STACK_CHECK:
++ case EXCEPTION_FLT_UNDERFLOW:
++ case EXCEPTION_INT_DIVIDE_BY_ZERO:
++ case EXCEPTION_INT_OVERFLOW:
++ case EXCEPTION_PRIV_INSTRUCTION:
++ case EXCEPTION_IN_PAGE_ERROR:
++ case EXCEPTION_ILLEGAL_INSTRUCTION:
++ case EXCEPTION_NONCONTINUABLE_EXCEPTION:
++ case EXCEPTION_STACK_OVERFLOW:
++ case EXCEPTION_INVALID_DISPOSITION:
++ case EXCEPTION_GUARD_PAGE:
++ case EXCEPTION_INVALID_HANDLE:
++ return EXCEPTION_EXECUTE_HANDLER;
++ };
++
++ return EXCEPTION_CONTINUE_SEARCH;
++}
++#endif
++}
++
++#endif
++
+diff -urN liblas-1.2.1/test/unit/tut/tut_reporter.hpp main/test/unit/tut/tut_reporter.hpp
+--- liblas-1.2.1/test/unit/tut/tut_reporter.hpp 1970-01-01 01:00:00.000000000 +0100
++++ main/test/unit/tut/tut_reporter.hpp 2009-10-02 16:46:36.000000000 +0200
+@@ -0,0 +1,227 @@
++#ifndef TUT_REPORTER
++#define TUT_REPORTER
++
++#include <tut/tut.hpp>
++
++/**
++ * Template Unit Tests Framework for C++.
++ * http://tut.dozen.ru
++ *
++ * @author Vladimir Dyuzhev, Vladimir.Dyuzhev at gmail.com
++ */
++namespace
++{
++
++std::ostream& operator<<(std::ostream& os, const tut::test_result& tr)
++{
++ switch(tr.result)
++ {
++ case tut::test_result::ok:
++ os << '.';
++ break;
++ case tut::test_result::fail:
++ os << '[' << tr.test << "=F]";
++ break;
++ case tut::test_result::ex_ctor:
++ os << '[' << tr.test << "=C]";
++ break;
++ case tut::test_result::ex:
++ os << '[' << tr.test << "=X]";
++ break;
++ case tut::test_result::warn:
++ os << '[' << tr.test << "=W]";
++ break;
++ case tut::test_result::term:
++ os << '[' << tr.test << "=T]";
++ break;
++ }
++
++ return os;
++}
++
++} // end of namespace
++
++namespace tut
++{
++
++/**
++ * Default TUT callback handler.
++ */
++class reporter : public tut::callback
++{
++ std::string current_group;
++ typedef std::vector<tut::test_result> not_passed_list;
++ not_passed_list not_passed;
++ std::ostream& os;
++
++public:
++
++ int ok_count;
++ int exceptions_count;
++ int failures_count;
++ int terminations_count;
++ int warnings_count;
++
++ reporter()
++ : os(std::cout)
++ {
++ init();
++ }
++
++ reporter(std::ostream& out)
++ : os(out)
++ {
++ init();
++ }
++
++ void run_started()
++ {
++ init();
++ }
++
++ void test_completed(const tut::test_result& tr)
++ {
++ if (tr.group != current_group)
++ {
++ os << std::endl << tr.group << ": " << std::flush;
++ current_group = tr.group;
++ }
++
++ os << tr << std::flush;
++ if (tr.result == tut::test_result::ok)
++ {
++ ok_count++;
++ }
++ else if (tr.result == tut::test_result::ex)
++ {
++ exceptions_count++;
++ }
++ else if (tr.result == tut::test_result::ex_ctor)
++ {
++ exceptions_count++;
++ }
++ else if (tr.result == tut::test_result::fail)
++ {
++ failures_count++;
++ }
++ else if (tr.result == tut::test_result::warn)
++ {
++ warnings_count++;
++ }
++ else
++ {
++ terminations_count++;
++ }
++
++ if (tr.result != tut::test_result::ok)
++ {
++ not_passed.push_back(tr);
++ }
++ }
++
++ void run_completed()
++ {
++ os << std::endl;
++
++ if (not_passed.size() > 0)
++ {
++ not_passed_list::const_iterator i = not_passed.begin();
++ while (i != not_passed.end())
++ {
++ tut::test_result tr = *i;
++
++ os << std::endl;
++
++ os << "---> " << "group: " << tr.group
++ << ", test: test<" << tr.test << ">"
++ << (!tr.name.empty() ? (std::string(" : ") + tr.name) : std::string())
++ << std::endl;
++
++ os << " problem: ";
++ switch(tr.result)
++ {
++ case test_result::fail:
++ os << "assertion failed" << std::endl;
++ break;
++ case test_result::ex:
++ case test_result::ex_ctor:
++ os << "unexpected exception" << std::endl;
++ if( tr.exception_typeid != "" )
++ {
++ os << " exception typeid: "
++ << tr.exception_typeid << std::endl;
++ }
++ break;
++ case test_result::term:
++ os << "would be terminated" << std::endl;
++ break;
++ case test_result::warn:
++ os << "test passed, but cleanup code (destructor) raised"
++ " an exception" << std::endl;
++ break;
++ default:
++ break;
++ }
++
++ if (!tr.message.empty())
++ {
++ if (tr.result == test_result::fail)
++ {
++ os << " failed assertion: \"" << tr.message << "\""
++ << std::endl;
++ }
++ else
++ {
++ os << " message: \"" << tr.message << "\""
++ << std::endl;
++ }
++ }
++
++ ++i;
++ }
++ }
++
++ os << std::endl;
++
++ os << "tests summary:";
++ if (terminations_count > 0)
++ {
++ os << " terminations:" << terminations_count;
++ }
++ if (exceptions_count > 0)
++ {
++ os << " exceptions:" << exceptions_count;
++ }
++ if (failures_count > 0)
++ {
++ os << " failures:" << failures_count;
++ }
++ if (warnings_count > 0)
++ {
++ os << " warnings:" << warnings_count;
++ }
++ os << " ok:" << ok_count;
++ os << std::endl;
++ }
++
++ bool all_ok() const
++ {
++ return not_passed.empty();
++ }
++
++private:
++
++ void init()
++ {
++ ok_count = 0;
++ exceptions_count = 0;
++ failures_count = 0;
++ terminations_count = 0;
++ warnings_count = 0;
++ not_passed.clear();
++ }
++};
++
++}
++
++#endif
+diff -urN liblas-1.2.1/test/unit/tut/tut_restartable.hpp main/test/unit/tut/tut_restartable.hpp
+--- liblas-1.2.1/test/unit/tut/tut_restartable.hpp 1970-01-01 01:00:00.000000000 +0100
++++ main/test/unit/tut/tut_restartable.hpp 2009-10-02 16:46:36.000000000 +0200
+@@ -0,0 +1,394 @@
++#ifndef TUT_RESTARTABLE_H_GUARD
++#define TUT_RESTARTABLE_H_GUARD
++
++#include <tut/tut.hpp>
++#include <fstream>
++#include <iostream>
++#include <stdexcept>
++
++/**
++ * Template Unit Tests Framework for C++.
++ * http://tut.dozen.ru
++ *
++ * Optional restartable wrapper for test_runner. Allows to restart test runs
++ * finished due to abnormal test application termination (such as segmentation
++ * fault or math error).
++ *
++ * @author Vladimir Dyuzhev, Vladimir.Dyuzhev at gmail.com
++ */
++
++namespace tut
++{
++
++namespace util
++{
++
++/**
++ * Escapes non-alphabetical characters in string.
++ */
++std::string escape(const std::string& orig)
++{
++ std::string rc;
++ std::string::const_iterator i,e;
++ i = orig.begin();
++ e = orig.end();
++
++ while (i != e)
++ {
++ if ((*i >= 'a' && *i <= 'z') ||
++ (*i >= 'A' && *i <= 'Z') ||
++ (*i >= '0' && *i <= '9') )
++ {
++ rc += *i;
++ }
++ else
++ {
++ rc += '\\';
++ rc += ('a'+(((unsigned int)*i) >> 4));
++ rc += ('a'+(((unsigned int)*i) & 0xF));
++ }
++
++ ++i;
++ }
++ return rc;
++}
++
++/**
++ * Un-escapes string.
++ */
++std::string unescape(const std::string& orig)
++{
++ std::string rc;
++ std::string::const_iterator i,e;
++ i = orig.begin();
++ e = orig.end();
++
++ while (i != e)
++ {
++ if (*i != '\\')
++ {
++ rc += *i;
++ }
++ else
++ {
++ ++i;
++ if (i == e)
++ {
++ throw std::invalid_argument("unexpected end of string");
++ }
++ unsigned int c1 = *i;
++ ++i;
++ if (i == e)
++ {
++ throw std::invalid_argument("unexpected end of string");
++ }
++ unsigned int c2 = *i;
++ rc += (((c1 - 'a') << 4) + (c2 - 'a'));
++ }
++
++ ++i;
++ }
++ return rc;
++}
++
++/**
++ * Serialize test_result avoiding interfering with operator <<.
++ */
++void serialize(std::ostream& os, const tut::test_result& tr)
++{
++ os << escape(tr.group) << std::endl;
++ os << tr.test << ' ';
++ switch(tr.result)
++ {
++ case test_result::ok:
++ os << 0;
++ break;
++ case test_result::fail:
++ os << 1;
++ break;
++ case test_result::ex:
++ os << 2;
++ break;
++ case test_result::warn:
++ os << 3;
++ break;
++ case test_result::term:
++ os << 4;
++ break;
++ default:
++ throw std::logic_error("operator << : bad result_type");
++ }
++ os << ' ' << escape(tr.message) << std::endl;
++}
++
++/**
++ * deserialization for test_result
++ */
++void deserialize(std::istream& is, tut::test_result& tr)
++{
++ std::getline(is,tr.group);
++ if (is.eof())
++ {
++ throw tut::no_more_tests();
++ }
++ tr.group = unescape(tr.group);
++
++ tr.test = -1;
++ is >> tr.test;
++ if (tr.test < 0)
++ {
++ throw std::logic_error("operator >> : bad test number");
++ }
++
++ int n = -1;
++ is >> n;
++ switch(n)
++ {
++ case 0:
++ tr.result = test_result::ok;
++ break;
++ case 1:
++ tr.result = test_result::fail;
++ break;
++ case 2:
++ tr.result = test_result::ex;
++ break;
++ case 3:
++ tr.result = test_result::warn;
++ break;
++ case 4:
++ tr.result = test_result::term;
++ break;
++ default:
++ throw std::logic_error("operator >> : bad result_type");
++ }
++
++ is.ignore(1); // space
++ std::getline(is,tr.message);
++ tr.message = unescape(tr.message);
++ if (!is.good())
++ {
++ throw std::logic_error("malformed test result");
++ }
++}
++};
++
++/**
++ * Restartable test runner wrapper.
++ */
++class restartable_wrapper
++{
++ test_runner& runner_;
++ callback* callback_;
++
++ std::string dir_;
++ std::string log_; // log file: last test being executed
++ std::string jrn_; // journal file: results of all executed tests
++
++public:
++ /**
++ * Default constructor.
++ * @param dir Directory where to search/put log and journal files
++ */
++ restartable_wrapper(const std::string& dir = ".")
++ : runner_(runner.get()),
++ callback_(0),
++ dir_(dir)
++ {
++ // dozen: it works, but it would be better to use system path separator
++ jrn_ = dir_ + '/' + "journal.tut";
++ log_ = dir_ + '/' + "log.tut";
++ }
++
++ /**
++ * Stores another group for getting by name.
++ */
++ void register_group(const std::string& name, group_base* gr)
++ {
++ runner_.register_group(name,gr);
++ }
++
++ /**
++ * Stores callback object.
++ */
++ void set_callback(callback* cb)
++ {
++ callback_ = cb;
++ }
++
++ /**
++ * Returns callback object.
++ */
++ callback& get_callback() const
++ {
++ return runner_.get_callback();
++ }
++
++ /**
++ * Returns list of known test groups.
++ */
++ groupnames list_groups() const
++ {
++ return runner_.list_groups();
++ }
++
++ /**
++ * Runs all tests in all groups.
++ */
++ void run_tests() const
++ {
++ // where last run was failed
++ std::string fail_group;
++ int fail_test;
++ read_log_(fail_group,fail_test);
++ bool fail_group_reached = (fail_group == "");
++
++ // iterate over groups
++ tut::groupnames gn = list_groups();
++ tut::groupnames::const_iterator gni,gne;
++ gni = gn.begin();
++ gne = gn.end();
++ while (gni != gne)
++ {
++ // skip all groups before one that failed
++ if (!fail_group_reached)
++ {
++ if (*gni != fail_group)
++ {
++ ++gni;
++ continue;
++ }
++ fail_group_reached = true;
++ }
++
++ // first or restarted run
++ int test = (*gni == fail_group && fail_test >= 0) ? fail_test + 1 : 1;
++ while(true)
++ {
++ // last executed test pos
++ register_execution_(*gni,test);
++
++ try
++ {
++ tut::test_result tr = runner_.run_test(*gni,test);
++ register_test_(tr);
++ }
++ catch (const tut::beyond_last_test&)
++ {
++ break;
++ }
++ catch(const tut::no_such_test&)
++ {
++ // it's ok
++ }
++
++ ++test;
++ }
++
++ ++gni;
++ }
++
++ // show final results to user
++ invoke_callback_();
++
++ // truncate files as mark of successful finish
++ truncate_();
++ }
++
++private:
++ /**
++ * Shows results from journal file.
++ */
++ void invoke_callback_() const
++ {
++ runner_.set_callback(callback_);
++ runner_.get_callback().run_started();
++
++ std::string current_group;
++ std::ifstream ijournal(jrn_.c_str());
++ while (ijournal.good())
++ {
++ // read next test result
++ try
++ {
++ tut::test_result tr;
++ util::deserialize(ijournal,tr);
++ runner_.get_callback().test_completed(tr);
++ }
++ catch (const no_more_tests&)
++ {
++ break;
++ }
++ }
++
++ runner_.get_callback().run_completed();
++ }
++
++ /**
++ * Register test into journal.
++ */
++ void register_test_(const test_result& tr) const
++ {
++ std::ofstream ojournal(jrn_.c_str(), std::ios::app);
++ util::serialize(ojournal, tr);
++ ojournal << std::flush;
++ if (!ojournal.good())
++ {
++ throw std::runtime_error("unable to register test result in file "
++ + jrn_);
++ }
++ }
++
++ /**
++ * Mark the fact test going to be executed
++ */
++ void register_execution_(const std::string& grp, int test) const
++ {
++ // last executed test pos
++ std::ofstream olog(log_.c_str());
++ olog << util::escape(grp) << std::endl << test << std::endl << std::flush;
++ if (!olog.good())
++ {
++ throw std::runtime_error("unable to register execution in file "
++ + log_);
++ }
++ }
++
++ /**
++ * Truncate tests.
++ */
++ void truncate_() const
++ {
++ std::ofstream olog(log_.c_str());
++ std::ofstream ojournal(jrn_.c_str());
++ }
++
++ /**
++ * Read log file
++ */
++ void read_log_(std::string& fail_group, int& fail_test) const
++ {
++ // read failure point, if any
++ std::ifstream ilog(log_.c_str());
++ std::getline(ilog,fail_group);
++ fail_group = util::unescape(fail_group);
++ ilog >> fail_test;
++ if (!ilog.good())
++ {
++ fail_group = "";
++ fail_test = -1;
++ truncate_();
++ }
++ else
++ {
++ // test was terminated...
++ tut::test_result tr(fail_group, fail_test, "", tut::test_result::term);
++ register_test_(tr);
++ }
++ }
++};
++
++}
++
++#endif
++
Added: liblas/trunk/debian/patches/series
===================================================================
--- liblas/trunk/debian/patches/series (rev 0)
+++ liblas/trunk/debian/patches/series 2009-10-06 16:51:32 UTC (rev 2520)
@@ -0,0 +1,2 @@
+# no patches
+missing.diff
Added: liblas/trunk/debian/rules
===================================================================
--- liblas/trunk/debian/rules (rev 0)
+++ liblas/trunk/debian/rules 2009-10-06 16:51:32 UTC (rev 2520)
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/class/autotools.mk
+include /usr/share/cdbs/1/rules/patchsys-quilt.mk
+
+DEB_CONFIGURE_EXTRA_FLAGS = --with-gdal=/usr/bin/gdal-config --with-geotiff=/usr
+DEB_MAKE_CHECK_TARGET = check
+
Property changes on: liblas/trunk/debian/rules
___________________________________________________________________
Added: svn:executable
+ *
Added: liblas/trunk/debian/watch
===================================================================
--- liblas/trunk/debian/watch (rev 0)
+++ liblas/trunk/debian/watch 2009-10-06 16:51:32 UTC (rev 2520)
@@ -0,0 +1,6 @@
+# Rename this file to "watch" and then you can run the "uscan" command
+# to check for upstream updates and more.
+# See uscan(1) for format
+# Compulsory line, this is a version 3 file
+version=3
+http://liblas.org/wiki/1.2.1 http://liblas.org/raw-attachment/wiki/1.2.1/liblas-src-([\d\.]+).tar.bz2
More information about the Pkg-grass-devel
mailing list