Giter Site home page Giter Site logo

servicefabric.mocks's People

Contributors

abatishchev avatar ben-kotvis avatar chrismissal avatar dependabot[bot] avatar iamjustsam avatar invalid-commit avatar izzmo avatar jasper136 avatar jcwrequests avatar jjcollinge avatar john-garland avatar kgayo avatar lanfeust69 avatar likevi-msft avatar loekd avatar lordlezehaf avatar marusyk avatar mfmadsen avatar moswald avatar mrmint avatar pixeltitan avatar ralphcu avatar solita-jrutila avatar thiemenl avatar timhermann avatar vaclavk avatar vegar avatar waynemunro avatar whitwaldo avatar wonderpanda avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

servicefabric.mocks's Issues

Deadlock issue in Tests

I experienced deadlock issue in Tests specially when many tests sharing the Initialize I needed to synchronize the block to get it working :

Deadlock code to reproduce:

[TestInitialize]
public virtual async Task TestInitialize()
{
//await SyncLock.WaitAsync();
var partition = new MockStatefulServicePartition()
{
PartitionInfo = MockQueryPartitionFactory.CreateSingletonPartitonInfo(Guid.NewGuid())
};

        this.VariantSettings = new Mock<IVariantSettings>(MockBehavior.Loose);

        Func<StatefulServiceContext, IReliableStateManagerReplica2, TObj> serviceFactory =
            (context, stateManagerReplica) =>
            {
                // The mock library creates a new partition per instance; re-create the StatefulServiceContext with our singleton partition.
                context = MockStatefulServiceContextFactory.Create(
                    context.CodePackageActivationContext,
                    context.ServiceTypeName,
                    context.ServiceName,
                    partition.PartitionInfo.Id,
                    context.ReplicaId);

                TObj service = this.CreateService(context, stateManagerReplica);
                service.SetPartition(partition);

                return service;
            };

        this.ReplicaSet = new MockStatefulServiceReplicaSet<TObj>(serviceFactory);
        this.MockEventLogger = new Mock<IEventLogger>(MockBehavior.Loose);
        this.CacheClient = new Mock<ICacheClient>(MockBehavior.Strict);
        this.StoreResultCache = new Mock<IStoreResultCache<long>>(MockBehavior.Loose);

        MockCodePackageActivationContext cxt =
            (MockCodePackageActivationContext)this.ReplicaSet.CodePackageActivationContext;
        cxt.ConfigurationPackage = GetTestConfiguration();

        await this.ReplicaSet.AddReplicaAsync(ReplicaRole.Primary, 1);
        await this.ReplicaSet.AddReplicaAsync(ReplicaRole.ActiveSecondary, 2);

        this.Primary = this.ReplicaSet.Primary.ServiceInstance;
        this.Secondary = this.ReplicaSet.FirstActiveSecondary.ServiceInstance;
        //SyncLock.Release();
    }

Enhancement: Defaulting keyedcollections

Currently you have to create a context and then set the collection before you can add to it

      codePackageActivationContext.EndpointResourceDescriptions = keyedCollection;

if we added a default KeyedCollection like below we could add to it straight away.

       public class EndpointResourceDescriptionsKeyedCollection : KeyedCollection<string, EndpointResourceDescription>
        {
            protected override string GetKeyForItem(EndpointResourceDescription item)
            {
                return item.Name;
            }
        }

Happy to submit a PR but wanted to pass it first.

MockStatefulServiceReplica.DemoteToActiveSecondaryAsync() fails w/ OperationCanceledException when a stateful service overrides RunAsync(..) w/ proper cancellation token handling

I have a StatefulService that overrides RunAsync(CancellationToken token) with something like this:

protected override async Task RunAsync(CancellationToken cancellationToken)
{
    while (true)
    {
        cancellationToken.ThrowIfCancellationRequested();

        // Do some processing

        await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
    }
}

Microsoft documentation states the following:

If an OperationCanceledException escapes from RunAsync(CancellationToken) and Service Fabric runtime has requested cancellation by signaling cancellationToken passed to RunAsync(CancellationToken), Service Fabric runtime handles this exception and considers it as graceful completion of RunAsync(CancellationToken).

When MockStatefulServiceReplica.DemoteToActiveSecondaryAsync() is called on a replica with a service that overrides RunAsync(..) as shown above, it throws an OperationCanceledException with the message A task was canceled. and the operation fails. I think DemoteToActiveSecondaryAsync() should handle OperationCanceledExceptions and disregard them.

To reproduce, add the RunAsync(..) method above to StatefulServiceWithReplicaListener and run test method TestPromoteActiveSecondaryToPrimaryAsync() in the test project.

Mock actor service with unknown implementation

My actor service is accessing another actor service that belongs to a different application and is not in the same solution. The interface is known (referenced throw nuget package) but the implementation is not, so we cannot initiate it with its constructor, as it is done in the examples.
Is there a way to mock this accessed actor service with ServiceFabric.Mocks?

Mock and test multiple Stateful Services in one testrun

Hello,

I'm struggling with the ability to test multiple statefull services in my Unit tests. All tests work fine if they are executed seperately. But if the VSTS Test run Task executes them all together the task fails and shutdown unexpectedly. I think the issue resides on the ServiceFabric Mocks side since I'm using MockStatefulServiceContextFactory.Default. It doesn't help if I use the Create method of the factory for one of them. Could you please provide me some feedback about this or provide me with a workaround?

PS: we're running SF 2.5.216 so we are locked to 1.8.1 of the library.

Thanks!

Can I mock custom ActorService classes?

In your example you create a mocked actor using the following lines:

    Func<ActorService, ActorId, TActor> actorFactory = (service, actorId) => ...
     var svc = MockActorServiceFactory.CreateActorServiceForActor<TActor>(actorFactory);
     Actor = svc.Activate(id);

But how do I mock an actor which is using a custom ActorService? It´s initiated like this:

        ActorRuntime.RegisterActorAsync<CompanyActor>(
            (context, actorType) => new CustomActorService(context,
              actorType,
              (service, id) => new CompanyActor(service, id)))
          .GetAwaiter().GetResult();

How can I supply an instance or mock of my CustomActorService type?

Compatibility with Service Fabric SDK 2.7 preview

It appears VSTS 2017 hosted build agents recently had SF SDK 2.7 preview installed, breaking our Unit Tests that use ServiceFabric.Mocks:

System.TypeLoadException: Method 'Initialize' in type 'ServiceFabric.Mocks.MockActorStateProvider' from assembly 'ServiceFabric.Mocks, Version=1.8.1.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.

Any chance of creating a prerelease based on SDK 2.7 preview?
I am willing to create a PR, but some guidance may be needed since I am not very active in OS.

Need example of how to mock the StatefulServiceBase.Partition property for resolving partition information

Please add an example of how to create a mock for a StatefulSevice implementation that uses mocked partition information. The following code using reflection to try to set the Partition property does not work for the private setter for the StatefulServiceBase.Partition property because StatefulServicePartition does not implement IStatefulServicePartition (in 3.0.467)

		var partitionInformation = MockQueryPartitionFactory.CreateIntPartitonInfo(0, 3, Guid.NewGuid());

		Partition partition = MockQueryPartitionFactory.CreateStatefulPartition(partitionInformation, 1L, 1L, HealthState.Ok, ServicePartitionStatus.Ready, TimeSpan.MinValue, new Epoch());

		var statefulServiceContext = CreateMockStatefulServiceContext(mockConfigurationPackage, partitionInformation);

		this.sut = new MyStatefulService(
			context: statefulServiceContext
		);

		PropertyInfo propertyInfo = this.sut.GetType().GetProperty("Partition", BindingFlags.Instance | BindingFlags.NonPublic, null, null, new Type[0], null);

		propertyInfo.SetValue(this.sut, partition);

MoveNextAysnc Not returning false with empty result

var collection = await _stateManager.GetOrAddAsync<IReliableDictionary2<Guid, long>>("Collection");

        using (var tx = _stateManager.CreateTransaction())
        {
      
                var query = await collection.CreateEnumerableAsync(tx, key => (Something that has no matches), EnumerationMode.Unordered);

                var list = new List<Guid>();

This goes into infinite loop if the query returns an empty collection with a key value pair of null for both the key and the value.
while (await query.GetAsyncEnumerator().MoveNextAsync(new CancellationToken()))
list.Add(query.GetAsyncEnumerator().Current.Value.Id);

                await tx.CommitAsync();

Nuget package is missing strong name

Could you please add strong name to the nuget?

We are using ServiceFabric.Mocks internally at Microsoft, but unsigned libraries cause all kinds of inconveniences. Thank you!

Support of actor events

Hi Loek,

Do you see a way to mock the actor events?

I don't think it is possible because of the static class ActorProxyEventExtensions in Microsoft.ServiceFabric.Actors.Client?

When I call SubscribeAsync I get this exception:

System.ArgumentException: This method can only be called on ActorProxy.
Parameter name: actorProxy
at Microsoft.ServiceFabric.Actors.Client.ActorProxyEventExtensions.d__0`1.MoveNext()

Code to reproduce:

using System;
using System.Diagnostics;
using System.Fabric;
using System.Threading.Tasks;
using Microsoft.ServiceFabric.Actors;
using Microsoft.ServiceFabric.Actors.Client;
using Microsoft.ServiceFabric.Actors.Runtime;
using Microsoft.ServiceFabric.Data;
using Microsoft.ServiceFabric.Services.Remoting;
using Microsoft.ServiceFabric.Services.Runtime;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ServiceFabric.Mocks;

namespace Project.UnitTests
{

    [TestClass]
    public class ActorEventTests
    {
        protected static bool IsSuccess = false;
        public interface IExampleEvents : IActorEvents
        {
            void OnSuccess(string msg);
        }

        public interface IExampleActor : IActor, IActorEventPublisher<IExampleEvents>
        {
            Task ActorSomething(string msg);
        }

        public class ExampleActorMock : Actor, IExampleActor
        {
            public ExampleActorMock(ActorService actorService, ActorId actorId) : base(actorService, actorId)
            {
            }

            public Task ActorSomething(string msg)
            {
                Debug.WriteLine("Actor:"+msg);
                var ev = GetEvent<IExampleEvents>();
                ev.OnSuccess(msg);
                return Task.CompletedTask;
            }
        }

        public interface IExampleService : IService
        {
            Task DoSomething(Guid id, string msg);
        }


        public class ExampleClient : StatefulService, IExampleService, IExampleEvents
        {
            protected IActorProxyFactory ActorProxy;
            public ExampleClient(StatefulServiceContext serviceContext) : base(serviceContext)
            {
            }

            public ExampleClient(StatefulServiceContext serviceContext, IReliableStateManagerReplica reliableStateManagerReplica, IActorProxyFactory actorProxy) : base(serviceContext, reliableStateManagerReplica)
            {
                ActorProxy = actorProxy;
            }

            public async Task DoSomething(Guid id, string msg)
            {
                var proxy = ActorProxy.CreateActorProxy<IExampleActor>(new ActorId(id));
                await proxy.SubscribeAsync<IExampleEvents>(this);
                await proxy.ActorSomething(msg);
            }

            public void OnSuccess(string msg)
            {
                Debug.WriteLine("Service: "+msg);
                IsSuccess = true;
            }
        }


        [TestMethod]
        public async Task TestSubscribeAsync()
        {
            var guid = Guid.NewGuid();
            var id = new ActorId(guid);
            Func<ActorService, ActorId, ActorBase> factory = (service, actorId) => new ExampleActorMock(service, actorId);
            var svc = MockActorServiceFactory.CreateActorServiceForActor<ExampleActorMock>(factory);
            var actor = svc.Activate(id);

            var context = MockStatefulServiceContextFactory.Default;
            var stateManager = new MockReliableStateManager();
            var mockProxyFactory = new MockActorProxyFactory();
            mockProxyFactory.RegisterActor(actor);

            var exampleService = new ExampleClient(context, stateManager, mockProxyFactory);
            await exampleService.DoSomething(guid, "message text");

            Assert.IsTrue(IsSuccess);
        }
    }
}

SetStateAsync in ActorStateManager should not check for type

When I want to mock the following code in an actor:

await StateManager.SetStateAsync(stateName, string.Empty);
await StateManager.SetStateAsync(stateName, 5);
await StateManager.SetStateAsync(stateName, DateTimeOffset.UtcNow);

It fails with an InvalidCastException trying to cast 5 to string. It is actually valid code when running under Service Fabric itself.

If you agree, I can create a PR to fix this.

MyStatefulActorTests.CreateActor() in example/tests is confusing

The code for CreateActor() first configures an actor service with a factory method to create the actor (which new's up an instance of the actor class with the provided parameters) and thereafter it also new's up a new instance of the actor class, which it returns.

The reason for the two instantiation statements is not obvious. Very likely it is because I do not understand well enough the SF object lifetime management but my first impression is that I am confused regarding what the role of each new statement actually is. When is my actor created? Why does the other statement exist?

Some comments in the relevant code would be desirable, clarifying what the responsibilities of this code are in a mocking scenario and what the actual object flow is.

Create Replica never returns if RunAsync is endless

In your Tests project, you have the following Test:

      [TestMethod]
       public async Task TestServiceState_InMemoryState_PromoteActiveSecondary()
       {
           var replicaSet = new MockStatefulServiceReplicaSet<MyStatefulService>(CreateStatefulService, CreateStateManagerReplica);
           await replicaSet.AddReplicaAsync(ReplicaRole.Primary, 1);
           await replicaSet.AddReplicaAsync(ReplicaRole.ActiveSecondary, 2);
           await replicaSet.AddReplicaAsync(ReplicaRole.ActiveSecondary, 3);

           const string stateName = "test";
           var payload = new Payload(StatePayload);

           //insert data
           await replicaSet.Primary.ServiceInstance.InsertAsync(stateName, payload);
           //promote one of the secondaries to primary
           await replicaSet.PromoteActiveSecondaryToPrimaryAsync(2);
           //get data
           var payloads = (await replicaSet.Primary.ServiceInstance.GetPayloadsAsync()).ToList();

           //data should match what was inserted against the primary
           Assert.IsTrue(payloads.Count == 1);
           Assert.IsTrue(payloads[0].Content == payload.Content);

           //the primary should not have any in-memory state
           var payloadsFromOldPrimary = await replicaSet[1].ServiceInstance.GetPayloadsAsync();
           Assert.IsTrue(!payloadsFromOldPrimary.Any());
       }

The problem is this test is not working, if service is executing endless loop in RunAsync, let's say for background task.

Some details:

AddReplicaAsync will wait for CreateAsync:

        public async Task AddReplicaAsync(ReplicaRole role, long? replicaId = null, int activationDelayMs = 0)
        {
            var serviceContext = MockStatefulServiceContextFactory.Create(CodePackageActivationContext, ServiceTypeName, ServiceUri, Guid.NewGuid(), replicaId ?? _random.Next());
            var stateManager = _stateManagerFactory(serviceContext, _reliableStates);
            var replica = new MockStatefulServiceReplica<TStatefulService>(_serviceFactory, serviceContext, stateManager);
            await replica.CreateAsync(role);
            _replicas.Add(replica);
        }

and then CreateAsync will wait for RunAsync which will never return

        public async Task CreateAsync(ReplicaRole role)
        {
            await OpenAsync(ReplicaOpenMode.New);

            if (role == ReplicaRole.Primary)
            {
                await OpenServiceReplicaListeners();
                await ChangeRoleAsync(role);
                await RunAsync();
            }
            else
                await ChangeRoleAsync(role);
        }

My suggestion is to wait for RunAnync to be completed in CreateAsync. Thank you.

No Servicefabric Mock package available for version 3.3.622

Hi ,
There is no package available which points to the Service fabric packages for version 3.3.622
When using ServiceFabric.Mocks to version 3.4.3 which should support all version of service fabric greated than 3.2.187, I am getting error "System.TypeLoadException : Method 'CreateNonIServiceProxy' in type 'ServiceFabric.Mocks.MockServiceProxyFactory' from assembly 'ServiceFabric.Mocks, Version=3.4.3.0, Culture=neutral, PublicKeyToken=c8a3b3cecf8974ee' does not have an implementation"
Version 3.4.5 of the Mocks supports 3.3.624, which seems to have been deprecated by microsoft. Could you suggest which version of Mock should we use if we are using version 3.3.622 for service fabric

How to add parameter?

My stateless service receives a parameter from the the ApplicationManifest.xml and it is consumed at the constructor of the service.

I found

    public class MockStatelessServiceContextFactory
    {
        public const string ServiceTypeName = "MockServiceType";
        public const string ServiceName = "fabric:/MockApp/MockStatefulService";

        public MockStatelessServiceContextFactory();

        public static StatelessServiceContext Default { get; }

        public static StatelessServiceContext Create(ICodePackageActivationContext codePackageActivationContext, string serviceTypeName, Uri serviceName, Guid partitionId, long instanceId);
    }

but I haven't seen any sample on how to use this and more important, how to set the parameter required for my service to start.

Can you help?

State Manager Rebuild Events while Testing Service Moves

This issue only occurs while testing service moves using the new MockStatefulServiceReplicaSet.

When a stateful service primary moves to a new replica that was not originally part of the replica set, the rebuild event is triggered. This is the behavior we observed while our service is running on the cluster. However, this condition is not documented very thoroughly on the ASF docs.

Currently, I do not believe rebuild events are being emitted from the MockReliableStateManager under this condition. This is because we have to share the same instance of the MockReliableStateManager for all replicas to simulate the replicas' state keeping in state with each other. The trade off is the MockReliableStateManager cant track the role for the specific replica hosting its instance. We would need this to be able to know when the replica is transitioning from Unknown -> Idle/Active Secondary. This transition is when the state manager's rebuild event is triggered.

The rebuild i believe is to allow a new replica to subscribe to all reliable states currently being managed by the replica set as it comes into the fold. Without this, the new node will not be able to subscribe to events like DictionaryChanged.

I believe the first part to allowing the simulation of this event is to allow for different State manager instances to be inserted into each replica. This will allow the state manager to observe the role of its owning replica. That will then allow it to trigger events during the role transitions.

The second part of the solution is how to keep the State manager instances in sync with each other. To do this I believe there are two options. First, we inject into the state manager or the mock reliable states a singleton dictionary so that all the state managers save their data to a single location. The drawback to this solution is it makes the creation of the MockReliableStateManager much more complex. It puts more burden on the consumers of this package. The other option would be to add some sort of eventing between the state manager instances to simulate them staying in sync.

I wanted to get some input on whether to use injection of single dictionaries or events before i push a PR with a change to support this.

Nuget package is missing strong name

Could you please add strong name to the nuget? We are using ServiceFabric.Mocks internally at Microsoft, but unsigned libraries cause all kinds of inconveniences. Thank you!

TryDequeueAsync differs from ServiceFabric implementation for timeout=0

MockReliableConcurrentQueue.TryDequeueAsync does not return items if the supplied timeout is TimeSpan.Zero.

The ServiceFabric ReliableConcurrentQueue does allow a timeout of zero to return items if they exist (without blocking the queue to see if any arrive).

I think this is easily fixed on the following line, changing milliseconds > 0 to milliseconds >= 0, which would allow a supplied timeout of 0 at least one iteration of the for loop.

for (long milliseconds = totalMilliseconds; milliseconds > 0; milliseconds = totalMilliseconds - sw.ElapsedMilliseconds)

'ServiceFabric.Mocks.MockStatefulServiceContextFactory' threw an exception.

Hi,

I am trying to do some very basic unit tests around my SchedulerActor but I cannot get that working.

    private static SchedulerActor CreateActor(ActorId id)
    {
      Func<ActorService, ActorId, ActorBase> actorFactory = (service, actorId) => new SchedulerActor(service, id);
      var svc = MockActorServiceFactory.CreateActorServiceForActor<SchedulerActor>(actorFactory);
      var actor = svc.Activate(id);
      return actor;
    }

The exception message:

System.TypeInitializationException : The type initializer for 'ServiceFabric.Mocks.MockStatefulServiceContextFactory' threw an exception.
  ----> System.TypeLoadException : Method 'ReportApplicationHealth' in type 'ServiceFabric.Mocks.MockCodePackageActivationContext' from assembly 'ServiceFabric.Mocks, Version=2.1.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
   at ServiceFabric.Mocks.MockActorServiceFactory.CreateActorServiceForActor[TActor](Func`3 actorFactory, IActorStateProvider actorStateProvider, StatefulServiceContext context, ActorServiceSettings settings)

failure when promoting and demoting replicas to different roles

We'd like to be able to test our logic that kicks in during SF role transitions.
The following sequence of operations yields an error though:
this.ReplicaSet = new MockStatefulServiceReplicaSet(serviceFactory);

await this.ReplicaSet.AddReplicaAsync(ReplicaRole.Primary, 1);
await this.ReplicaSet.AddReplicaAsync(ReplicaRole.ActiveSecondary, 2);
...
await this.ReplicaSet.PromoteActiveSecondaryToPrimaryAsync(2);

When added, the last step fails with the following error:
System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.ServiceFabric.FabricTransport, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies.

When FabricTransport dll reference is added, it fails with the following error:
System.Runtime.InteropServices.COMException: No such host is known. (Exception from HRESULT: 0x80072AF9).

That is, it seems to actually try and use the real transport, not a mock one.

What is the way to enable promotion and demotion of replicas to different roles using mock library?

Thanks,
-Ayse

Incorrect implementation of SetAsync in TransactedConcurrentDictionary

Per the documentation of IReliableDictionary
Summary:
Adds a key/value pair to the Reliable Dictionary if the key does not already exist, or updates a key/value pair in the Reliable Dictionary if the key already exists.

However, looks like the mock is implemented to throw if the key does not exist, this deviates from the Service fabric implementation

Could not load type 'Microsoft.ServiceFabric.Data.Collections.IReliableConcurrentQueue`

After upgrading the fabric version and this NuGet package, I am getting the following error in VSTS builds:

Could not load type 'Microsoft.ServiceFabric.Data.Collections.IReliableConcurrentQueue1' from assembly 'Microsoft.ServiceFabric.Data.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. Stack Trace: at ServiceFabric.Mocks.MockReliableStateManager.<>c__DisplayClass25_01.b__0(Uri collectionName)
at System.Collections.Concurrent.ConcurrentDictionary2.GetOrAdd(TKey key, Func2 valueFactory)
at ServiceFabric.Mocks.MockReliableStateManager.GetOrAddAsync[T](ITransaction tx, String name)

It runs fine locally, so I am just looking for any pointers on what could be wrong in the hosted build.

Needs to be updated to account for 2.8 SDK

At a minimum, classes that implement IActorStateProvider need to account for the new IStateProviderReplica2 interface, and those that implement IServiceProxy need to provide ServicePartitionClient2 endpoint. Using statements related to remoting also need to be changed to include V1 specification.

A deeper assessment of V1 vs V2 probably also needs to happen to determine if the Mocks need to be extended or split to handle the new communication tooling.

TimeoutException during IReliableDictionary.TryUpdateAsync

It seems to be a timing thing, and maybe more than one call is trying to access the same entry at the same time, but they are all wrapped in transactions so I don't see why this should happen:

System.TimeoutException: The operation has timed out.
at ServiceFabric.Mocks.ReliableCollections.Lock1.<Acquire>d__11.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at ServiceFabric.Mocks.ReliableCollections.LockManager2.<AcquireLock>d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at ServiceFabric.Mocks.ReliableCollections.TransactedConcurrentDictionary`2.d__26.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
further stack trace redacted

MockReliableQueue - transaction abort replaces items in reversed order

(reported through nuget)
We're using Service Fabric mocks heavily for our unit testing of Service Fabric reliable services. Before all, thank you and your team for this library.

I'd like to report an issue with ServiceFabric.Mocks.ReliableCollections.MockReliableQueue though. The implementation behaves in a way that breaks IReliableQueue contract in multiple ways. Let me explain with an example.

Say a queue has the items: A B C D E If you: await queue.TryDequeueAsync(tx); await queue.TryDequeueAsync(tx); await queue.TryDequeueAsync(tx); tx.Abort(); you will end up with the following state in the queue: D E C B A instead of A B C D E

It enqueues the dequeued items that were aborted back into the queue, that basically puts them to the tail instead of the head
It reversed the order while doing so
This behavior greatly reduces the usability of MockReliableQueue. Can you please let me know whether you would have this fixed or not. If so, how long would it take to get the fix?

Transactions support for ReliableQueue

Thanks for this very nice library!

I'm writing a unit test which uses the MockReliableQueue. I expect that the message is still in the queue once the CommitAsync on the transaction is not called. But the message is removed.

Are there any plans to support transactions?

var queue = await StateManager.GetOrAddAsync<IReliableQueue<Message>>("QueueName");
using (var tx = StateManager.CreateTransaction())
{
   var res = await queue.TryDequeueAsync(tx);    
   throw new Exception("Something went wrong");
   // Remove from queue
   await tx.CommitAsync();
}

Testing RunAsync in StatefulService

When testing a StatefulService with your library, how do you make the RunAsync method start? I have a processing loop in RunAsync that consumes from a queue which I need to run and test its behavior.

Is there a method to call on the StatefulService/Context, or something similiar?

var context = MockStatefulServiceContextFactory.Default;
_stateManager = new MockReliableStateManager();
_mockThing = new MockThing{};
var service = new TenantDispatcherService(context, _stateManager, _mockThing);

service.??????
context.?????

Allowing Overrides in Classes

I am wanting to allow for the use of test spies in this framework so I can more easily make sure transactions are getting applied. On our team, a team member might forget to to commit a transaction on a ReliableDictionary<T> and this override of a base test could help locate that issue faster.

So, what I'm wanting to commit a PR of something like below. Thoughts?

ServiceFabric.Mocks Update

    public class MockReliableStateManager : IReliableStateManagerReplica2
    {
        // ..begin methods

        public virtual void Abort()
        {
        }

        public virtual Task BackupAsync(Func<BackupInfo, CancellationToken, Task<bool>> backupCallback)
        {
            return BackupAsync(BackupOption.Full, TimeSpan.MaxValue, CancellationToken.None, backupCallback);
        }

        public virtual Task BackupAsync(BackupOption option, TimeSpan timeout, CancellationToken cancellationToken, Func<BackupInfo, CancellationToken, Task<bool>> backupCallback)
        {
            string stateBin = Path.Combine(Path.GetTempPath(), "state.bin");
            using (var fs = File.Create(stateBin))
            {
                var formatter = new BinaryFormatter();
                formatter.Serialize(fs, _store);
            }
            var info = new BackupInfo(Path.GetDirectoryName(stateBin), option, new BackupInfo.BackupVersion());
            return backupCallback(info, CancellationToken.None);
        }

        public virtual Task ChangeRoleAsync(ReplicaRole newRole, CancellationToken cancellationToken)
        {
            ReplicaRole = newRole;
            return Task.FromResult(true);
        }

        public virtual Task ClearAsync(ITransaction tx)
        {
            return ClearAsync();
        }

        public virtual Task ClearAsync()
        {
            _store.Clear();
            return Task.FromResult(true);
        }

        public virtual Task CloseAsync(CancellationToken cancellationToken)
        {
            return Task.FromResult(true);
        }

        public virtual ITransaction CreateTransaction()
        {
            return new MockTransaction();
        }

        // other methods..
}

User Code

public class MockReliableStateManagerSpy : MockReliableStateManager
{
   public MockTransactionSpy Transaction { get; private set; }

   public bool TransanctionIsCreated => Transaction != null;

   public bool TransactionIsCommitted => Transaction.IsCommitted;

   public new ITransaction CreateTransaction()
   {
      Transaction = new MockTransactionSpy();
      return Transaction;
   }
}

public class MockTransactionSpy : MockTransaction
{
   public bool IsCommitted { get; private set; }

   private new Task CommitAsync()
   {
      IsCommitted = true;
      return base.CommitAsync();
   }
}

NRE from RegisterReminderAsync()

I have an actor that is being tested via a mocked ActorService. When it tries to register a reminder, it encounters a NullReferenceException coming (based on stack trace information) from within the stateful storage system.

System.NullReferenceException : Object reference not set to an instance of an object.
      Stack Trace:
           at Microsoft.ServiceFabric.Actors.Runtime.KvsActorStateProvider.<AddOrUpdateReminderAsync>d__4c.MoveNext()
        --- End of stack trace from previous location where exception was thrown ---
           at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
           at Microsoft.ServiceFabric.Actors.Runtime.ActorStateProviderHelper.<>c__DisplayClass1.<<ExecuteWithRetriesAsync>b__0>d__3.MoveNext()
        --- End of stack trace from previous location where exception was thrown ---
           at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
           at Microsoft.ServiceFabric.Actors.Runtime.ActorStateProviderHelper.<ExecuteWithRetriesAsync>d__6`1.MoveNext()
        --- End of stack trace from previous location where exception was thrown ---
           at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
           at Microsoft.ServiceFabric.Actors.Runtime.MockActorManager.<RegisterOrUpdateReminderAsync>d__5.MoveNext()
        --- End of stack trace from previous location where exception was thrown ---
           at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
           at Microsoft.ServiceFabric.Actors.Runtime.ActorBase.<RegisterReminderAsync>d__3.MoveNext()
        --- End of stack trace from previous location where exception was thrown ---
           at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
        FileThingy\FileThingy.cs(109,0): at FileThingy.FileThingy.<TakeLeaseAsync>d__13.MoveNext()
        --- End of stack trace from previous location where exception was thrown ---
           at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
        Tests\FileThingyTests.cs(51,0): at Tests.FileThingyTests.<TakeLease_TwiceInARow_RemembersLongestLease>d__3.MoveNext()
        --- End of stack trace from previous location where exception was thrown ---
           at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
        --- End of stack trace from previous location where exception was thrown ---
           at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
        --- End of stack trace from previous location where exception was thrown ---
           at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
           at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

Using SF SDK 2.3.301 and ServiceFabric.Mocks 0.9.4.

This is the call that fails:

await RegisterReminderAsync(CleanupReminderName, null, durationFromNow, CleanupRetryInterval);

There is no actor state saved before this reminder registration call.

CreateActorServiceForActor does not mock state provider

When creating a stateful actor an exception is thrown because the state provider is not mocked. First call to CreateActor in my test case throws an exception here:

    System.Fabric.FabricRuntime.NativeFabricRuntimeFactory.GetCodePackageActivationContextHelper()  C#
    System.Fabric.Interop.Utility.WrapNativeSyncInvoke<System.__Canon>(func, functionTag, functionArgs) C#
    System.Fabric.Interop.Utility.RunInMTA<System.Fabric.CodePackageActivationContext>(func)    C#
    Microsoft.ServiceFabric.Actors.Runtime.ActorStateProviderHelper.GetActorStateProviderOverride() C#
    Microsoft.ServiceFabric.Actors.Runtime.ActorStateProviderHelper.CreateDefaultStateProvider(actorTypeInfo)   C#
    Microsoft.ServiceFabric.Actors.Runtime.ActorService.ActorService(context, actorTypeInfo, actorFactory, stateManagerFactory, stateProvider, settings)    C#
    ServiceFabric.Mocks.MockActorServiceFactory.CreateActorServiceForActor<Actors.Jobs.JobActor>(actorFactory)  C#
    Tests.Class1.CreateActor<Actors.Jobs.JobActor>(id)  C#
    Tests.Class1.CreateActor<Actors.Jobs.JobActor>(id)  C#
    Tests.Class1.Test() C#

Test class used:

    public class Class1
    {

        internal static TActor CreateActor<TActor>(Guid id) where TActor : Actor
        {
            return CreateActor<TActor>(new ActorId(id));
        }

        internal static TActor CreateActor<TActor>(ActorId id) where TActor : Actor
        {
            Func<ActorService, ActorId, ActorBase> actorFactory = (service, actorId) => (ActorBase)Activator.CreateInstance(typeof(TActor), service, actorId);
            var svc = MockActorServiceFactory.CreateActorServiceForActor<TActor>(actorFactory);
            return actorFactory(svc, id) as TActor;
        }

        [Fact]
        public async Task Test()
        {
            //  new job
            var job = CreateActor<JobActor>(Guid.NewGuid()) as IJobActor;

            // new device
            var device = CreateActor<DeviceActor>(Guid.NewGuid());

            await job.Create(new Guid[] { Guid.NewGuid() }, new Guid[] { Guid.NewGuid() }, new IDeviceActor[] { device });

            //  new action
            var action = CreateActor<JobActionActor>(Guid.NewGuid()) as IJobActionActor;

            await action.Create(JobActionType.Download, new Uri[] { new Uri("http://test.net") });
            await job.AddAction(action);

            await job.Run();
        }
    }

Issue with Mock Actor with CreateActorProxyFactory

I have started using ServiceFabric.Mocks for mocking, I am testing a scenario where ACtor is called from a service, more specifically an API, which is .net core stateless service. Actor is being called from controller and I am writing unit tests for controller, I am mocking the Actor using mockActorProxyFactory, in the tests i get a correct instance of mockActorProxyFactory with all mocked data, but when in controller it tries to createActor proxy it returns always null
ActorProxyFactory.CreateActorProxy(new ActorId(Id)) This line is always returning me null.
do we have a any such issue which is known, I am using 3.4.5 version of mocks and 3.4.624 version of service fabric.
Any help will be appreciated!
I am using the details given in link for Communication between Actors and Services
https://loekd.wordpress.com/2018/03/05/unit-testing-in-azure-service-fabric/

MockActorStateManager methods should throw exceptions

as expample, the AddStateAsync method in MockActorStateManager does not throw an InvalidOperationException if a state (key) already exists (in the dictionary). same for GetStateAsync.

https://github.com/loekd/ServiceFabric.Mocks/blob/master/src/ServiceFabric.Mocks/MockActorStateManager.cs#L26

can this be changed to throw the exceptions according to the real implementation?

https://github.com/Azure/service-fabric-services-and-actors-dotnet/blob/develop/src/Microsoft.ServiceFabric.Actors/Runtime/ActorStateManager.cs#L32

OnPreActorMethodAsync not called

I have a unit test on a method that requires code in OnPreActorMethodAsync to be called to work correctly. Is there a way to invoke actor instance methods in a way that this method is executed too?

GetReminder does not find mocked reminder of MockActorStateProvider

when i want to verify my actor is removing an existing reminder, i first need to call
GetReminder( String reminderName )
to obtain the IActorReminder by name. unfortunately this throws a ReminderNotFoundException.

as far as i can see, this method does not even touch the mock state provider.

if this is the wrong approch to test unregistering a reminder, what would be the right way?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.