packages feed

squeeze-1.0.1.4: src/Squeeze/QC.hs

{-# OPTIONS_GHC -fno-warn-orphans #-}
{-
	Copyright (C) 2010 Dr. Alistair Ward

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
-}
{- |
 [@AUTHOR@]	Dr. Alistair Ward

 [@DESCRIPTION@]	Defines tests to dynamically verify the module "Squeeze.Squeeze" against arbitrary data.
-}

module Squeeze.QC(
-- * Types
-- ** Type-synonyms
--	Testable,
-- * Functions
	quickChecks
) where

import qualified	Control.Arrow
import qualified	Data.List
import qualified	Test.QuickCheck
import qualified	Squeeze.File		as File
import qualified	Squeeze.FileSizeBounds	as FileSizeBounds
import qualified	Squeeze.Squeeze		as Squeeze

type Testable	= [File.FileSizeAndPath] -> Test.QuickCheck.Property

-- | Defines invariant properties, which must hold for any 'FileSizeAndPath'.
quickChecks :: (Testable -> IO ()) -> IO ()
quickChecks	= (`mapM_` [prop_bisectionRatio, prop_totalCombinations, prop_bounds, prop_all])	where
	translate :: [File.FileSizeAndPath] -> [File.FileSizeAndPath]
	translate	= Data.List.nub . map (Control.Arrow.first abs)

	prop_bisectionRatio, prop_totalCombinations, prop_bounds, prop_all :: Testable
	prop_bisectionRatio fileSizeAndPathList	= Test.QuickCheck.label "prop_bisectionRatio" $ (== 1) . length . Data.List.nub . map (
		\bisectionRatio	-> Data.List.sort . Squeeze.distribute bisectionRatio fileSizeBounds $ File.order l
	 ) . take 8 {-arbitrarily-} $ map ((1.0 /) . fromInteger) [1 ..]	where
		l :: [File.FileSizeAndPath]
		l	= take 10 {-arbitrarily-} $ translate fileSizeAndPathList	--CAVEAT: may be shorter than requested.

		fileSizeBounds :: FileSizeBounds.FileSizeBounds
		fileSizeBounds	= (minimumBytes, maximumBytes)	where
			maximumBytes, minimumBytes :: File.FileSize
			maximumBytes	= round $ fromIntegral (File.aggregateSize l) / (4.0 :: Double)	--Arbitrarily.
			minimumBytes	= maximumBytes `div` 2						--Arbitrarily.

	prop_totalCombinations fileSizeAndPathList	=  Test.QuickCheck.label "prop_totalCombinations" $ (length . Data.List.nub . Squeeze.findCombinations (0, fromIntegral (maxBound :: Int)) $ File.order l) == 2 ^ length l where
		l :: [File.FileSizeAndPath]
		l	= take 10 {-arbitrarily-} $ translate fileSizeAndPathList	--CAVEAT: may be shorter than requested.

	prop_bounds fileSizeAndPathList	=  Test.QuickCheck.label "prop_bounds" $ all (FileSizeBounds.inside fileSizeBounds) . map fst . Squeeze.findCombinations fileSizeBounds $ File.order l	where
		l :: [File.FileSizeAndPath]
		l	= take 16 {-arbitrarily-} $ translate fileSizeAndPathList	--CAVEAT: may be shorter than requested.

		fileSizeBounds :: FileSizeBounds.FileSizeBounds
		fileSizeBounds	= (minimumBytes, maximumBytes)	where
			maximumBytes, minimumBytes :: File.FileSize
			maximumBytes	= round $ fromIntegral (File.aggregateSize l) / (4.0 :: Double)	--Arbitrarily.
			minimumBytes	= maximumBytes `div` 2						--Arbitrarily.

	prop_all fileSizeAndPathList =	Test.QuickCheck.label "prop_all" $ (== bytes) . last . map fst $ Squeeze.findBestFit 0.5 (FileSizeBounds.precisely bytes) l	where
		l :: [File.FileSizeAndPath]
		l	= take 16 {-arbitrarily-} . translate $ fileSizeAndPathList	--CAVEAT: may be shorter than requested.

		bytes :: File.FileSize
		bytes	= File.aggregateSize l