@@ -2497,6 +2497,208 @@ public void Position_KeyIsCaseInsensitive()
24972497 retrieved . Changes [ PositionChangeTypes . CurrentValue ] . AssertEqual ( 200m ) ;
24982498 }
24992499
2500+ [ TestMethod ]
2501+ public void Position_GetAllSnapshots_Empty_ReturnsEmpty ( )
2502+ {
2503+ var holder = new PositionSnapshotHolder ( ) ;
2504+
2505+ var snapshots = holder . GetAllSnapshots ( ) . ToList ( ) ;
2506+
2507+ snapshots . Count . AssertEqual ( 0 ) ;
2508+ }
2509+
2510+ [ TestMethod ]
2511+ public void Position_GetAllSnapshots_ReturnsAllPositions ( )
2512+ {
2513+ var holder = new PositionSnapshotHolder ( ) ;
2514+
2515+ holder . Process ( new PositionChangeMessage
2516+ {
2517+ PortfolioName = "Portfolio1" ,
2518+ SecurityId = _secId1 ,
2519+ ServerTime = _now ,
2520+ } . TryAdd ( PositionChangeTypes . CurrentValue , 100m ) ) ;
2521+
2522+ holder . Process ( new PositionChangeMessage
2523+ {
2524+ PortfolioName = "Portfolio2" ,
2525+ SecurityId = _secId2 ,
2526+ ServerTime = _now ,
2527+ } . TryAdd ( PositionChangeTypes . CurrentValue , 200m ) ) ;
2528+
2529+ var snapshots = holder . GetAllSnapshots ( ) . ToList ( ) ;
2530+
2531+ snapshots . Count . AssertEqual ( 2 ) ;
2532+
2533+ var snap1 = snapshots . First ( s => s . PortfolioName == "Portfolio1" ) ;
2534+ var snap2 = snapshots . First ( s => s . PortfolioName == "Portfolio2" ) ;
2535+
2536+ snap1 . Changes [ PositionChangeTypes . CurrentValue ] . AssertEqual ( 100m ) ;
2537+ snap2 . Changes [ PositionChangeTypes . CurrentValue ] . AssertEqual ( 200m ) ;
2538+ }
2539+
2540+ [ TestMethod ]
2541+ public void Position_GetAllSnapshots_ReturnsCopies ( )
2542+ {
2543+ var holder = new PositionSnapshotHolder ( ) ;
2544+
2545+ holder . Process ( new PositionChangeMessage
2546+ {
2547+ PortfolioName = "Portfolio1" ,
2548+ SecurityId = _secId1 ,
2549+ ServerTime = _now ,
2550+ } . TryAdd ( PositionChangeTypes . CurrentValue , 100m ) ) ;
2551+
2552+ var snapshots = holder . GetAllSnapshots ( ) . ToList ( ) ;
2553+ snapshots [ 0 ] . Changes [ PositionChangeTypes . CurrentValue ] = 999m ;
2554+
2555+ // Internal state should not be affected
2556+ holder . TryGetSnapshot ( "Portfolio1" , _secId1 , null , null , null , null , null , out var internal1 ) . AssertTrue ( ) ;
2557+ internal1 . Changes [ PositionChangeTypes . CurrentValue ] . AssertEqual ( 100m ) ;
2558+ }
2559+
2560+ [ TestMethod ]
2561+ public void Position_GetAllSnapshots_ReflectsUpdates ( )
2562+ {
2563+ var holder = new PositionSnapshotHolder ( ) ;
2564+
2565+ holder . Process ( new PositionChangeMessage
2566+ {
2567+ PortfolioName = "Portfolio1" ,
2568+ SecurityId = _secId1 ,
2569+ ServerTime = _now ,
2570+ } . TryAdd ( PositionChangeTypes . CurrentValue , 100m ) ) ;
2571+
2572+ // Update same position
2573+ holder . Process ( new PositionChangeMessage
2574+ {
2575+ PortfolioName = "Portfolio1" ,
2576+ SecurityId = _secId1 ,
2577+ ServerTime = _now . AddSeconds ( 1 ) ,
2578+ } . TryAdd ( PositionChangeTypes . CurrentValue , 150m )
2579+ . TryAdd ( PositionChangeTypes . BlockedValue , 10m ) ) ;
2580+
2581+ var snapshots = holder . GetAllSnapshots ( ) . ToList ( ) ;
2582+
2583+ snapshots . Count . AssertEqual ( 1 ) ;
2584+ snapshots [ 0 ] . Changes [ PositionChangeTypes . CurrentValue ] . AssertEqual ( 150m ) ;
2585+ snapshots [ 0 ] . Changes [ PositionChangeTypes . BlockedValue ] . AssertEqual ( 10m ) ;
2586+ }
2587+
2588+ [ TestMethod ]
2589+ public void Position_GetAllSnapshots_AfterReset_ReturnsEmpty ( )
2590+ {
2591+ var holder = new PositionSnapshotHolder ( ) ;
2592+
2593+ holder . Process ( new PositionChangeMessage
2594+ {
2595+ PortfolioName = "Portfolio1" ,
2596+ SecurityId = _secId1 ,
2597+ ServerTime = _now ,
2598+ } . TryAdd ( PositionChangeTypes . CurrentValue , 100m ) ) ;
2599+
2600+ holder . Process ( new PositionChangeMessage
2601+ {
2602+ PortfolioName = "Portfolio2" ,
2603+ SecurityId = _secId2 ,
2604+ ServerTime = _now ,
2605+ } . TryAdd ( PositionChangeTypes . CurrentValue , 200m ) ) ;
2606+
2607+ holder . ResetSnapshot ( null ) ;
2608+
2609+ holder . GetAllSnapshots ( ) . ToList ( ) . Count . AssertEqual ( 0 ) ;
2610+ }
2611+
2612+ [ TestMethod ]
2613+ public void Position_GetAllSnapshots_AfterPartialReset ( )
2614+ {
2615+ var holder = new PositionSnapshotHolder ( ) ;
2616+
2617+ holder . Process ( new PositionChangeMessage
2618+ {
2619+ PortfolioName = "Portfolio1" ,
2620+ SecurityId = _secId1 ,
2621+ ServerTime = _now ,
2622+ } . TryAdd ( PositionChangeTypes . CurrentValue , 100m ) ) ;
2623+
2624+ holder . Process ( new PositionChangeMessage
2625+ {
2626+ PortfolioName = "Portfolio2" ,
2627+ SecurityId = _secId2 ,
2628+ ServerTime = _now ,
2629+ } . TryAdd ( PositionChangeTypes . CurrentValue , 200m ) ) ;
2630+
2631+ holder . ResetSnapshot ( "Portfolio1" , _secId1 ) ;
2632+
2633+ var snapshots = holder . GetAllSnapshots ( ) . ToList ( ) ;
2634+ snapshots . Count . AssertEqual ( 1 ) ;
2635+ snapshots [ 0 ] . PortfolioName . AssertEqual ( "Portfolio2" ) ;
2636+ }
2637+
2638+ [ TestMethod ]
2639+ public void Position_GetAllSnapshots_MultipleSecuritiesPerPortfolio ( )
2640+ {
2641+ var holder = new PositionSnapshotHolder ( ) ;
2642+
2643+ holder . Process ( new PositionChangeMessage
2644+ {
2645+ PortfolioName = "Portfolio1" ,
2646+ SecurityId = _secId1 ,
2647+ ServerTime = _now ,
2648+ } . TryAdd ( PositionChangeTypes . CurrentValue , 100m ) ) ;
2649+
2650+ holder . Process ( new PositionChangeMessage
2651+ {
2652+ PortfolioName = "Portfolio1" ,
2653+ SecurityId = _secId2 ,
2654+ ServerTime = _now ,
2655+ } . TryAdd ( PositionChangeTypes . CurrentValue , 200m ) ) ;
2656+
2657+ var snapshots = holder . GetAllSnapshots ( ) . ToList ( ) ;
2658+ snapshots . Count . AssertEqual ( 2 ) ;
2659+
2660+ var byAapl = snapshots . First ( s => s . SecurityId == _secId1 ) ;
2661+ var byMsft = snapshots . First ( s => s . SecurityId == _secId2 ) ;
2662+
2663+ byAapl . Changes [ PositionChangeTypes . CurrentValue ] . AssertEqual ( 100m ) ;
2664+ byMsft . Changes [ PositionChangeTypes . CurrentValue ] . AssertEqual ( 200m ) ;
2665+ }
2666+
2667+ [ TestMethod ]
2668+ public Task Position_GetAllSnapshots_ConcurrentAccess_ThreadSafe ( )
2669+ {
2670+ var holder = new PositionSnapshotHolder ( ) ;
2671+ var token = CancellationToken ;
2672+
2673+ // Pre-populate
2674+ for ( var i = 0 ; i < 10 ; i ++ )
2675+ {
2676+ holder . Process ( new PositionChangeMessage
2677+ {
2678+ PortfolioName = $ "Portfolio{ i } ",
2679+ SecurityId = _secId1 ,
2680+ ServerTime = _now ,
2681+ } . TryAdd ( PositionChangeTypes . CurrentValue , i ) ) ;
2682+ }
2683+
2684+ var tasks = Enumerable . Range ( 0 , 100 ) . Select ( i => Task . Run ( ( ) =>
2685+ {
2686+ // Concurrent reads via GetAllSnapshots
2687+ var all = holder . GetAllSnapshots ( ) . ToList ( ) ;
2688+ ( all . Count >= 10 ) . AssertTrue ( ) ;
2689+
2690+ // Concurrent writes
2691+ holder . Process ( new PositionChangeMessage
2692+ {
2693+ PortfolioName = $ "Portfolio{ i % 10 } ",
2694+ SecurityId = _secId1 ,
2695+ ServerTime = _now . AddMilliseconds ( i ) ,
2696+ } . TryAdd ( PositionChangeTypes . CurrentValue , i * 10m ) ) ;
2697+ } , token ) ) . ToArray ( ) ;
2698+
2699+ return Task . WhenAll ( tasks ) ;
2700+ }
2701+
25002702 #endregion
25012703
25022704 #region Order Immutability and Behavior Tests
0 commit comments