#include #include "../continuous_function.h" #include "../../graph/continuous_function_store.h" #include "../../sequence/sequence.h" #include "../../sequence/sequence_store.h" namespace Shared { template void interactWithBaseRecordMember(F * fct) { /* Accessing Function record member m_color, which has a 2-byte alignment * Only effective in DEBUG=1, as there are no compiler optimizations */ KDColor color = fct->color(); (void) color; // Silence compilation warning about unused variable. } void interactWithRecordMember(Sequence::SequenceStore * store, Ion::Storage::Record rec) { Sequence::Sequence * seq = store->modelForRecord(rec); /* Setting Sequence type will write record member m_initialConditionSizes, * which has a 2-byte alignment */ seq->setType(Sequence::Sequence::Type::SingleRecurrence); interactWithBaseRecordMember(seq); } void interactWithRecordMember(Graph::ContinuousFunctionStore * store, Ion::Storage::Record rec) { ContinuousFunction * fct = store->modelForRecord(rec).pointer(); // Setting m_min from record member m_domain, which has a 2-byte alignment fct->setTMin(3.0f); interactWithBaseRecordMember(fct); } template Ion::Storage::Record createRecord(T * store) { Ion::Storage::Record::ErrorStatus err = store->addEmptyModel(); assert(err == Ion::Storage::Record::ErrorStatus::None); (void) err; // Silence compilation warning about unused variable. return store->recordAtIndex(store->numberOfModels()-1); } template void testAlignmentHandlingFor() { T store; Ion::Storage * sharedStorage = Ion::Storage::sharedStorage(); sharedStorage->destroyAllRecords(); Ion::Storage::Record rec1 = createRecord(&store); // Evaluate the sequence shift compared to a 2-byte alignment uintptr_t shift = reinterpret_cast(rec1.value().buffer) % 2; /* Interact with an alignment sensitive member. A mishandled record alignment * should throw an abort(alignment fault) exception */ interactWithRecordMember(&store, rec1); sharedStorage->destroyAllRecords(); // Repeat the same process with a 1 byte record padding Ion::Storage::Record::ErrorStatus err = sharedStorage->createRecordWithExtension("1", "1", "1", 1); assert(err == Ion::Storage::Record::ErrorStatus::None); (void) err; // Silence compilation warning about unused variable. Ion::Storage::Record rec2 = createRecord(&store); shift += reinterpret_cast(rec2.value().buffer) % 2; interactWithRecordMember(&store, rec2); /* If fct1 and fct2 had different shifts, the test is able to detect a * mishandled record alignment */ quiz_assert(shift == 1); sharedStorage->destroyAllRecords(); } QUIZ_CASE(alignment_handling) { /* This test main function is to crash if storage alignment is not handled * properly. It also ensures that the right test - load and store of * differently-aligned objects - is performed (if storage/record * implementations change for instance). */ testAlignmentHandlingFor(); testAlignmentHandlingFor(); } }