- added more unit tests for ArrayDatabase
@@ -270,6 +270,40 @@ | ||
270 | 270 | } |
271 | 271 | printf( "ok.\n" ); |
272 | 272 | |
273 | + printf( "testing ArrayDatabase aborting of three chain-linked transactions..." ); | |
274 | + { | |
275 | + filePtr memFile = fileSys->CreateMemoryFile(); | |
276 | + | |
277 | + ArrayDatabase::db_construction_params cparams; | |
278 | + cparams.item_block_size = 600; | |
279 | + cparams.journal_size = 244; | |
280 | + cparams.user_ident = 0x93658476; | |
281 | + cparams.align_blocks = true; | |
282 | + | |
283 | + ArrayDatabase::CreateDatabase( memFile, cparams ); | |
284 | + | |
285 | + ArrayDatabase db( execMan, std::move( memFile ) ); | |
286 | + | |
287 | + std::uint32_t tid1 = db.BeginTransaction( 0 ); | |
288 | + std::uint32_t tid2 = db.BeginTransaction( 1 ); | |
289 | + std::uint32_t tid3 = db.BeginTransaction( 2 ); | |
290 | + | |
291 | + assert( db.IsTransactionRunning( tid1 ) == true ); | |
292 | + assert( db.IsTransactionRunning( tid2 ) == true ); | |
293 | + assert( db.IsTransactionRunning( tid3 ) == true ); | |
294 | + | |
295 | + db.LinkTransactions( tid1, tid2 ); | |
296 | + db.LinkTransactions( tid2, tid3 ); | |
297 | + | |
298 | + // This must abort tid1, tid2 and tid3. | |
299 | + db.AbortTransaction( tid1 ); | |
300 | + | |
301 | + assert( db.IsTransactionRunning( tid1 ) == false ); | |
302 | + assert( db.IsTransactionRunning( tid2 ) == false ); | |
303 | + assert( db.IsTransactionRunning( tid3 ) == false ); | |
304 | + } | |
305 | + printf( "ok.\n" ); | |
306 | + | |
273 | 307 | printf( "testing ArrayDatabase parsing journal with aborted transaction..." ); |
274 | 308 | { |
275 | 309 | filePtr memFile = fileSys->CreateMemoryFile(); |
@@ -492,5 +526,300 @@ | ||
492 | 526 | } |
493 | 527 | printf( "ok.\n" ); |
494 | 528 | |
529 | + printf( "testing ArrayDatabase swapping chunks..." ); | |
530 | + { | |
531 | + filePtr memFile = fileSys->CreateMemoryFile(); | |
532 | + | |
533 | + ArrayDatabase::db_construction_params cparams; | |
534 | + cparams.item_block_size = 64; | |
535 | + cparams.journal_size = 1024; | |
536 | + cparams.user_ident = 42; | |
537 | + cparams.align_blocks = true; | |
538 | + | |
539 | + ArrayDatabase::CreateDatabase( memFile, cparams ); | |
540 | + | |
541 | + // We write a block with data and then swap it out. | |
542 | + ArrayDatabase db( execMan, std::move( memFile ) ); | |
543 | + | |
544 | + static const unsigned char _write_data[] = | |
545 | + { | |
546 | + 0, 1, 2, 3, 4, 5, 6, 7, | |
547 | + 8, 9, 10, 11, 12, 13, 14, 15, | |
548 | + 16, 17, 18, 19, 20, 21, 22, 23, | |
549 | + 24, 25, 26, 27, 28, 29, 30, 31, | |
550 | + 32, 33, 34, 35, 36, 37, 38, 39, | |
551 | + 40, 41, 42, 43, 44, 45, 46, 47, | |
552 | + 48, 49, 50, 51, 52, 53, 54, 55, | |
553 | + 56, 57, 58, 59, 60, 61, 62, 63 | |
554 | + }; | |
555 | + | |
556 | + std::uint32_t tid = db.BeginTransaction( 0 ); | |
557 | + | |
558 | + db.WriteToChunk( tid, 0, _write_data, sizeof(_write_data) ); | |
559 | + | |
560 | + std::uint32_t tid2 = db.BeginTransaction( 1 ); | |
561 | + | |
562 | + db.SwapTransactionData( tid, tid2 ); | |
563 | + | |
564 | + db.EndTransaction( tid2 ); | |
565 | + db.EndTransaction( tid ); | |
566 | + | |
567 | + // We should now have an empty chunk 0 and a filled chunk 1. | |
568 | + for ( std::uint32_t n = 0; n < 64; n++ ) | |
569 | + { | |
570 | + assert( db.ReadStruct_EX <unsigned char> ( 0, n ) == 0 ); | |
571 | + assert( db.ReadStruct_EX <unsigned char> ( 1, n ) == n ); | |
572 | + } | |
573 | + | |
574 | + // OK. | |
575 | + } | |
576 | + printf( "ok.\n" ); | |
577 | + | |
578 | + printf( "testing ArrayDatabase aborting chunk swap..." ); | |
579 | + { | |
580 | + filePtr memFile = fileSys->CreateMemoryFile(); | |
581 | + | |
582 | + ArrayDatabase::db_construction_params cparams; | |
583 | + cparams.item_block_size = 32; | |
584 | + cparams.journal_size = 400; | |
585 | + cparams.user_ident = 0x75529374; | |
586 | + cparams.align_blocks = true; | |
587 | + | |
588 | + ArrayDatabase::CreateDatabase( memFile, cparams ); | |
589 | + | |
590 | + ArrayDatabase db( execMan, std::move( memFile ) ); | |
591 | + | |
592 | + std::uint32_t tid1 = db.BeginTransaction( 0 ); | |
593 | + | |
594 | + db.WriteStruct <std::uint32_t> ( tid1, 0, 42 ); | |
595 | + | |
596 | + std::uint32_t tid2 = db.BeginTransaction( 1 ); | |
597 | + | |
598 | + db.SwapTransactionData( tid1, tid2 ); | |
599 | + | |
600 | + db.AbortTransaction( tid2 ); | |
601 | + | |
602 | + assert( db.ReadStruct_EX <std::uint32_t> ( 0, 0 ) == 0 ); | |
603 | + assert( db.ReadStruct_EX <std::uint32_t> ( 1, 0 ) == 0 ); | |
604 | + } | |
605 | + printf( "ok.\n" ); | |
606 | + | |
607 | + printf( "testing ArrayDatabase parsing journal with chunk swap..." ); | |
608 | + { | |
609 | + filePtr memFile = fileSys->CreateMemoryFile(); | |
610 | + | |
611 | + ArrayDatabase::db_construction_params cparams; | |
612 | + cparams.item_block_size = sizeof(std::uint32_t); | |
613 | + cparams.journal_size = 250; | |
614 | + cparams.user_ident = 0x48307574; | |
615 | + | |
616 | + ArrayDatabase::CreateDatabase( memFile, cparams ); | |
617 | + | |
618 | + // We first write a database in an invalid state. | |
619 | + { | |
620 | + ArrayDatabase write_db( execMan, filePtr( memFile, false ) ); | |
621 | + | |
622 | + std::uint32_t tid1 = write_db.BeginTransaction( 0 ); | |
623 | + | |
624 | + write_db.WriteStruct <std::uint32_t> ( tid1, 0, 33 ); | |
625 | + | |
626 | + std::uint32_t tid2 = write_db.BeginTransaction( 1 ); | |
627 | + | |
628 | + write_db.SwapTransactionData( tid1, tid2 ); | |
629 | + | |
630 | + write_db.EndTransaction( tid1 ); | |
631 | + | |
632 | + // Boom. Since tid2 is still open/uncommitted we must revert both tid1 and tid2. | |
633 | + } | |
634 | + | |
635 | + // Now read it. | |
636 | + { | |
637 | + ArrayDatabase read_db( execMan, std::move( memFile ) ); | |
638 | + | |
639 | + assert( read_db.ReadStruct_EX <std::uint32_t> ( 0, 0 ) == 0 ); | |
640 | + assert( read_db.ReadStruct_EX <std::uint32_t> ( 1, 0 ) == 0 ); | |
641 | + } | |
642 | + } | |
643 | + printf( "ok.\n" ); | |
644 | + | |
645 | + printf( "testing ArrayDatabase aborting transaction with swap causes transaction link..." ); | |
646 | + { | |
647 | + filePtr memFile = fileSys->CreateMemoryFile(); | |
648 | + | |
649 | + ArrayDatabase::db_construction_params cparams; | |
650 | + cparams.item_block_size = 80; | |
651 | + cparams.journal_size = 320; | |
652 | + cparams.user_ident = 0x54298471; | |
653 | + cparams.align_blocks = false; | |
654 | + | |
655 | + ArrayDatabase::CreateDatabase( memFile, cparams ); | |
656 | + | |
657 | + ArrayDatabase db( execMan, std::move( memFile ) ); | |
658 | + | |
659 | + std::uint32_t tid1 = db.BeginTransaction( 0 ); | |
660 | + | |
661 | + assert( db.IsTransactionRunning( tid1 ) == true ); | |
662 | + | |
663 | + db.WriteStruct <std::uint16_t> ( tid1, 0, 948 ); | |
664 | + | |
665 | + std::uint32_t tid2 = db.BeginTransaction( 1 ); | |
666 | + | |
667 | + assert( db.IsTransactionRunning( tid2 ) == true ); | |
668 | + | |
669 | + db.SwapTransactionData( tid1, tid2 ); | |
670 | + | |
671 | + db.AbortTransaction( tid2 ); | |
672 | + | |
673 | + assert( db.IsTransactionRunning( tid1 ) == false ); | |
674 | + assert( db.IsTransactionRunning( tid2 ) == false ); | |
675 | + } | |
676 | + printf( "ok.\n" ); | |
677 | + | |
678 | + printf( "testing ArrayDatabase zeroing chunks..." ); | |
679 | + { | |
680 | + filePtr memFile = fileSys->CreateMemoryFile(); | |
681 | + | |
682 | + ArrayDatabase::db_construction_params cparams; | |
683 | + cparams.item_block_size = 60; | |
684 | + cparams.journal_size = 812; | |
685 | + cparams.user_ident = 0; | |
686 | + | |
687 | + ArrayDatabase::CreateDatabase( memFile, cparams ); | |
688 | + | |
689 | + ArrayDatabase db( execMan, std::move( memFile ) ); | |
690 | + | |
691 | + std::uint32_t tid = db.BeginTransaction( 0 ); | |
692 | + | |
693 | + db.WriteStruct <std::uint32_t> ( tid, 0, 8888 ); | |
694 | + db.ZeroTransactionData( tid ); | |
695 | + | |
696 | + db.EndTransaction( tid ); | |
697 | + | |
698 | + assert( db.ReadStruct_EX <std::uint32_t> ( 0, 0 ) == 0 ); | |
699 | + } | |
700 | + printf( "ok.\n" ); | |
701 | + | |
702 | + printf( "testing ArrayDatabase aborting chunk zeroing..." ); | |
703 | + { | |
704 | + filePtr memFile = fileSys->CreateMemoryFile(); | |
705 | + | |
706 | + ArrayDatabase::db_construction_params cparams; | |
707 | + cparams.item_block_size = sizeof(std::uint32_t); | |
708 | + cparams.journal_size = 200; | |
709 | + cparams.user_ident = 0x63463920; | |
710 | + | |
711 | + ArrayDatabase::CreateDatabase( memFile, cparams ); | |
712 | + | |
713 | + ArrayDatabase db( execMan, std::move( memFile ) ); | |
714 | + | |
715 | + std::uint32_t tid = db.BeginTransaction( 0 ); | |
716 | + | |
717 | + db.WriteStruct <std::uint32_t> ( tid, 0, 66 ); | |
718 | + | |
719 | + db.EndTransaction( tid ); | |
720 | + | |
721 | + assert( db.ReadStruct_EX <std::uint32_t> ( 0, 0 ) == 66 ); | |
722 | + | |
723 | + tid = db.BeginTransaction( 0 ); | |
724 | + | |
725 | + db.ZeroTransactionData( tid ); | |
726 | + db.AbortTransaction( tid ); | |
727 | + | |
728 | + assert( db.ReadStruct_EX <std::uint32_t> ( 0, 0 ) == 66 ); | |
729 | + | |
730 | + // OK. | |
731 | + } | |
732 | + printf( "ok.\n" ); | |
733 | + | |
734 | + printf( "testing ArrayDatabase parsing journal with chunk zeroing..." ); | |
735 | + { | |
736 | + filePtr memFile = fileSys->CreateMemoryFile(); | |
737 | + | |
738 | + ArrayDatabase::db_construction_params cparams; | |
739 | + cparams.item_block_size = 76; | |
740 | + cparams.journal_size = 555; | |
741 | + cparams.user_ident = 0x12347650; | |
742 | + | |
743 | + ArrayDatabase::CreateDatabase( memFile, cparams ); | |
744 | + | |
745 | + // We first write stuff. | |
746 | + { | |
747 | + ArrayDatabase db( execMan, filePtr( memFile, false ) ); | |
748 | + | |
749 | + std::uint32_t wtid = db.BeginTransaction( 0 ); | |
750 | + | |
751 | + db.WriteStruct <std::uint32_t> ( wtid, 0, 99 ); | |
752 | + | |
753 | + db.EndTransaction( wtid ); | |
754 | + | |
755 | + std::uint32_t tid = db.BeginTransaction( 0 ); | |
756 | + | |
757 | + db.WriteStruct <std::uint32_t> ( tid, 0, 55 ); | |
758 | + db.ZeroTransactionData( tid ); | |
759 | + | |
760 | + // Boom. tid is not closed so it must be reverted. | |
761 | + } | |
762 | + | |
763 | + // Now read the journal. | |
764 | + { | |
765 | + ArrayDatabase db( execMan, std::move( memFile ) ); | |
766 | + | |
767 | + assert( db.ReadStruct_EX <std::uint32_t> ( 0, 0 ) == 99 ); | |
768 | + } | |
769 | + } | |
770 | + printf( "ok.\n" ); | |
771 | + | |
772 | + printf( "testing ArrayDatabase building data array and removing last entry only..." ); | |
773 | + { | |
774 | + filePtr memFile = fileSys->CreateMemoryFile(); | |
775 | + | |
776 | + ArrayDatabase::db_construction_params cparams; | |
777 | + cparams.item_block_size = 32; | |
778 | + cparams.journal_size = 300; | |
779 | + cparams.user_ident = 1; | |
780 | + | |
781 | + ArrayDatabase::CreateDatabase( memFile, cparams ); | |
782 | + | |
783 | + ArrayDatabase db( execMan, std::move( memFile ) ); | |
784 | + | |
785 | + // We first write three entries into the database. | |
786 | + { | |
787 | + std::uint32_t tid = db.BeginTransaction( 0 ); | |
788 | + | |
789 | + db.WriteStruct <std::uint32_t> ( tid, 0, 11 ); | |
790 | + | |
791 | + db.EndTransaction( tid ); | |
792 | + | |
793 | + tid = db.BeginTransaction( 1 ); | |
794 | + | |
795 | + db.WriteStruct <std::uint32_t> ( tid, 0, 22 ); | |
796 | + | |
797 | + db.EndTransaction( tid ); | |
798 | + | |
799 | + tid = db.BeginTransaction( 2 ); | |
800 | + | |
801 | + db.WriteStruct <std::uint32_t> ( tid, 0, 33 ); | |
802 | + | |
803 | + db.EndTransaction( tid ); | |
804 | + } | |
805 | + | |
806 | + // Now we want to remove the first entry, marking the total count to two. | |
807 | + { | |
808 | + std::uint32_t tid1 = db.BeginTransaction( 0 ); | |
809 | + std::uint32_t tid2 = db.BeginTransaction( 2 ); | |
810 | + | |
811 | + db.SwapTransactionData( tid1, tid2 ); | |
812 | + db.ZeroTransactionData( tid2 ); | |
813 | + | |
814 | + db.EndTransaction( tid1 ); | |
815 | + db.EndTransaction( tid2 ); | |
816 | + } | |
817 | + | |
818 | + assert( db.ReadStruct_EX <std::uint32_t> ( 0, 0 ) == 33 ); | |
819 | + assert( db.ReadStruct_EX <std::uint32_t> ( 1, 0 ) == 22 ); | |
820 | + assert( db.ReadStruct_EX <std::uint32_t> ( 2, 0 ) == 0 ); | |
821 | + } | |
822 | + printf( "ok.\n" ); | |
823 | + | |
495 | 824 | // TODO: more tests. |
496 | 825 | } |
\ No newline at end of file |