Best Syzkaller code snippet using asset.makeStorage
emojisource.go
Source:emojisource.go
...98 ri: ri,99 encryptedDB: encrypteddb.New(g.ExternalG(), dbFn, keyFn),100 }101}102func (s *DevConvEmojiSource) makeStorage(topicType chat1.TopicType) types.ConvConversationBackedStorage {103 return NewConvDevConversationBackedStorage(s.G(), topicType, false, s.ri)104}105func (s *DevConvEmojiSource) topicName(suffix *string) string {106 ret := "emojis"107 if suffix != nil {108 ret += *suffix109 }110 return ret111}112func (s *DevConvEmojiSource) dbKey(uid gregor1.UID) libkb.DbKey {113 return libkb.DbKey{114 Typ: libkb.DBChatUserEmojis,115 Key: uid.String(),116 }117}118func (s *DevConvEmojiSource) getAliasLookup(ctx context.Context, uid gregor1.UID) (res map[string]chat1.Emoji, err error) {119 s.aliasLookupLock.Lock()120 defer s.aliasLookupLock.Unlock()121 if s.aliasLookup != nil {122 res = make(map[string]chat1.Emoji, len(s.aliasLookup))123 for alias, emoji := range s.aliasLookup {124 res[alias] = emoji125 }126 return res, nil127 }128 res = make(map[string]chat1.Emoji)129 s.Debug(ctx, "getAliasLookup: missed alias lookup, reading from disk")130 found, err := s.encryptedDB.Get(ctx, s.dbKey(uid), &res)131 if err != nil {132 return res, err133 }134 if !found {135 return make(map[string]chat1.Emoji), nil136 }137 return res, nil138}139func (s *DevConvEmojiSource) putAliasLookup(ctx context.Context, uid gregor1.UID,140 aliasLookup map[string]chat1.Emoji, opts chat1.EmojiFetchOpts) error {141 s.aliasLookupLock.Lock()142 defer s.aliasLookupLock.Unlock()143 // set this if it is blank, or a full fetch144 if !opts.OnlyInTeam || s.aliasLookup == nil {145 s.aliasLookup = aliasLookup146 }147 // only commit to disk if this is a full lookup148 if !opts.OnlyInTeam {149 return s.encryptedDB.Put(ctx, s.dbKey(uid), s.aliasLookup)150 }151 return nil152}153func (s *DevConvEmojiSource) addAdvanced(ctx context.Context, uid gregor1.UID,154 storageConv *chat1.ConversationLocal, convID chat1.ConversationID,155 alias, filename string, allowOverwrite bool, storage types.ConvConversationBackedStorage) (res chat1.EmojiRemoteSource, err error) {156 var stored chat1.EmojiStorage157 alias = strings.ReplaceAll(alias, ":", "") // drop any colons from alias158 if storageConv != nil {159 _, err = storage.GetFromKnownConv(ctx, uid, *storageConv, &stored)160 } else {161 topicName := s.topicName(nil)162 _, storageConv, err = storage.Get(ctx, uid, convID, topicName, &stored, true)163 }164 if err != nil {165 return res, err166 }167 if stored.Mapping == nil {168 stored.Mapping = make(map[string]chat1.EmojiRemoteSource)169 }170 if _, ok := stored.Mapping[alias]; ok && !allowOverwrite {171 return res, NewEmojiValidationError(errors.New("alias already exists"),172 "alias already exists, must specify --allow-overwrite to edit", "alias already exists")173 }174 sender := NewBlockingSender(s.G(), NewBoxer(s.G()), s.ri)175 _, msgID, err := attachments.NewSender(s.G()).PostFileAttachment(ctx, sender, uid,176 storageConv.GetConvID(), storageConv.Info.TlfName, keybase1.TLFVisibility_PRIVATE, nil, filename,177 "", nil, 0, nil, nil)178 if err != nil {179 return res, err180 }181 if msgID == nil {182 return res, errors.New("no messageID from attachment")183 }184 res = chat1.NewEmojiRemoteSourceWithMessage(chat1.EmojiMessage{185 ConvID: storageConv.GetConvID(),186 MsgID: *msgID,187 })188 stored.Mapping[alias] = res189 return res, storage.PutToKnownConv(ctx, uid, *storageConv, stored)190}191func (s *DevConvEmojiSource) IsStockEmoji(alias string) bool {192 parts := strings.Split(alias, ":")193 if len(parts) > 3 { // if we have a skin tone here, drop it194 alias = fmt.Sprintf(":%s:", parts[1])195 } else if len(parts) == 1 {196 alias = fmt.Sprintf(":%s:", parts[0])197 }198 alias2 := strings.ReplaceAll(alias, "-", "_")199 return storage.EmojiExists(alias) || storage.EmojiExists(alias2)200}201func (s *DevConvEmojiSource) normalizeShortName(shortName string) string {202 return strings.ReplaceAll(shortName, ":", "") // drop any colons from alias203}204func (s *DevConvEmojiSource) validateShortName(shortName string) error {205 if s.IsStockEmoji(shortName) {206 return NewEmojiValidationErrorJustError(errors.New("alias already exists"))207 }208 if len(shortName) > maxShortNameLength {209 err := errors.New("alias is too long")210 return NewEmojiValidationError(err, fmt.Sprintf("alias is too long, must be less than %d",211 maxShortNameLength), err.Error())212 }213 if len(shortName) < minShortNameLength {214 err := errors.New("alias is too short")215 return NewEmojiValidationError(err,216 fmt.Sprintf("alias is too short, must be greater than %d", minShortNameLength),217 err.Error())218 }219 if strings.Contains(shortName, "#") {220 return NewEmojiValidationErrorJustError(errors.New("invalid character in alias"))221 }222 return nil223}224func (s *DevConvEmojiSource) validateCustomEmoji(ctx context.Context, shortName, filename string) (string, error) {225 err := s.validateShortName(shortName)226 if err != nil {227 return "", err228 }229 shortName = s.normalizeShortName(shortName)230 err = s.validateFile(ctx, filename)231 if err != nil {232 return "", err233 }234 return shortName, nil235}236// validateFile validates the following:237// file size238// format239func (s *DevConvEmojiSource) validateFile(ctx context.Context, filename string) error {240 finfo, err := attachments.StatOSOrKbfsFile(ctx, s.G().GlobalContext, filename)241 if err != nil {242 return NewEmojiValidationErrorSimple(err, "unable to open file")243 }244 if finfo.IsDir() {245 return NewEmojiValidationErrorJustError(errors.New("unable to use a directory"))246 } else if finfo.Size() > maxEmojiSize {247 err := errors.New("file too large")248 return NewEmojiValidationError(err,249 fmt.Sprintf("emoji filesize too large, must be less than %s", humanize.Bytes(maxEmojiSize)),250 err.Error())251 } else if finfo.Size() < minEmojiSize {252 err := errors.New("file too small")253 return NewEmojiValidationError(err,254 fmt.Sprintf("emoji filesize too small, must be greater than %s", humanize.Bytes(minEmojiSize)),255 err.Error())256 }257 src, err := attachments.NewReadCloseResetter(ctx, s.G().GlobalContext, filename)258 if err != nil {259 return NewEmojiValidationErrorSimple(err, "failed to process file")260 }261 defer func() { src.Close() }()262 if _, _, err = images.Decode(src, nil); err != nil {263 s.Debug(ctx, "validateFile: failed to decode image: %s", err)264 if err := src.Reset(); err != nil {265 return NewEmojiValidationErrorSimple(err, "failed to process file")266 }267 g, err := gif.DecodeAll(src)268 if err != nil {269 s.Debug(ctx, "validateFile: failed to decode gif: %s", err)270 return NewEmojiValidationErrorSimple(err, "invalid image file")271 }272 if len(g.Image) == 0 {273 return NewEmojiValidationErrorJustError(errors.New("no image frames in GIF"))274 }275 }276 return nil277}278func (s *DevConvEmojiSource) fromURL(ctx context.Context, url string) (string, error) {279 resp, err := http.Get(url)280 if err != nil {281 return "", err282 }283 defer resp.Body.Close()284 file, _, err := s.G().AttachmentUploader.GetUploadTempSink(ctx, "tmp-emoji")285 if err != nil {286 return "", err287 }288 _, err = io.Copy(file, resp.Body)289 return file.Name(), err290}291func (s *DevConvEmojiSource) Add(ctx context.Context, uid gregor1.UID, convID chat1.ConversationID,292 alias, filename string, allowOverwrite bool) (res chat1.EmojiRemoteSource, err error) {293 defer s.Trace(ctx, &err, "Add")()294 if strings.HasPrefix(filename, "http://") || strings.HasPrefix(filename, "https://") {295 filename, err = s.fromURL(ctx, filename)296 if err != nil {297 return res, err298 }299 defer func() { _ = os.Remove(filename) }()300 }301 if alias, err = s.validateCustomEmoji(ctx, alias, filename); err != nil {302 return res, err303 }304 storage := s.makeStorage(chat1.TopicType_EMOJI)305 return s.addAdvanced(ctx, uid, nil, convID, alias, filename, allowOverwrite, storage)306}307func (s *DevConvEmojiSource) AddAlias(ctx context.Context, uid gregor1.UID, convID chat1.ConversationID,308 newAlias, existingAlias string) (res chat1.EmojiRemoteSource, err error) {309 defer s.Trace(ctx, &err, "AddAlias")()310 if err = s.validateShortName(newAlias); err != nil {311 return res, err312 }313 var stored chat1.EmojiStorage314 storage := s.makeStorage(chat1.TopicType_EMOJI)315 topicName := s.topicName(nil)316 if _, _, err := storage.Get(ctx, uid, convID, topicName, &stored, false); err != nil {317 return res, err318 }319 getExistingMsgSrc := func() (res chat1.EmojiRemoteSource, found bool) {320 if stored.Mapping == nil {321 return res, false322 }323 existingSource, ok := stored.Mapping[strings.Trim(existingAlias, ":")]324 if !ok {325 return res, false326 }327 if !existingSource.IsMessage() {328 return res, false329 }330 return existingSource, true331 }332 msgSrc, ok := getExistingMsgSrc()333 if ok {334 res = chat1.NewEmojiRemoteSourceWithMessage(chat1.EmojiMessage{335 ConvID: msgSrc.Message().ConvID,336 MsgID: msgSrc.Message().MsgID,337 IsAlias: true,338 })339 newAlias = s.normalizeShortName(newAlias)340 } else if s.IsStockEmoji(existingAlias) {341 username, err := s.G().GetUPAKLoader().LookupUsername(ctx, keybase1.UID(uid.String()))342 if err != nil {343 return res, err344 }345 res = chat1.NewEmojiRemoteSourceWithStockalias(chat1.EmojiStockAlias{346 Text: existingAlias,347 Username: username.String(),348 Time: gregor1.ToTime(s.G().GetClock().Now()),349 })350 } else {351 return res, fmt.Errorf("alias is not a valid existing custom emoji or stock emoji")352 }353 if stored.Mapping == nil {354 stored.Mapping = make(map[string]chat1.EmojiRemoteSource)355 }356 stored.Mapping[newAlias] = res357 return res, storage.Put(ctx, uid, convID, topicName, stored)358}359func (s *DevConvEmojiSource) removeRemoteSource(ctx context.Context, uid gregor1.UID,360 conv chat1.ConversationLocal, source chat1.EmojiRemoteSource) error {361 typ, err := source.Typ()362 if err != nil {363 return err364 }365 switch typ {366 case chat1.EmojiRemoteSourceTyp_MESSAGE:367 if source.Message().IsAlias {368 s.Debug(ctx, "removeRemoteSource: skipping asset remove on alias")369 return nil370 }371 return s.G().ChatHelper.DeleteMsg(ctx, source.Message().ConvID, conv.Info.TlfName,372 source.Message().MsgID)373 case chat1.EmojiRemoteSourceTyp_STOCKALIAS:374 // do nothing375 default:376 return fmt.Errorf("unable to delete remote source of typ: %v", typ)377 }378 return nil379}380func (s *DevConvEmojiSource) Remove(ctx context.Context, uid gregor1.UID, convID chat1.ConversationID,381 alias string) (err error) {382 defer s.Trace(ctx, &err, "Remove")()383 var stored chat1.EmojiStorage384 storage := s.makeStorage(chat1.TopicType_EMOJI)385 topicName := s.topicName(nil)386 _, storageConv, err := storage.Get(ctx, uid, convID, topicName, &stored, true)387 if err != nil {388 return err389 }390 if storageConv == nil {391 s.Debug(ctx, "Remove: no storage conv returned, bailing")392 return nil393 }394 if stored.Mapping == nil {395 s.Debug(ctx, "Remove: no mapping, bailing")396 return nil397 }398 // get attachment message and delete it399 source, ok := stored.Mapping[alias]400 if !ok {401 s.Debug(ctx, "Remove: no alias in mapping, bailing")402 return nil403 }404 if err := s.removeRemoteSource(ctx, uid, *storageConv, source); err != nil {405 s.Debug(ctx, "Remove: failed to remove remote source: %s", err)406 return err407 }408 delete(stored.Mapping, alias)409 // take out any aliases410 if source.IsMessage() && !source.Message().IsAlias {411 for existingAlias, existingSource := range stored.Mapping {412 if existingSource.IsMessage() && existingSource.Message().IsAlias &&413 existingSource.Message().MsgID == source.Message().MsgID {414 delete(stored.Mapping, existingAlias)415 }416 }417 }418 return storage.Put(ctx, uid, convID, topicName, stored)419}420func (s *DevConvEmojiSource) animationsDisabled(ctx context.Context, uid gregor1.UID) bool {421 st, err := s.G().GregorState.State(ctx)422 if err != nil {423 s.Debug(ctx, "animationsDisabled: failed to get state: %s", err)424 return false425 }426 cat, err := gregor1.ObjFactory{}.MakeCategory(animationKey)427 if err != nil {428 s.Debug(ctx, "animationsDisabled: failed to make category: %s", err)429 return false430 }431 items, err := st.ItemsInCategory(cat)432 if err != nil {433 s.Debug(ctx, "animationsDisabled: failed to get items: %s", err)434 return false435 }436 return len(items) > 0437}438func (s *DevConvEmojiSource) ToggleAnimations(ctx context.Context, uid gregor1.UID, enabled bool) (err error) {439 defer s.Trace(ctx, &err, "ToggleAnimations: enabled: %v", enabled)()440 cat, err := gregor1.ObjFactory{}.MakeCategory(animationKey)441 if err != nil {442 s.Debug(ctx, "animationsDisabled: failed to make category: %s", err)443 return err444 }445 if enabled {446 return s.G().GregorState.DismissCategory(ctx, cat.(gregor1.Category))447 }448 _, err = s.G().GregorState.InjectItem(ctx, animationKey, []byte{1}, gregor1.TimeOrOffset{})449 return err450}451func (s *DevConvEmojiSource) RemoteToLocalSource(ctx context.Context, uid gregor1.UID,452 remote chat1.EmojiRemoteSource) (source chat1.EmojiLoadSource, noAnimSource chat1.EmojiLoadSource, err error) {453 typ, err := remote.Typ()454 if err != nil {455 return source, noAnimSource, err456 }457 noAnim := s.animationsDisabled(ctx, uid)458 switch typ {459 case chat1.EmojiRemoteSourceTyp_MESSAGE:460 msg := remote.Message()461 sourceURL := s.G().AttachmentURLSrv.GetURL(ctx, msg.ConvID, msg.MsgID, false, noAnim, true)462 noAnimSourceURL := s.G().AttachmentURLSrv.GetURL(ctx, msg.ConvID, msg.MsgID, false, true, true)463 return chat1.NewEmojiLoadSourceWithHttpsrv(sourceURL),464 chat1.NewEmojiLoadSourceWithHttpsrv(noAnimSourceURL), nil465 case chat1.EmojiRemoteSourceTyp_STOCKALIAS:466 ret := chat1.NewEmojiLoadSourceWithStr(remote.Stockalias().Text)467 return ret, ret, nil468 default:469 return source, noAnimSource, errors.New("unknown remote source for local source")470 }471}472func (s *DevConvEmojiSource) creationInfo(ctx context.Context, uid gregor1.UID,473 remote chat1.EmojiRemoteSource) (res chat1.EmojiCreationInfo, err error) {474 typ, err := remote.Typ()475 if err != nil {476 return res, err477 }478 reason := chat1.GetThreadReason_EMOJISOURCE479 switch typ {480 case chat1.EmojiRemoteSourceTyp_MESSAGE:481 msg := remote.Message()482 sourceMsg, err := s.G().ConvSource.GetMessage(ctx, msg.ConvID, uid, msg.MsgID, &reason, nil, false)483 if err != nil {484 return res, err485 }486 if !sourceMsg.IsValid() {487 return res, errors.New("invalid message for creation info")488 }489 return chat1.EmojiCreationInfo{490 Username: sourceMsg.Valid().SenderUsername,491 Time: sourceMsg.Valid().ServerHeader.Ctime,492 }, nil493 case chat1.EmojiRemoteSourceTyp_STOCKALIAS:494 return chat1.EmojiCreationInfo{495 Username: remote.Stockalias().Username,496 Time: remote.Stockalias().Time,497 }, nil498 default:499 return res, errors.New("unknown remote source for creation info")500 }501}502func (s *DevConvEmojiSource) getNoSet(ctx context.Context, uid gregor1.UID, convID *chat1.ConversationID,503 opts chat1.EmojiFetchOpts) (res chat1.UserEmojis, aliasLookup map[string]chat1.Emoji, err error) {504 aliasLookup = make(map[string]chat1.Emoji)505 topicType := chat1.TopicType_EMOJI506 storage := s.makeStorage(topicType)507 var sourceTLFID *chat1.TLFID508 seenAliases := make(map[string]int)509 if convID != nil {510 conv, err := utils.GetUnverifiedConv(ctx, s.G(), uid, *convID, types.InboxSourceDataSourceAll)511 if err != nil {512 return res, aliasLookup, err513 }514 sourceTLFID = new(chat1.TLFID)515 *sourceTLFID = conv.Conv.Metadata.IdTriple.Tlfid516 }517 readTopicName := s.topicName(nil)518 ibox, _, err := s.G().InboxSource.Read(ctx, uid, types.ConversationLocalizerBlocking,519 types.InboxSourceDataSourceAll, nil, &chat1.GetInboxLocalQuery{520 TopicType: &topicType,521 TopicName: &readTopicName,522 })523 if err != nil {524 return res, aliasLookup, err525 }526 convs := ibox.Convs527 addEmojis := func(convs []chat1.ConversationLocal, isCrossTeam bool) {528 if opts.OnlyInTeam && isCrossTeam {529 return530 }531 for _, conv := range convs {532 var stored chat1.EmojiStorage533 found, err := storage.GetFromKnownConv(ctx, uid, conv, &stored)534 if err != nil {535 s.Debug(ctx, "Get: failed to read from known conv: %s", err)536 continue537 }538 if !found {539 s.Debug(ctx, "Get: no stored info for: %s", conv.GetConvID())540 continue541 }542 group := chat1.EmojiGroup{543 Name: conv.Info.TlfName,544 }545 for alias, storedEmoji := range stored.Mapping {546 if !opts.GetAliases && storedEmoji.IsAlias() {547 continue548 }549 var creationInfo *chat1.EmojiCreationInfo550 source, noAnimSource, err := s.RemoteToLocalSource(ctx, uid, storedEmoji)551 if err != nil {552 s.Debug(ctx, "Get: skipping emoji on remote-to-local error: %s", err)553 continue554 }555 if opts.GetCreationInfo {556 ci, err := s.creationInfo(ctx, uid, storedEmoji)557 if err != nil {558 s.Debug(ctx, "Get: failed to get creation info: %s", err)559 } else {560 creationInfo = new(chat1.EmojiCreationInfo)561 *creationInfo = ci562 }563 }564 teamname := conv.Info.TlfName565 emoji := chat1.Emoji{566 Alias: alias,567 Source: source,568 NoAnimSource: noAnimSource,569 RemoteSource: storedEmoji,570 IsCrossTeam: isCrossTeam,571 CreationInfo: creationInfo,572 IsAlias: storedEmoji.IsAlias(),573 Teamname: &teamname,574 }575 if seen, ok := seenAliases[alias]; ok {576 seenAliases[alias]++577 emoji.Alias += fmt.Sprintf("#%d", seen)578 } else {579 seenAliases[alias] = 2580 }581 aliasLookup[emoji.Alias] = emoji582 group.Emojis = append(group.Emojis, emoji)583 }584 res.Emojis = append(res.Emojis, group)585 }586 }587 var tlfConvs, otherConvs []chat1.ConversationLocal588 for _, conv := range convs {589 if sourceTLFID != nil && conv.Info.Triple.Tlfid.Eq(*sourceTLFID) {590 tlfConvs = append(tlfConvs, conv)591 } else {592 otherConvs = append(otherConvs, conv)593 }594 }595 addEmojis(tlfConvs, false)596 addEmojis(otherConvs, sourceTLFID != nil)597 return res, aliasLookup, nil598}599func (s *DevConvEmojiSource) Get(ctx context.Context, uid gregor1.UID, convID *chat1.ConversationID,600 opts chat1.EmojiFetchOpts) (res chat1.UserEmojis, err error) {601 defer s.Trace(ctx, &err, "Get")()602 var aliasLookup map[string]chat1.Emoji603 if res, aliasLookup, err = s.getNoSet(ctx, uid, convID, opts); err != nil {604 return res, err605 }606 if err := s.putAliasLookup(ctx, uid, aliasLookup, opts); err != nil {607 s.Debug(ctx, "Get: failed to put alias lookup: %s", err)608 }609 for _, group := range res.Emojis {610 sort.Slice(group.Emojis, func(i, j int) bool {611 return group.Emojis[i].Alias < group.Emojis[j].Alias612 })613 }614 return res, nil615}616type emojiMatch struct {617 name string618 position []int619}620func (s *DevConvEmojiSource) parse(ctx context.Context, body string) (res []emojiMatch) {621 body = utils.ReplaceQuotedSubstrings(body, false)622 hits := globals.EmojiPattern.FindAllStringSubmatchIndex(body, -1)623 for _, hit := range hits {624 if len(hit) < 4 {625 s.Debug(ctx, "parse: malformed hit: %d", len(hit))626 continue627 }628 res = append(res, emojiMatch{629 name: body[hit[2]:hit[3]],630 position: []int{hit[0], hit[1]},631 })632 }633 return res634}635func (s *DevConvEmojiSource) stripAlias(alias string) string {636 return strings.Split(alias, "#")[0]637}638func (s *DevConvEmojiSource) versionMatch(ctx context.Context, uid gregor1.UID, l chat1.EmojiRemoteSource,639 r chat1.EmojiRemoteSource) bool {640 if !l.IsMessage() || !r.IsMessage() {641 return false642 }643 reason := chat1.GetThreadReason_EMOJISOURCE644 lmsg, err := s.G().ConvSource.GetMessage(ctx, l.Message().ConvID, uid, l.Message().MsgID, &reason,645 nil, false)646 if err != nil {647 s.Debug(ctx, "versionMatch: failed to get lmsg: %s", err)648 return false649 }650 rmsg, err := s.G().ConvSource.GetMessage(ctx, r.Message().ConvID, uid, r.Message().MsgID, &reason,651 nil, false)652 if err != nil {653 s.Debug(ctx, "versionMatch: failed to get rmsg: %s", err)654 return false655 }656 if !lmsg.IsValid() || !rmsg.IsValid() {657 s.Debug(ctx, "versionMatch: one message not valid: lmsg: %s rmsg: %s", lmsg.DebugString(),658 rmsg.DebugString())659 return false660 }661 if !lmsg.Valid().MessageBody.IsType(chat1.MessageType_ATTACHMENT) ||662 !rmsg.Valid().MessageBody.IsType(chat1.MessageType_ATTACHMENT) {663 s.Debug(ctx, "versionMatch: one message not attachment: lmsg: %s rmsg: %s", lmsg.DebugString(),664 rmsg.DebugString())665 return false666 }667 lhash := lmsg.Valid().MessageBody.Attachment().Object.PtHash668 rhash := rmsg.Valid().MessageBody.Attachment().Object.PtHash669 return lhash != nil && rhash != nil && lhash.Eq(rhash)670}671func (s *DevConvEmojiSource) getCrossTeamConv(ctx context.Context, uid gregor1.UID,672 convID chat1.ConversationID, sourceConvID chat1.ConversationID) (res chat1.ConversationLocal, err error) {673 baseConv, err := utils.GetVerifiedConv(ctx, s.G(), uid, convID, types.InboxSourceDataSourceAll)674 if err != nil {675 s.Debug(ctx, "getCrossTeamConv: failed to get base conv: %s", err)676 return res, err677 }678 sourceConv, err := utils.GetVerifiedConv(ctx, s.G(), uid, sourceConvID, types.InboxSourceDataSourceAll)679 if err != nil {680 s.Debug(ctx, "getCrossTeamConv: failed to get source conv: %s", err)681 return res, err682 }683 var created bool684 topicID := chat1.TopicID(sourceConv.Info.Triple.Tlfid.Bytes())685 s.Debug(ctx, "getCrossTeamConv: attempting conv create: sourceConvID: %s topicID: %s",686 sourceConv.GetConvID(), topicID)687 topicName := topicID.String()688 if res, created, err = NewConversation(ctx, s.G(), uid, baseConv.Info.TlfName, &topicName,689 chat1.TopicType_EMOJICROSS, baseConv.GetMembersType(), baseConv.Info.Visibility,690 &topicID, s.ri, NewConvFindExistingNormal); err != nil {691 if convExistsErr, ok := err.(libkb.ChatConvExistsError); ok {692 s.Debug(ctx, "getCrossTeamConv: conv exists error received, attempting to join: %s", err)693 if err := JoinConversation(ctx, s.G(), s.DebugLabeler, s.ri, uid, convExistsErr.ConvID); err != nil {694 s.Debug(ctx, "getCrossTeamConv: failed to join: %s", err)695 return res, err696 }697 if res, err = utils.GetVerifiedConv(ctx, s.G(), uid, convExistsErr.ConvID,698 types.InboxSourceDataSourceAll); err != nil {699 s.Debug(ctx, "getCrossTeamConv: failed to get conv after successful join: %s", err)700 }701 created = false702 } else {703 return res, err704 }705 }706 if created {707 s.Debug(ctx, "getCrossTeamConv: created a new sync conv: %s (topicID: %s)", res.GetConvID(), topicID)708 if s.testingCreatedSyncConv != nil {709 s.testingCreatedSyncConv <- struct{}{}710 }711 } else {712 s.Debug(ctx, "getCrossTeamConv: using exising sync conv: %s (topicID: %s)", res.GetConvID(), topicID)713 }714 return res, nil715}716func (s *DevConvEmojiSource) getCacheDir() string {717 if len(s.tempDir) > 0 {718 return s.tempDir719 }720 return s.G().GetCacheDir()721}722func (s *DevConvEmojiSource) syncCrossTeam(ctx context.Context, uid gregor1.UID, emoji chat1.HarvestedEmoji,723 convID chat1.ConversationID) (res chat1.HarvestedEmoji, err error) {724 typ, err := emoji.Source.Typ()725 if err != nil {726 return res, err727 }728 switch typ {729 case chat1.EmojiRemoteSourceTyp_MESSAGE:730 case chat1.EmojiRemoteSourceTyp_STOCKALIAS:731 emoji.IsCrossTeam = true732 return emoji, nil733 default:734 return res, errors.New("invalid remote source to sync")735 }736 var stored chat1.EmojiStorage737 storage := s.makeStorage(chat1.TopicType_EMOJICROSS)738 sourceConvID := emoji.Source.Message().ConvID739 syncConv, err := s.getCrossTeamConv(ctx, uid, convID, sourceConvID)740 if err != nil {741 s.Debug(ctx, "syncCrossTeam: failed to get cross team conv: %s", err)742 return res, err743 }744 if _, err := storage.GetFromKnownConv(ctx, uid, syncConv, &stored); err != nil {745 s.Debug(ctx, "syncCrossTeam: failed to get from known conv: %s", err)746 return res, err747 }748 if stored.Mapping == nil {749 stored.Mapping = make(map[string]chat1.EmojiRemoteSource)750 }751 // check for a match...
storage_test.go
Source:storage_test.go
...48}49func (dm *dashMock) getDashapi() *dashapi.Dashboard {50 return dashapi.NewMock(dm.do)51}52func makeStorage(t *testing.T, dash *dashapi.Dashboard) (*Storage, *dummyStorageBackend) {53 be := makeDummyStorageBackend()54 cfg := &Config{55 UploadTo: "dummy://test",56 }57 return &Storage{58 dash: dash,59 cfg: cfg,60 backend: be,61 tracer: &debugtracer.TestTracer{T: t},62 }, be63}64func validateGzip(res *uploadedFile, expected []byte) error {65 if res == nil {66 return fmt.Errorf("no file was uploaded")67 }68 reader, err := gzip.NewReader(bytes.NewReader(res.bytes))69 if err != nil {70 return fmt.Errorf("gzip.NewReader failed: %w", err)71 }72 defer reader.Close()73 body, err := ioutil.ReadAll(reader)74 if err != nil {75 return fmt.Errorf("read of ungzipped content failed: %w", err)76 }77 if !reflect.DeepEqual(body, expected) {78 return fmt.Errorf("decompressed: %#v, expected: %#v", body, expected)79 }80 return nil81}82func validateXz(res *uploadedFile, expected []byte) error {83 if res == nil {84 return fmt.Errorf("no file was uploaded")85 }86 xzUsed := strings.HasSuffix(res.req.savePath, ".xz")87 if !xzUsed {88 return fmt.Errorf("xz expected to be used")89 }90 xzReader, err := xz.NewReader(bytes.NewReader(res.bytes))91 if err != nil {92 return fmt.Errorf("xz reader failed: %w", err)93 }94 out, err := ioutil.ReadAll(xzReader)95 if err != nil {96 return fmt.Errorf("xz decompression failed: %w", err)97 }98 if !reflect.DeepEqual(out, expected) {99 return fmt.Errorf("decompressed: %#v, expected: %#v", out, expected)100 }101 return nil102}103func (storage *Storage) sendBuildAsset(reader io.Reader, fileName string, assetType dashapi.AssetType,104 build *dashapi.Build) error {105 asset, err := storage.UploadBuildAsset(reader, fileName, assetType, build, nil)106 if err != nil {107 return err108 }109 return storage.ReportBuildAssets(build, asset)110}111func TestUploadBuildAsset(t *testing.T) {112 dashMock := newDashMock()113 storage, be := makeStorage(t, dashMock.getDashapi())114 be.currentTime = time.Now().Add(-2 * deletionEmbargo)115 build := &dashapi.Build{ID: "1234", KernelCommit: "abcdef2134"}116 // Upload two assets using different means.117 vmLinuxContent := []byte{0xDE, 0xAD, 0xBE, 0xEF}118 dashMock.addBuildAsset = func(newAsset dashapi.NewAsset) error {119 if newAsset.Type != dashapi.KernelObject {120 t.Fatalf("expected KernelObject, got %v", newAsset.Type)121 }122 if !strings.Contains(newAsset.DownloadURL, "vmlinux") {123 t.Fatalf("%#v was expected to mention vmlinux", newAsset.DownloadURL)124 }125 return nil126 }127 var file *uploadedFile128 be.objectUpload = collectBytes(&file)129 err := storage.sendBuildAsset(bytes.NewReader(vmLinuxContent), "vmlinux",130 dashapi.KernelObject, build)131 if err != nil {132 t.Fatalf("file upload failed: %s", err)133 }134 if err := validateXz(file, vmLinuxContent); err != nil {135 t.Fatalf("vmlinux validation failed: %s", err)136 }137 // Upload the same file the second time.138 storage.sendBuildAsset(bytes.NewReader(vmLinuxContent), "vmlinux", dashapi.KernelObject, build)139 // The currently expected behavior is that it will be uploaded twice and will have140 // different names.141 if len(dashMock.downloadURLs) < 2 {142 t.Fatalf("same-file upload was expected to succeed, but it didn't; %#v", dashMock.downloadURLs)143 }144 diskImageContent := []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}145 dashMock.addBuildAsset = func(newAsset dashapi.NewAsset) error {146 if newAsset.Type != dashapi.KernelImage {147 t.Fatalf("expected KernelImage, got %v", newAsset.Type)148 }149 if !strings.Contains(newAsset.DownloadURL, "disk") ||150 !strings.Contains(newAsset.DownloadURL, ".img") {151 t.Fatalf("%#v was expected to mention disk.img", newAsset.DownloadURL)152 }153 if !strings.Contains(newAsset.DownloadURL, build.KernelCommit[:6]) {154 t.Fatalf("%#v was expected to mention build commit", newAsset.DownloadURL)155 }156 return nil157 }158 file = nil159 be.objectUpload = collectBytes(&file)160 storage.sendBuildAsset(bytes.NewReader(diskImageContent), "disk.img", dashapi.KernelImage, build)161 if err := validateXz(file, diskImageContent); err != nil {162 t.Fatalf("disk.img validation failed: %s", err)163 }164 allUrls := []string{}165 for url := range dashMock.downloadURLs {166 allUrls = append(allUrls, url)167 }168 if len(allUrls) != 3 {169 t.Fatalf("invalid dashMock state: expected 3 assets, got %d", len(allUrls))170 }171 // First try to remove two assets.172 dashMock.downloadURLs = map[string]bool{allUrls[2]: true, "http://non-related-asset.com/abcd": true}173 // Pretend there's an asset deletion error.174 be.objectRemove = func(string) error { return fmt.Errorf("not now") }175 err = storage.DeprecateAssets()176 if err == nil {177 t.Fatalf("DeprecateAssets() should have failed")178 }179 // Let the deletion be successful.180 be.objectRemove = nil181 err = storage.DeprecateAssets()182 if err != nil {183 t.Fatalf("DeprecateAssets() was expected to be successful, got %s", err)184 }185 path, err := be.getPath(allUrls[2])186 if err != nil {187 t.Fatalf("getPath failed: %s", err)188 }189 err = be.hasOnly([]string{path})190 if err != nil {191 t.Fatalf("after first DeprecateAssets(): %s", err)192 }193 // Delete the rest.194 dashMock.downloadURLs = map[string]bool{}195 err = storage.DeprecateAssets()196 if err != nil || len(be.objects) != 0 {197 t.Fatalf("second DeprecateAssets() failed: %s, len %d",198 err, len(be.objects))199 }200}201type uploadedFile struct {202 req uploadRequest203 bytes []byte204}205func collectBytes(saveTo **uploadedFile) objectUploadCallback {206 return func(req *uploadRequest) (*uploadResponse, error) {207 buf := &bytes.Buffer{}208 wwc := &wrappedWriteCloser{209 writer: buf,210 closeCallback: func() error {211 *saveTo = &uploadedFile{req: *req, bytes: buf.Bytes()}212 return nil213 },214 }215 return &uploadResponse{path: req.savePath, writer: wwc}, nil216 }217}218func TestUploadHtmlAsset(t *testing.T) {219 dashMock := newDashMock()220 storage, be := makeStorage(t, dashMock.getDashapi())221 build := &dashapi.Build{ID: "1234", KernelCommit: "abcdef2134"}222 htmlContent := []byte("<html><head><title>Hi!</title></head></html>")223 dashMock.addBuildAsset = func(newAsset dashapi.NewAsset) error {224 if newAsset.Type != dashapi.HTMLCoverageReport {225 t.Fatalf("expected HtmlCoverageReport, got %v", newAsset.Type)226 }227 if !strings.Contains(newAsset.DownloadURL, "cover_report") {228 t.Fatalf("%#v was expected to mention cover_report", newAsset.DownloadURL)229 }230 if !strings.HasSuffix(newAsset.DownloadURL, ".html") {231 t.Fatalf("%#v was expected to have .html extension", newAsset.DownloadURL)232 }233 return nil234 }235 var file *uploadedFile236 be.objectUpload = collectBytes(&file)237 storage.sendBuildAsset(bytes.NewReader(htmlContent), "cover_report.html",238 dashapi.HTMLCoverageReport, build)239 if err := validateGzip(file, htmlContent); err != nil {240 t.Fatalf("cover_report.html validation failed: %s", err)241 }242}243func TestRecentAssetDeletionProtection(t *testing.T) {244 dashMock := newDashMock()245 storage, be := makeStorage(t, dashMock.getDashapi())246 build := &dashapi.Build{ID: "1234", KernelCommit: "abcdef2134"}247 htmlContent := []byte("<html><head><title>Hi!</title></head></html>")248 be.currentTime = time.Now().Add(-time.Hour * 24 * 6)249 err := storage.sendBuildAsset(bytes.NewReader(htmlContent), "cover_report.html",250 dashapi.HTMLCoverageReport, build)251 if err != nil {252 t.Fatalf("failed to upload a file: %v", err)253 }254 // Try to delete a recent file.255 dashMock.downloadURLs = map[string]bool{}256 err = storage.DeprecateAssets()257 if err != nil {258 t.Fatalf("DeprecateAssets failed: %v", err)259 } else if len(be.objects) == 0 {260 t.Fatalf("a recent object was deleted: %v", err)261 }262}263func TestAssetStorageConfiguration(t *testing.T) {264 dashMock := newDashMock()265 cfg := &Config{266 UploadTo: "dummy://",267 Assets: map[dashapi.AssetType]TypeConfig{268 dashapi.HTMLCoverageReport: {Never: true},269 dashapi.KernelObject: {},270 },271 }272 storage, err := StorageFromConfig(cfg, dashMock.getDashapi())273 if err != nil {274 t.Fatalf("unexpected error from StorageFromConfig: %s", err)275 }276 build := &dashapi.Build{ID: "1234", KernelCommit: "abcdef2134"}277 // Uploading a file of a disabled asset type.278 htmlContent := []byte("<html><head><title>Hi!</title></head></html>")279 err = storage.sendBuildAsset(bytes.NewReader(htmlContent), "cover_report.html",280 dashapi.HTMLCoverageReport, build)281 if !errors.Is(err, ErrAssetTypeDisabled) {282 t.Fatalf("UploadBuildAssetStream expected to fail with ErrAssetTypeDisabled, but got %v", err)283 }284 // Uploading a file of an unspecified asset type.285 testContent := []byte{0x1, 0x2, 0x3, 0x4}286 err = storage.sendBuildAsset(bytes.NewReader(testContent), "disk.raw", dashapi.BootableDisk, build)287 if err != nil {288 t.Fatalf("UploadBuildAssetStream of BootableDisk expected to succeed, got %v", err)289 }290 // Uploading a file of a specified asset type.291 err = storage.sendBuildAsset(bytes.NewReader(testContent), "vmlinux", dashapi.KernelObject, build)292 if err != nil {293 t.Fatalf("UploadBuildAssetStream of BootableDisk expected to succeed, got %v", err)294 }295}296func TestUploadSameContent(t *testing.T) {297 dashMock := newDashMock()298 storage, be := makeStorage(t, dashMock.getDashapi())299 be.currentTime = time.Now().Add(-2 * deletionEmbargo)300 build := &dashapi.Build{ID: "1234", KernelCommit: "abcdef2134"}301 extra := &ExtraUploadArg{UniqueTag: "uniquetag", SkipIfExists: true}302 testContent := []byte{0x1, 0x2, 0x3, 0x4}303 asset, err := storage.UploadBuildAsset(bytes.NewReader(testContent), "disk.raw",304 dashapi.BootableDisk, build, extra)305 if err != nil {306 t.Fatalf("UploadBuildAssetexpected to succeed, got %v", err)307 }308 if !strings.Contains(asset.DownloadURL, extra.UniqueTag) {309 t.Fatalf("%#v was expected to contain %#v", asset.DownloadURL, extra.UniqueTag)310 }311 // Upload the same asset again.312 be.objectUpload = func(req *uploadRequest) (*uploadResponse, error) {...
makeStorage
Using AI Code Generation
1import "fmt"2func main() {3 var asset1 = asset{}4 asset1.makeStorage()5 fmt.Println(asset1.storage)6}7import "fmt"8func main() {9 var asset1 = asset{}10 asset1.makeStorage()11 fmt.Println(asset1.storage)12}13type asset struct {14}15func (a *asset) makeStorage() {16 a.storage = make([]int, 10)17}18import "fmt"19func main() {20 var asset1 = asset{}21 asset1.makeStorage()22 fmt.Println(asset1.storage)23}24type asset struct {25}26func (a *asset) makeStorage() {27 a.storage = make([]int, 10)28}
makeStorage
Using AI Code Generation
1import (2func main() {3 a.makeStorage()4}5import (6func main() {7 a.makeStorage()8}9import (10func main() {11 a.makeStorage()12}13import (14func main() {15 a.makeStorage()16}17import (18func main() {19 a.makeStorage()20}21import (22func main() {23 a.makeStorage()24}25import (26func main() {27 a.makeStorage()28}
makeStorage
Using AI Code Generation
1import (2func main() {3 storage := asset.MakeStorage()4 storage.Add(asset.Asset{"foo", 100})5 storage.Add(asset.Asset{"bar", 200})6 fmt.Println("Total value of all assets: ", storage.TotalValue())7}
makeStorage
Using AI Code Generation
1import (2func main() {3 asset := Asset{"abc", "xyz", 200}4 fmt.Println(asset)5 asset.makeStorage()6}7import (8func main() {9 asset := Asset{"abc", "xyz", 200}10 fmt.Println(asset)11 asset.makeStorage()12}13type Asset struct {14}15func (a *Asset) makeStorage() {16 fmt.Println(a.assetName, a.assetType, a.assetQty)17 fmt.Println(a.assetName, a.assetType, a.assetQty)18}19import (20func main() {21 asset := Asset{"abc", "xyz", 200}22 fmt.Println(asset)23 asset.makeStorage()24}25type Asset struct {26}27func (a *Asset) makeStorage() {28 fmt.Println(a.assetName, a.assetType, a.assetQty)29 fmt.Println(a.assetName, a.assetType, a.assetQty)30}31func (a Asset) makeStorage1() {32 fmt.Println(a.assetName, a
makeStorage
Using AI Code Generation
1import "fmt"2func main() {3 storage = makeStorage()4 storage.store("Hello World")5 fmt.Println(storage.load())6}
makeStorage
Using AI Code Generation
1import (2type asset struct {3}4type storage interface {5 getData() []byte6}7type storageImpl struct {8}9func (s storageImpl) getData() []byte {10 return []byte("data")11}12func makeStorage() storage {13 return storageImpl{}14}15func main() {16 a := asset{makeStorage()}17 fmt.Println(string(a.storage.getData()))18 time.Sleep(5 * time.Second)19}20import (21type asset struct {22}23type storage interface {24 getData() []byte25}26type storageImpl struct {27}28func (s storageImpl) getData() []byte {29 return []byte("data")30}31func makeStorage() storage {32 return storageImpl{}33}34func main() {35 a := asset{makeStorage()}36 fmt.Println(string(a.storage.getData()))37 time.Sleep(5 * time.Second)38}39import (40type asset struct {41}42type storage interface {43 getData() []byte44}45type storageImpl struct {46}47func (s storageImpl) getData() []byte {48 return []byte("data")49}50func makeStorage() storage {51 return storageImpl{}52}53func main() {54 a := asset{makeStorage()}55 fmt.Println(string(a.storage.getData()))56 time.Sleep(5 * time.Second)57}58import (59type asset struct {60}61type storage interface {62 getData() []byte63}64type storageImpl struct {65}66func (s storageImpl) getData()
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!