github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/libkbfs/mdserver_test.go (about)

     1  // Copyright 2016 Keybase Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD
     3  // license that can be found in the LICENSE file.
     4  
     5  package libkbfs
     6  
     7  import (
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/keybase/client/go/kbfs/kbfscodec"
    12  	"github.com/keybase/client/go/kbfs/kbfscrypto"
    13  	"github.com/keybase/client/go/kbfs/kbfsmd"
    14  	"github.com/keybase/client/go/kbfs/tlf"
    15  	"github.com/keybase/client/go/protocol/keybase1"
    16  	"github.com/stretchr/testify/require"
    17  
    18  	"golang.org/x/net/context"
    19  )
    20  
    21  func makeBRMDForTest(t *testing.T, codec kbfscodec.Codec,
    22  	id tlf.ID, h tlf.Handle, revision kbfsmd.Revision, uid keybase1.UID,
    23  	prevRoot kbfsmd.ID) *kbfsmd.RootMetadataV2 {
    24  	var md kbfsmd.RootMetadataV2
    25  	// MDv3 TODO: uncomment the below when we're ready for MDv3
    26  	// md := &kbfsmd.RootMetadataV3{}
    27  	md.SetTlfID(id)
    28  	md.SetSerializedPrivateMetadata([]byte{0x1})
    29  	md.SetRevision(revision)
    30  	md.SetLastModifyingWriter(uid)
    31  	md.SetLastModifyingUser(uid)
    32  	kbfsmd.FakeInitialRekey(&md, h, kbfscrypto.TLFPublicKey{})
    33  	md.SetPrevRoot(prevRoot)
    34  	return &md
    35  }
    36  
    37  func signRMDSForTest(
    38  	t *testing.T, codec kbfscodec.Codec, signer kbfscrypto.Signer,
    39  	brmd *kbfsmd.RootMetadataV2) *RootMetadataSigned {
    40  	ctx := context.Background()
    41  
    42  	// Encode and sign writer metadata.
    43  	err := brmd.SignWriterMetadataInternally(ctx, codec, signer)
    44  	require.NoError(t, err)
    45  
    46  	rmds, err := SignBareRootMetadata(
    47  		ctx, codec, signer, signer, brmd, time.Time{})
    48  	require.NoError(t, err)
    49  
    50  	return rmds
    51  }
    52  
    53  // This should pass for both local and remote servers.
    54  func TestMDServerBasics(t *testing.T) {
    55  	// setup
    56  	ctx := context.Background()
    57  	config := MakeTestConfigOrBust(t, "test_user")
    58  	defer CheckConfigAndShutdown(ctx, t, config)
    59  	mdServer := config.MDServer()
    60  
    61  	session, err := config.KBPKI().GetCurrentSession(ctx)
    62  	require.NoError(t, err)
    63  	uid := session.UID
    64  
    65  	// (1) get metadata -- allocates an ID
    66  	h, err := tlf.MakeHandle(
    67  		[]keybase1.UserOrTeamID{uid.AsUserOrTeam()}, nil, nil, nil, nil)
    68  	require.NoError(t, err)
    69  
    70  	id, rmds, err := mdServer.GetForHandle(ctx, h, kbfsmd.Merged, nil)
    71  	require.NoError(t, err)
    72  	require.Nil(t, rmds)
    73  
    74  	// (2) push some new metadata blocks
    75  	prevRoot := kbfsmd.ID{}
    76  	middleRoot := kbfsmd.ID{}
    77  	for i := kbfsmd.Revision(1); i <= 10; i++ {
    78  		brmd := makeBRMDForTest(t, config.Codec(), id, h, i, uid, prevRoot)
    79  		rmds := signRMDSForTest(t, config.Codec(), config.Crypto(), brmd)
    80  		// MDv3 TODO: pass actual key bundles
    81  		err = mdServer.Put(ctx, rmds, nil, nil, keybase1.MDPriorityNormal)
    82  		require.NoError(t, err)
    83  		prevRoot, err = kbfsmd.MakeID(config.Codec(), rmds.MD)
    84  		require.NoError(t, err)
    85  		if i == 5 {
    86  			middleRoot = prevRoot
    87  		}
    88  	}
    89  
    90  	// (3) trigger a conflict
    91  	brmd := makeBRMDForTest(t, config.Codec(), id, h, 10, uid, prevRoot)
    92  	rmds = signRMDSForTest(t, config.Codec(), config.Crypto(), brmd)
    93  	// MDv3 TODO: pass actual key bundles
    94  	err = mdServer.Put(ctx, rmds, nil, nil, keybase1.MDPriorityNormal)
    95  	require.IsType(t, kbfsmd.ServerErrorConflictRevision{}, err)
    96  
    97  	// (4) push some new unmerged metadata blocks linking to the
    98  	//     middle merged block.
    99  	prevRoot = middleRoot
   100  	bid, err := config.Crypto().MakeRandomBranchID()
   101  	require.NoError(t, err)
   102  	for i := kbfsmd.Revision(6); i < 41; i++ {
   103  		brmd := makeBRMDForTest(t, config.Codec(), id, h, i, uid, prevRoot)
   104  		brmd.SetUnmerged()
   105  		brmd.SetBranchID(bid)
   106  		rmds := signRMDSForTest(t, config.Codec(), config.Crypto(), brmd)
   107  		// MDv3 TODO: pass actual key bundles
   108  		err = mdServer.Put(ctx, rmds, nil, nil, keybase1.MDPriorityNormal)
   109  		require.NoError(t, err)
   110  		prevRoot, err = kbfsmd.MakeID(config.Codec(), rmds.MD)
   111  		require.NoError(t, err)
   112  	}
   113  
   114  	// (5) check for proper unmerged head
   115  	head, err := mdServer.GetForTLF(ctx, id, bid, kbfsmd.Unmerged, nil)
   116  	require.NoError(t, err)
   117  	require.NotNil(t, head)
   118  	require.Equal(t, kbfsmd.Revision(40), head.MD.RevisionNumber())
   119  
   120  	// (6a) try to get unmerged range
   121  	rmdses, err := mdServer.GetRange(ctx, id, bid, kbfsmd.Unmerged, 1, 100, nil)
   122  	require.NoError(t, err)
   123  	require.Equal(t, 35, len(rmdses))
   124  	for i := kbfsmd.Revision(6); i < 41; i++ {
   125  		require.Equal(t, i, rmdses[i-6].MD.RevisionNumber())
   126  	}
   127  
   128  	// (6b) try to get unmerged range subset.
   129  	rmdses, err = mdServer.GetRange(ctx, id, bid, kbfsmd.Unmerged, 7, 14, nil)
   130  	require.NoError(t, err)
   131  	require.Equal(t, 8, len(rmdses))
   132  	for i := kbfsmd.Revision(7); i <= 14; i++ {
   133  		require.Equal(t, i, rmdses[i-7].MD.RevisionNumber())
   134  	}
   135  
   136  	// (7) prune unmerged
   137  	err = mdServer.PruneBranch(ctx, id, bid)
   138  	require.NoError(t, err)
   139  
   140  	// (8) verify head is pruned
   141  	head, err = mdServer.GetForTLF(ctx, id, kbfsmd.NullBranchID, kbfsmd.Unmerged, nil)
   142  	require.NoError(t, err)
   143  	require.Nil(t, head)
   144  
   145  	// (9) verify revision history is pruned
   146  	rmdses, err = mdServer.GetRange(ctx, id, kbfsmd.NullBranchID, kbfsmd.Unmerged, 1, 100, nil)
   147  	require.NoError(t, err)
   148  	require.Equal(t, 0, len(rmdses))
   149  
   150  	// (10) check for proper merged head
   151  	head, err = mdServer.GetForTLF(ctx, id, kbfsmd.NullBranchID, kbfsmd.Merged, nil)
   152  	require.NoError(t, err)
   153  	require.NotNil(t, head)
   154  	require.Equal(t, kbfsmd.Revision(10), head.MD.RevisionNumber())
   155  
   156  	// (11) try to get merged range
   157  	rmdses, err = mdServer.GetRange(ctx, id, kbfsmd.NullBranchID, kbfsmd.Merged, 1, 100, nil)
   158  	require.NoError(t, err)
   159  	require.Equal(t, 10, len(rmdses))
   160  	for i := kbfsmd.Revision(1); i <= 10; i++ {
   161  		require.Equal(t, i, rmdses[i-1].MD.RevisionNumber())
   162  	}
   163  }
   164  
   165  // This should pass for both local and remote servers. Make sure that
   166  // registering multiple TLFs for updates works. This is a regression
   167  // test for https://keybase.atlassian.net/browse/KBFS-467 .
   168  func TestMDServerRegisterForUpdate(t *testing.T) {
   169  	// setup
   170  	ctx := context.Background()
   171  	config := MakeTestConfigOrBust(t, "test_user")
   172  	defer CheckConfigAndShutdown(ctx, t, config)
   173  	mdServer := config.MDServer()
   174  
   175  	session, err := config.KBPKI().GetCurrentSession(ctx)
   176  	require.NoError(t, err)
   177  	id := session.UID.AsUserOrTeam()
   178  
   179  	// Create first TLF.
   180  	h1, err := tlf.MakeHandle([]keybase1.UserOrTeamID{id}, nil, nil, nil, nil)
   181  	require.NoError(t, err)
   182  
   183  	id1, _, err := mdServer.GetForHandle(ctx, h1, kbfsmd.Merged, nil)
   184  	require.NoError(t, err)
   185  
   186  	// Create second TLF, which should end up being different from
   187  	// the first one.
   188  	h2, err := tlf.MakeHandle([]keybase1.UserOrTeamID{id},
   189  		[]keybase1.UserOrTeamID{keybase1.UserOrTeamID(keybase1.PUBLIC_UID)},
   190  		nil, nil, nil)
   191  	require.NoError(t, err)
   192  
   193  	id2, _, err := mdServer.GetForHandle(ctx, h2, kbfsmd.Merged, nil)
   194  	require.NoError(t, err)
   195  	require.NotEqual(t, id1, id2)
   196  
   197  	_, err = mdServer.RegisterForUpdate(ctx, id1, kbfsmd.RevisionInitial)
   198  	require.NoError(t, err)
   199  
   200  	_, err = mdServer.RegisterForUpdate(ctx, id2, kbfsmd.RevisionInitial)
   201  	require.NoError(t, err)
   202  }