github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/chat/unfurl/packager_test.go (about)

     1  package unfurl
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"crypto/sha256"
     7  	"fmt"
     8  	"io"
     9  	"net/http"
    10  	"os"
    11  	"path/filepath"
    12  	"testing"
    13  
    14  	"github.com/keybase/client/go/chat/globals"
    15  
    16  	"github.com/keybase/client/go/chat/attachments"
    17  	"github.com/keybase/client/go/libkb"
    18  	"github.com/keybase/client/go/protocol/chat1"
    19  	"github.com/keybase/client/go/protocol/gregor1"
    20  	"github.com/keybase/clockwork"
    21  	"github.com/stretchr/testify/require"
    22  )
    23  
    24  type ptsigner struct{}
    25  
    26  func (p *ptsigner) Sign(payload []byte) ([]byte, error) {
    27  	s := sha256.Sum256(payload)
    28  	return s[:], nil
    29  }
    30  
    31  type paramsRemote struct {
    32  	chat1.RemoteInterface
    33  }
    34  
    35  func (p paramsRemote) GetS3Params(ctx context.Context, arg chat1.GetS3ParamsArg) (chat1.S3Params, error) {
    36  	return chat1.S3Params{
    37  		Bucket:    "packager-test",
    38  		ObjectKey: libkb.RandStringB64(3),
    39  	}, nil
    40  }
    41  
    42  func TestPackager(t *testing.T) {
    43  	tc := libkb.SetupTest(t, "packager", 1)
    44  	defer tc.Cleanup()
    45  	g := globals.NewContext(tc.G, &globals.ChatContext{})
    46  
    47  	store := attachments.NewStoreTesting(g, nil)
    48  	s3Signer := &ptsigner{}
    49  	ri := func() chat1.RemoteInterface { return paramsRemote{} }
    50  	packager := NewPackager(g, store, s3Signer, ri)
    51  	clock := clockwork.NewFakeClock()
    52  	packager.cache.setClock(clock)
    53  	srvFile := func(w io.Writer, name string) {
    54  		file, err := os.Open(name)
    55  		require.NoError(t, err)
    56  		defer file.Close()
    57  		_, err = io.Copy(w, file)
    58  		require.NoError(t, err)
    59  	}
    60  	srv := newDummyHTTPSrv(t, func(w http.ResponseWriter, r *http.Request) {
    61  		w.WriteHeader(200)
    62  		if r.URL.Query().Get("typ") == "favicon" {
    63  			srvFile(w, filepath.Join("testcases", "nytimes.ico"))
    64  			return
    65  		}
    66  		srvFile(w, filepath.Join("testcases", "nytogimage.jpg"))
    67  	})
    68  	addr := srv.Start()
    69  	defer srv.Stop()
    70  
    71  	uid := gregor1.UID([]byte{0})
    72  	convID := chat1.ConversationID([]byte{0})
    73  	imageURL := fmt.Sprintf("http://%s/?typ=image", addr)
    74  	faviconURL := fmt.Sprintf("http://%s/?typ=favicon", addr)
    75  	raw := chat1.NewUnfurlRawWithGeneric(chat1.UnfurlGenericRaw{
    76  		Url:        "https://example.com",
    77  		ImageUrl:   &imageURL,
    78  		FaviconUrl: &faviconURL,
    79  	})
    80  	res, err := packager.Package(context.TODO(), uid, convID, raw)
    81  	require.NoError(t, err)
    82  	typ, err := res.UnfurlType()
    83  	require.NoError(t, err)
    84  	require.Equal(t, chat1.UnfurlType_GENERIC, typ)
    85  	image := res.Generic().Image
    86  	require.NotNil(t, image)
    87  	favicon := res.Generic().Favicon
    88  	require.NotNil(t, favicon)
    89  	require.NotZero(t, image.Metadata.Image().Height)
    90  	require.NotZero(t, image.Metadata.Image().Width)
    91  	require.NotZero(t, favicon.Metadata.Image().Height)
    92  	require.NotZero(t, favicon.Metadata.Image().Width)
    93  
    94  	// test caching
    95  	cacheKey := packager.cacheKey(uid, convID, raw)
    96  	cachedRes, valid := packager.cache.get(cacheKey)
    97  	require.True(t, valid)
    98  	require.Equal(t, res, cachedRes.data.(chat1.Unfurl))
    99  
   100  	clock.Advance(defaultCacheLifetime * 2)
   101  	cachedRes, valid = packager.cache.get(cacheKey)
   102  	require.False(t, valid)
   103  
   104  	compareSol := func(name string, resDat []byte) {
   105  		dat, err := os.ReadFile(filepath.Join("testcases", name))
   106  		require.NoError(t, err)
   107  		require.True(t, bytes.Equal(dat, resDat))
   108  	}
   109  	var buf bytes.Buffer
   110  	s3params, err := ri().GetS3Params(context.TODO(), chat1.GetS3ParamsArg{
   111  		ConversationID: convID,
   112  		TempCreds:      true,
   113  	})
   114  	require.NoError(t, err)
   115  	require.NoError(t, store.DownloadAsset(context.TODO(), s3params, *image, &buf, s3Signer, nil))
   116  	compareSol("nytogimage_sol.jpg", buf.Bytes())
   117  	buf.Reset()
   118  	require.NoError(t, store.DownloadAsset(context.TODO(), s3params, *favicon, &buf, s3Signer, nil))
   119  	compareSol("nytimes_sol.ico", buf.Bytes())
   120  }