public async Task GetHostIdAsync_ReturnsExpectedResult() { // ensure that the below job method is discovered and this test // assembly is used to generate the ID var type = GetType(); var firstJobMethod = FunctionIndexer.GetJobMethods(type).FirstOrDefault(); Assert.NotNull(firstJobMethod); var mockTypeLocator = new Mock <ITypeLocator>(MockBehavior.Strict); mockTypeLocator.Setup(p => p.GetTypes()).Returns(new Type[] { type }); var idProvider = new DefaultHostIdProvider(mockTypeLocator.Object); // as long as this test assembly name stays the same, the ID // computed should remain static. If this test is failing // it likely means we've changed the ID computation algorithm // which would be a BREAKING CHANGE string expected = "be6b3849f12290e0f182b27aa6f10fff"; var id = await idProvider.GetHostIdAsync(CancellationToken.None); Assert.Equal(expected, id); // ensure the same ID is returned each time mockTypeLocator = new Mock <ITypeLocator>(MockBehavior.Strict); mockTypeLocator.Setup(p => p.GetTypes()).Returns(new Type[] { type }); idProvider = new DefaultHostIdProvider(mockTypeLocator.Object); Assert.Equal(expected, await idProvider.GetHostIdAsync(CancellationToken.None)); // ensure once the ID is computed, a cached result is returned Assert.Equal(expected, await idProvider.GetHostIdAsync(CancellationToken.None)); Assert.Equal(expected, await idProvider.GetHostIdAsync(CancellationToken.None)); mockTypeLocator.Verify(p => p.GetTypes(), Times.Once); }
public async Task GetHostIdAsync_NoJobMethodsFound_ReturnsExpectedResult() { // pick a type that returns no job methods var type = typeof(FunctionNameAttribute); var firstJobMethod = FunctionIndexer.GetJobMethods(type).FirstOrDefault(); Assert.Null(firstJobMethod); var mockTypeLocator = new Mock <ITypeLocator>(MockBehavior.Strict); mockTypeLocator.Setup(p => p.GetTypes()).Returns(new Type[] { type }); var idProvider = new DefaultHostIdProvider(mockTypeLocator.Object); // as long as this test assembly name stays the same, the ID // computed should remain static. If this test is failing // it likely means we've changed the ID computation algorithm // which would be a BREAKING CHANGE string expected = "943b1888c56ce8f0c96b2e66e1c74a7e"; var id = await idProvider.GetHostIdAsync(CancellationToken.None); Assert.Equal(expected, id); // ensure the same ID is returned each time mockTypeLocator = new Mock <ITypeLocator>(MockBehavior.Strict); mockTypeLocator.Setup(p => p.GetTypes()).Returns(new Type[] { type }); idProvider = new DefaultHostIdProvider(mockTypeLocator.Object); Assert.Equal(expected, await idProvider.GetHostIdAsync(CancellationToken.None)); }
private string ComputeHostId() { // Search through all types for the first job method. // The reason we have to do this rather than attempt to use the entry assembly // (Assembly.GetEntryAssembly) is because that doesn't work for WebApps, and the // SDK supports both WebApp and Console app hosts. MethodInfo firstJobMethod = null; foreach (var type in _typeLocator.GetTypes()) { firstJobMethod = FunctionIndexer.GetJobMethods(type).FirstOrDefault(); if (firstJobMethod != null) { break; } } // Compute hash and map to Guid // If the job host doesn't yet have any job methods (e.g. it's a new project) // then a default ID is generated string hostName = firstJobMethod?.DeclaringType.Assembly.FullName ?? "Unknown"; Guid id; using (var md5 = MD5.Create()) { var hash = md5.ComputeHash(Encoding.UTF8.GetBytes(hostName)); id = new Guid(hash); } return(id.ToString("N")); }