summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs
blob: 9f4727dce4a43f63fb2e3409fe4035811f825704 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//-----------------------------------------------------------------------
// <copyright file="PerformanceTests.cs" company="Andrew Arnott">
//     Copyright (c) Andrew Arnott. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

namespace DotNetOpenAuth.Test.OpenId.Provider {
	using System;
	using System.Collections.Generic;
	using System.Diagnostics;
	using System.IO;
	using System.Linq;
	using System.Net;
	using System.Text;
	using DotNetOpenAuth.Messaging;
	using DotNetOpenAuth.Messaging.Reflection;
	using DotNetOpenAuth.OpenId;
	using DotNetOpenAuth.OpenId.ChannelElements;
	using DotNetOpenAuth.OpenId.Messages;
	using DotNetOpenAuth.OpenId.Provider;
	using Microsoft.VisualStudio.TestTools.UnitTesting;

	[TestClass]
	public class PerformanceTests : OpenIdTestBase {
		private const string SharedAssociationHandle = "handle";
		private static readonly TimeSpan TestRunTime = TimeSpan.FromSeconds(3);
		private OpenIdProvider provider;

		[TestInitialize]
		public override void SetUp() {
			base.SetUp();
			SuspendLogging();
			this.provider = CreateProvider();
		}

		[TestCleanup]
		public override void Cleanup() {
			ResumeLogging();
			base.Cleanup();
		}

		[TestMethod]
		public void AssociateDH() {
			var associateRequest = this.CreateAssociateRequest(OPUri);
			Stopwatch timer = new Stopwatch();
			timer.Start();
			int iterations;
			for (iterations = 0; timer.ElapsedMilliseconds < TestRunTime.TotalMilliseconds; iterations++) {
				IRequest request = this.provider.GetRequest(associateRequest);
				var response = this.provider.PrepareResponse(request);
				Assert.IsInstanceOfType(response.OriginalMessage, typeof(AssociateSuccessfulResponse));
			}
			timer.Stop();
			double executionsPerSecond = GetExecutionsPerSecond(iterations, timer);
			TestContext.WriteLine("Created {0} associations in {1}, or {2} per second.", iterations, timer.Elapsed, executionsPerSecond);
			Assert.IsTrue(executionsPerSecond >= 2, "Too slow ({0} >= 2 executions per second required.)", executionsPerSecond);
		}

		[TestMethod]
		public void AssociateClearText() {
			var associateRequest = this.CreateAssociateRequest(OPUriSsl); // SSL will cause a plaintext association
			Stopwatch timer = new Stopwatch();
			timer.Start();
			int iterations;
			for (iterations = 0; timer.ElapsedMilliseconds < TestRunTime.TotalMilliseconds; iterations++) {
				IRequest request = this.provider.GetRequest(associateRequest);
				var response = this.provider.PrepareResponse(request);
				Assert.IsInstanceOfType(response.OriginalMessage, typeof(AssociateSuccessfulResponse));
			}
			timer.Stop();
			double executionsPerSecond = GetExecutionsPerSecond(iterations, timer);
			TestContext.WriteLine("Created {0} associations in {1}, or {2} per second.", iterations, timer.Elapsed, executionsPerSecond);
			Assert.IsTrue(executionsPerSecond > 1000, "Too slow ({0} > 1000 executions per second required.)", executionsPerSecond);
		}

		[TestMethod]
		public void CheckIdSharedHmacSha1Association() {
			Protocol protocol = Protocol.Default;
			string assocType = protocol.Args.SignatureAlgorithm.HMAC_SHA1;
			double executionsPerSecond = this.ParameterizedCheckIdTest(protocol, assocType);
			TestContext.WriteLine("{0} executions per second.", executionsPerSecond);
			Assert.IsTrue(executionsPerSecond > 500, "Too slow ({0} > 500 executions per second required.)", executionsPerSecond);
		}

		[TestMethod]
		public void CheckIdSharedHmacSha256Association() {
			Protocol protocol = Protocol.Default;
			string assocType = protocol.Args.SignatureAlgorithm.HMAC_SHA256;
			double executionsPerSecond = this.ParameterizedCheckIdTest(protocol, assocType);
			TestContext.WriteLine("{0} executions per second.", executionsPerSecond);
			Assert.IsTrue(executionsPerSecond > 400, "Too slow ({0} > 400 executions per second required.)", executionsPerSecond);
		}

		private static double GetExecutionsPerSecond(int iterations, Stopwatch timer) {
			return (double)iterations / (timer.ElapsedMilliseconds / 1000);
		}

		private double ParameterizedCheckIdTest(Protocol protocol, string assocType) {
			Association assoc = HmacShaAssociation.Create(
				protocol,
				assocType,
				AssociationRelyingPartyType.Smart,
				this.provider.SecuritySettings);
			this.provider.AssociationStore.StoreAssociation(AssociationRelyingPartyType.Smart, assoc);
			var checkidRequest = this.CreateCheckIdRequest(true);
			Stopwatch timer = new Stopwatch();
			timer.Start();
			int iterations;
			for (iterations = 0; timer.ElapsedMilliseconds < TestRunTime.TotalMilliseconds; iterations++) {
				var request = (IAuthenticationRequest)this.provider.GetRequest(checkidRequest);
				request.IsAuthenticated = true;
				var response = this.provider.PrepareResponse(request);
				Assert.IsInstanceOfType(response.OriginalMessage, typeof(PositiveAssertionResponse));
			}
			timer.Stop();
			double executionsPerSecond = GetExecutionsPerSecond(iterations, timer);
			TestContext.WriteLine("Responded to {0} checkid messages in {1}; or {2} authentications per second.", iterations, timer.Elapsed, executionsPerSecond);
			return executionsPerSecond;
		}

		private HttpRequestInfo CreateAssociateRequest(Uri opEndpoint) {
			var rp = CreateRelyingParty(true);
			AssociateRequest associateMessage = AssociateRequest.Create(rp.SecuritySettings, new ProviderEndpointDescription(opEndpoint, Protocol.Default.Version));
			Channel rpChannel = rp.Channel;
			MemoryStream ms = new MemoryStream();
			StreamWriter mswriter = new StreamWriter(ms);
			mswriter.Write(MessagingUtilities.CreateQueryString(rpChannel.MessageDescriptions.GetAccessor(associateMessage)));
			mswriter.Flush();
			ms.Position = 0;
			var headers = new WebHeaderCollection();
			headers.Add(HttpRequestHeader.ContentType, Channel.HttpFormUrlEncoded);
			var httpRequest = new HttpRequestInfo("POST", opEndpoint, opEndpoint.PathAndQuery, headers, ms);
			return httpRequest;
		}

		private HttpRequestInfo CreateCheckIdRequest(bool sharedAssociation) {
			var rp = CreateRelyingParty(true);
			CheckIdRequest checkidMessage = new CheckIdRequest(
				Protocol.Default.Version,
				OPUri,
				DotNetOpenAuth.OpenId.RelyingParty.AuthenticationRequestMode.Setup);
			if (sharedAssociation) {
				checkidMessage.AssociationHandle = SharedAssociationHandle;
			}
			checkidMessage.ClaimedIdentifier = OPLocalIdentifiers[0];
			checkidMessage.LocalIdentifier = OPLocalIdentifiers[0];
			checkidMessage.Realm = RPRealmUri;
			checkidMessage.ReturnTo = RPUri;
			Channel rpChannel = rp.Channel;
			UriBuilder receiver = new UriBuilder(OPUri);
			receiver.Query = MessagingUtilities.CreateQueryString(rpChannel.MessageDescriptions.GetAccessor(checkidMessage));
			var headers = new WebHeaderCollection();
			var httpRequest = new HttpRequestInfo("GET", receiver.Uri, receiver.Uri.PathAndQuery, headers, null);
			return httpRequest;
		}
	}
}