1
0
forked from Alepha/Alepha
Files

206 lines
4.7 KiB
C++

#include "../Attestation.h"
#include <Alepha/Testing/test.h>
#include <cstddef>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <mutex>
#include <memory>
#include <random>
#include <iostream>
namespace
{
using namespace Alepha::Testing::literals::test_literals;
struct Tester;
struct foobar_tag { using averant= Tester; };
using FoobarFact= Alepha::Proof::Attestation< foobar_tag >;
struct Tester
{
static void
test()
{
FoobarFact token= Alepha::Proof::impute< FoobarFact >();
FoobarFact token2= attest( FoobarFact::permission );
}
};
struct Sorter;
struct sorted_tag { using averant= Sorter; };
using Sorted= Alepha::Proof::Attestation< sorted_tag >;
struct Sorter
{
static Sorted::Witness< const std::vector< int > & >
sort( std::vector< int > &v )
{
std::sort( begin( v ), end( v ) );
return attest( Sorted::permission ).aver< const std::vector< int > & >( v );
}
};
struct Locker;
struct with_lock_tag { using averant= Locker; };
using Locked= Alepha::Proof::Attestation< with_lock_tag >;
struct Locker
{
struct WithLock : Locked
{
public:
WithLock( const std::lock_guard< std::mutex > & )
: Locked( attest( Locked::permission ) ) {}
WithLock( std::lock_guard< std::mutex > && )= delete;
};
};
using WithLock= Locker::WithLock;
struct NullChecker;
struct non_null_tag { using averant= NullChecker; };
using NonNull= Alepha::Proof::Attestation< non_null_tag >;
struct NullChecker
{
template< typename Ptype >
static NonNull::Witness< Ptype >
isNotNull( Ptype p )
{
if( !p ) throw std::logic_error( "" );
return attest( NonNull::permission ).averCopy( std::move( p ) );
}
};
template< typename P >
auto
makeUnique()
{
return NullChecker::isNotNull( std::make_unique< P >() );
}
// Page aligned example
struct page_aligned_tag { using averant= struct AlignmentChecker; };
using PageAligned= Alepha::Proof::Attestation< page_aligned_tag >;
struct AlignmentChecker
{
template< typename Ptype >
static auto
check( Ptype *pointer )
{
if( pointer % 4096 ) throw std::runtime_error( "" );
return attest( PageAligned::permission ).template averCopy< Ptype *const >( pointer );
}
static PageAligned::Witness< void *const >
allocate( const std::size_t amt )
{
void *rv;
const int ec= posix_memalign( &rv, 4096, amt );
if( ec ) std::get_new_handler()();
return attest( PageAligned::permission ).averCopy< void *const >( rv );
}
};
template< typename T >
PageAligned::Witness< std::unique_ptr< T > >
make_unique_on_page()
{
// Dtor ordering and transition of responsibility struct
struct Safety
{
std::unique_ptr< void > memory;
explicit Safety( void *p ) : memory( p ) { new (p) T(); }
~Safety()= delete;
std::unique_ptr< T >
finish () & noexcept
{
return std::unique_ptr< T >( reinterpret_cast< T * >( memory.release() ) );
}
};
auto safe_adapt= []( auto p )
{
std::array< std::uint8_t, sizeof( Safety ) > locals;
auto safe= (new (locals.data()) Safety( witness( p ) ))->finish();
return std::make_pair( std::move( safe ), fact( p ) );
};
auto [ ptr, alignment ]= safe_adapt( AlignmentChecker::allocate( sizeof( T ) ) );
return alignment.template averCopy< std::unique_ptr< T > >( std::move( ptr ) );
}
}
auto simpleTest= "Simple attestation test"_test <=[]
{
Tester::test();
//attest( FoobarFact::permission );
FoobarFact token= Alepha::Proof::impute< FoobarFact >();
std::vector< int > v{ 5, 11, 3, 2, 1 };
Sorted::Witness< const std::vector< int > & > sortedVector= Sorter::sort( v );
assert( std::is_sorted( begin( testify( sortedVector ) ), end( testify( sortedVector ) ) ) );
// Since this is probability driven, and there's only 5 members, there's some chance that it
// might actually be sorted! Bogosort is a thing, after all.
//
// So instead, I just shuffle until it _isn't_ sorted. Should only repeat once, almost
// all the time.
while( std::is_sorted( begin( testify( sortedVector ) ), end( testify( sortedVector ) ) ) )
{
std::shuffle( begin( v ), end( v ), std::random_device() );
}
if( std::is_sorted( begin( testify( sortedVector ) ), end( testify( sortedVector ) ) ) )
{
std::cerr << "They were sorted! They shouldn't be!!" << std::endl;
assert( !std::is_sorted( begin( testify( sortedVector ) ), end( testify( sortedVector ) ) ) );
}
std::mutex mtx;
auto checker= []( WithLock ) {};
std::lock_guard< std::mutex > lk( mtx );
checker( lk );
auto myInt= makeUnique< int >();
};
namespace
{
namespace mongo
{
struct OperationContext { int member; };
void
operation( NonNull::Witness< OperationContext * > opCtx )
{
// ...
(void) testify( opCtx )->member;
}
}
}