1 // ----------------------------------------------------------------------------------------------
3 // / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
4 // / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
5 // / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
6 // /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
7 // ----------------------------------------------------------------------------------------------
9 // Copyright 2015-2024 Ćukasz "JustArchi" Domeradzki
10 // Contact: JustArchi@JustArchi.net
12 // Licensed under the Apache License, Version 2.0 (the "License");
13 // you may not use this file except in compliance with the License.
14 // You may obtain a copy of the License at
16 // http://www.apache.org/licenses/LICENSE-2.0
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the License is distributed on an "AS IS" BASIS,
20 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 // See the License for the specific language governing permissions and
22 // limitations under the License.
24 using System
.Collections
.Generic
;
25 using ArchiSteamFarm
.Steam
.Data
;
26 using Microsoft
.VisualStudio
.TestTools
.UnitTesting
;
27 using static ArchiSteamFarm
.Steam
.Exchange
.Trading
;
29 namespace ArchiSteamFarm
.Tests
;
31 #pragma warning disable CA1812 // False positive, the class is used during MSTest
33 internal sealed class Trading
{
35 internal void ExploitingNewSetsIsFairButNotNeutral() {
36 HashSet
<Asset
> inventory
= [
37 CreateItem(1, amount
: 40),
38 CreateItem(2, amount
: 10),
39 CreateItem(3, amount
: 10)
42 HashSet
<Asset
> itemsToGive
= [
43 CreateItem(2, amount
: 5),
44 CreateItem(3, amount
: 5)
47 HashSet
<Asset
> itemsToReceive
= [
48 CreateItem(1, amount
: 9),
52 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
53 Assert
.IsFalse(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
57 internal void Issue3203() {
58 HashSet
<Asset
> inventory
= [
59 CreateItem(1, amount
: 2),
60 CreateItem(2, amount
: 6),
65 HashSet
<Asset
> itemsToGive
= [
67 CreateItem(2, amount
: 2)
70 HashSet
<Asset
> itemsToReceive
= [
76 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
77 Assert
.IsTrue(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
81 internal void MismatchRarityIsNotFair() {
82 HashSet
<Asset
> itemsToGive
= [
83 CreateItem(1, rarity
: EAssetRarity
.Rare
)
86 HashSet
<Asset
> itemsToReceive
= [
90 Assert
.IsFalse(IsFairExchange(itemsToGive
, itemsToReceive
));
94 internal void MismatchRealAppIDsIsNotFair() {
95 HashSet
<Asset
> itemsToGive
= [
96 CreateItem(1, realAppID
: 570)
99 HashSet
<Asset
> itemsToReceive
= [
103 Assert
.IsFalse(IsFairExchange(itemsToGive
, itemsToReceive
));
107 internal void MismatchTypesIsNotFair() {
108 HashSet
<Asset
> itemsToGive
= [
109 CreateItem(1, type
: EAssetType
.Emoticon
)
112 HashSet
<Asset
> itemsToReceive
= [
116 Assert
.IsFalse(IsFairExchange(itemsToGive
, itemsToReceive
));
120 internal void MultiGameMultiTypeBadReject() {
121 HashSet
<Asset
> inventory
= [
122 CreateItem(1, amount
: 9),
123 CreateItem(3, amount
: 9, realAppID
: 730, type
: EAssetType
.Emoticon
),
124 CreateItem(4, realAppID
: 730, type
: EAssetType
.Emoticon
)
127 HashSet
<Asset
> itemsToGive
= [
129 CreateItem(4, realAppID
: 730, type
: EAssetType
.Emoticon
)
132 HashSet
<Asset
> itemsToReceive
= [
134 CreateItem(3, realAppID
: 730, type
: EAssetType
.Emoticon
)
137 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
138 Assert
.IsFalse(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
142 internal void MultiGameMultiTypeNeutralAccept() {
143 HashSet
<Asset
> inventory
= [
144 CreateItem(1, amount
: 9),
145 CreateItem(3, realAppID
: 730, type
: EAssetType
.Emoticon
)
148 HashSet
<Asset
> itemsToGive
= [
150 CreateItem(3, realAppID
: 730, type
: EAssetType
.Emoticon
)
153 HashSet
<Asset
> itemsToReceive
= [
155 CreateItem(4, realAppID
: 730, type
: EAssetType
.Emoticon
)
158 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
159 Assert
.IsTrue(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
163 internal void MultiGameSingleTypeBadReject() {
164 HashSet
<Asset
> inventory
= [
165 CreateItem(1, amount
: 9),
166 CreateItem(3, realAppID
: 730),
167 CreateItem(4, realAppID
: 730)
170 HashSet
<Asset
> itemsToGive
= [
172 CreateItem(3, realAppID
: 730)
175 HashSet
<Asset
> itemsToReceive
= [
177 CreateItem(4, realAppID
: 730)
180 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
181 Assert
.IsFalse(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
185 internal void MultiGameSingleTypeNeutralAccept() {
186 HashSet
<Asset
> inventory
= [
187 CreateItem(1, amount
: 2),
188 CreateItem(3, realAppID
: 730)
191 HashSet
<Asset
> itemsToGive
= [
193 CreateItem(3, realAppID
: 730)
196 HashSet
<Asset
> itemsToReceive
= [
198 CreateItem(4, realAppID
: 730)
201 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
202 Assert
.IsTrue(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
206 internal void SingleGameAbrynosWasWrongNeutralAccept() {
207 HashSet
<Asset
> inventory
= [
209 CreateItem(2, amount
: 2),
215 HashSet
<Asset
> itemsToGive
= [
219 HashSet
<Asset
> itemsToReceive
= [
223 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
224 Assert
.IsTrue(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
228 internal void SingleGameDonationAccept() {
229 HashSet
<Asset
> inventory
= [
233 HashSet
<Asset
> itemsToGive
= [
237 HashSet
<Asset
> itemsToReceive
= [
239 CreateItem(3, type
: EAssetType
.SteamGems
)
242 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
243 Assert
.IsTrue(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
247 internal void SingleGameMultiTypeBadReject() {
248 HashSet
<Asset
> inventory
= [
249 CreateItem(1, amount
: 9),
250 CreateItem(3, amount
: 9, type
: EAssetType
.Emoticon
),
251 CreateItem(4, type
: EAssetType
.Emoticon
)
254 HashSet
<Asset
> itemsToGive
= [
256 CreateItem(4, type
: EAssetType
.Emoticon
)
259 HashSet
<Asset
> itemsToReceive
= [
261 CreateItem(3, type
: EAssetType
.Emoticon
)
264 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
265 Assert
.IsFalse(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
269 internal void SingleGameMultiTypeNeutralAccept() {
270 HashSet
<Asset
> inventory
= [
271 CreateItem(1, amount
: 9),
272 CreateItem(3, type
: EAssetType
.Emoticon
)
275 HashSet
<Asset
> itemsToGive
= [
277 CreateItem(3, type
: EAssetType
.Emoticon
)
280 HashSet
<Asset
> itemsToReceive
= [
282 CreateItem(4, type
: EAssetType
.Emoticon
)
285 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
286 Assert
.IsTrue(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
290 internal void SingleGameQuantityBadReject() {
291 HashSet
<Asset
> inventory
= [
297 HashSet
<Asset
> itemsToGive
= [
303 HashSet
<Asset
> itemsToReceive
= [
304 CreateItem(4, amount
: 3)
307 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
308 Assert
.IsFalse(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
312 internal void SingleGameQuantityBadReject2() {
313 HashSet
<Asset
> inventory
= [
315 CreateItem(2, amount
: 2)
318 HashSet
<Asset
> itemsToGive
= [
320 CreateItem(2, amount
: 2)
323 HashSet
<Asset
> itemsToReceive
= [
324 CreateItem(3, amount
: 3)
327 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
328 Assert
.IsFalse(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
332 internal void SingleGameQuantityNeutralAccept() {
333 HashSet
<Asset
> inventory
= [
334 CreateItem(1, amount
: 2),
338 HashSet
<Asset
> itemsToGive
= [
343 HashSet
<Asset
> itemsToReceive
= [
344 CreateItem(3, amount
: 2)
347 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
348 Assert
.IsTrue(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
352 internal void SingleGameSingleTypeBadReject() {
353 HashSet
<Asset
> inventory
= [
358 HashSet
<Asset
> itemsToGive
= [
362 HashSet
<Asset
> itemsToReceive
= [
366 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
367 Assert
.IsFalse(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
371 internal void SingleGameSingleTypeBadWithOverpayingReject() {
372 HashSet
<Asset
> inventory
= [
373 CreateItem(1, amount
: 2),
374 CreateItem(2, amount
: 2),
375 CreateItem(3, amount
: 2)
378 HashSet
<Asset
> itemsToGive
= [
382 HashSet
<Asset
> itemsToReceive
= [
387 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
388 Assert
.IsFalse(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
392 internal void SingleGameSingleTypeBigDifferenceAccept() {
393 HashSet
<Asset
> inventory
= [
395 CreateItem(2, amount
: 5),
399 HashSet
<Asset
> itemsToGive
= [
403 HashSet
<Asset
> itemsToReceive
= [
407 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
408 Assert
.IsTrue(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
412 internal void SingleGameSingleTypeBigDifferenceReject() {
413 HashSet
<Asset
> inventory
= [
415 CreateItem(2, amount
: 2),
416 CreateItem(3, amount
: 2),
417 CreateItem(4, amount
: 3),
418 CreateItem(5, amount
: 10)
421 HashSet
<Asset
> itemsToGive
= [
426 HashSet
<Asset
> itemsToReceive
= [
431 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
432 Assert
.IsFalse(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
436 internal void SingleGameSingleTypeGoodAccept() {
437 HashSet
<Asset
> inventory
= [
438 CreateItem(1, amount
: 2)
441 HashSet
<Asset
> itemsToGive
= [
445 HashSet
<Asset
> itemsToReceive
= [
449 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
450 Assert
.IsTrue(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
454 internal void SingleGameSingleTypeNeutralAccept() {
455 HashSet
<Asset
> inventory
= [
459 HashSet
<Asset
> itemsToGive
= [
463 HashSet
<Asset
> itemsToReceive
= [
467 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
468 Assert
.IsTrue(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
472 internal void SingleGameSingleTypeNeutralWithOverpayingAccept() {
473 HashSet
<Asset
> inventory
= [
474 CreateItem(1, amount
: 2),
475 CreateItem(2, amount
: 2)
478 HashSet
<Asset
> itemsToGive
= [
482 HashSet
<Asset
> itemsToReceive
= [
487 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
488 Assert
.IsTrue(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
492 internal void TakingExcessiveAmountOfSingleCardCanStillBeFairAndNeutral() {
493 HashSet
<Asset
> inventory
= [
494 CreateItem(1, amount
: 52),
495 CreateItem(2, amount
: 73),
496 CreateItem(3, amount
: 52),
497 CreateItem(4, amount
: 47),
501 HashSet
<Asset
> itemsToGive
= [
502 CreateItem(2, amount
: 73)
505 HashSet
<Asset
> itemsToReceive
= [
506 CreateItem(1, amount
: 9),
507 CreateItem(3, amount
: 9),
508 CreateItem(4, amount
: 8),
509 CreateItem(5, amount
: 24),
510 CreateItem(6, amount
: 23)
513 Assert
.IsTrue(IsFairExchange(itemsToGive
, itemsToReceive
));
514 Assert
.IsTrue(IsTradeNeutralOrBetter(inventory
, itemsToGive
, itemsToReceive
));
517 private static Asset
CreateItem(ulong classID
, ulong instanceID
= 0, uint amount
= 1, bool marketable
= false, bool tradable
= false, uint realAppID
= Asset
.SteamAppID
, EAssetType type
= EAssetType
.TradingCard
, EAssetRarity rarity
= EAssetRarity
.Common
) => new(Asset
.SteamAppID
, Asset
.SteamCommunityContextID
, classID
, amount
, new InventoryDescription(Asset
.SteamAppID
, classID
, instanceID
, marketable
, tradable
, realAppID
, type
, rarity
));
519 #pragma warning restore CA1812 // False positive, the class is used during MSTest