* TestConcurrentRepeatableRead verifies repeatable read. The case intentionally creates a scenario that read and write transactions are interleaved. It performs several writing operations after starting each long-running read transaction to ensure it has a larger txid than previous read transaction.
(t *testing.T)
| 762 | any pages which are still being used by any read transaction. |
| 763 | */ |
| 764 | func TestConcurrentRepeatableRead(t *testing.T) { |
| 765 | if testing.Short() { |
| 766 | t.Skip("skipping test in short mode.") |
| 767 | } |
| 768 | |
| 769 | testCases := []struct { |
| 770 | name string |
| 771 | noFreelistSync bool |
| 772 | freelistType bolt.FreelistType |
| 773 | }{ |
| 774 | // [array] freelist |
| 775 | { |
| 776 | name: "sync array freelist", |
| 777 | noFreelistSync: false, |
| 778 | freelistType: bolt.FreelistArrayType, |
| 779 | }, |
| 780 | { |
| 781 | name: "not sync array freelist", |
| 782 | noFreelistSync: true, |
| 783 | freelistType: bolt.FreelistArrayType, |
| 784 | }, |
| 785 | // [map] freelist |
| 786 | { |
| 787 | name: "sync map freelist", |
| 788 | noFreelistSync: false, |
| 789 | freelistType: bolt.FreelistMapType, |
| 790 | }, |
| 791 | { |
| 792 | name: "not sync map freelist", |
| 793 | noFreelistSync: true, |
| 794 | freelistType: bolt.FreelistMapType, |
| 795 | }, |
| 796 | } |
| 797 | |
| 798 | for _, tc := range testCases { |
| 799 | tc := tc |
| 800 | t.Run(tc.name, func(t *testing.T) { |
| 801 | |
| 802 | t.Log("Preparing db.") |
| 803 | var ( |
| 804 | bucket = []byte("data") |
| 805 | key = []byte("mykey") |
| 806 | |
| 807 | option = &bolt.Options{ |
| 808 | PageSize: 4096, |
| 809 | NoFreelistSync: tc.noFreelistSync, |
| 810 | FreelistType: tc.freelistType, |
| 811 | } |
| 812 | ) |
| 813 | |
| 814 | db := mustCreateDB(t, option) |
| 815 | defer func() { |
| 816 | // The db will be reopened later, so put `db.Close()` in a function |
| 817 | // to avoid premature evaluation of `db`. Note that the execution |
| 818 | // of a deferred function is deferred to the moment the surrounding |
| 819 | // function returns, but the function value and parameters to the |
| 820 | // call are evaluated as usual and saved anew. |
| 821 | db.Close() |
nothing calls this directly
no test coverage detected