• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

loresoft / FluentRest / 8851497268

26 Apr 2024 04:40PM UTC coverage: 57.33% (+5.1%) from 52.206%
8851497268

push

github

pwelter34
Update Issue.cs

270 of 604 branches covered (44.7%)

Branch coverage included in aggregate %.

825 of 1306 relevant lines covered (63.17%)

69.17 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

59.04
/src/FluentRest.Fake/FileMessageStore.cs
1
using System;
2
using System.IO;
3
using System.Net;
4
using System.Net.Http;
5
using System.Text;
6
using System.Text.Json;
7
using System.Text.Json.Serialization;
8
using System.Threading.Tasks;
9

10
namespace FluentRest.Fake;
11

12
/// <summary>
13
/// A file based fake message store.  The fake response messages are saved and loaded from the StorePath directory.
14
/// </summary>
15
public class FileMessageStore : FakeMessageStore
16
{
17
    /// <summary>
18
    /// Initializes a new instance of the <see cref="FileMessageStore"/> class.
19
    /// </summary>
20
    /// <param name="storePath">The store path.</param>
21
    public FileMessageStore(string storePath)
3✔
22
    {
23
        StorePath = storePath;
3✔
24
    }
3✔
25

26
    private const int _bufferSize = 4096;
27

28
    /// <summary>
29
    /// Gets or sets the directory location to store response files.
30
    /// </summary>
31
    /// <value>
32
    /// The directory location to store response files.
33
    /// </value>
34
    public string StorePath { get; set; }
6✔
35

36
    /// <summary>
37
    /// Saves the specified HTTP <paramref name="response" /> to the message store as an asynchronous operation.
38
    /// </summary>
39
    /// <param name="request">The HTTP request message that was sent.</param>
40
    /// <param name="response">The HTTP response messsage to save.</param>
41
    /// <returns>
42
    /// The task object representing the asynchronous operation.
43
    /// </returns>
44
    public override async Task SaveAsync(HttpRequestMessage request, HttpResponseMessage response)
45
    {
46
        GetPaths(request, out var responsePath, out var contentPath);
×
47

48
        await SaveContent(response, contentPath).ConfigureAwait(false);
×
49
        await SaveResponse(response, responsePath).ConfigureAwait(false);
×
50
    }
×
51

52
    /// <summary>
53
    /// Loads an HTTP fake response message for the specified HTTP <paramref name="request" /> as an asynchronous operation.
54
    /// </summary>
55
    /// <param name="request">The HTTP request message to load response for.</param>
56
    /// <returns>
57
    /// The task object representing the asynchronous operation.
58
    /// </returns>
59
    public override async Task<HttpResponseMessage> LoadAsync(HttpRequestMessage request)
60
    {
61
        GetPaths(request, out var responsePath, out var contentPath);
3✔
62

63
        if (!File.Exists(responsePath))
3!
64
        {
65
            var httpResponseMessage = new HttpResponseMessage(HttpStatusCode.NotFound);
×
66
            httpResponseMessage.RequestMessage = request;
×
67
            httpResponseMessage.ReasonPhrase = $"Response file '{responsePath}' not found";
×
68
            return httpResponseMessage;
×
69
        }
70

71
        var httpContent = LoadContent(contentPath);
3✔
72

73
        var httpResponse = await LoadResponse(httpContent, responsePath).ConfigureAwait(false);
3✔
74
        httpResponse.RequestMessage = request;
3✔
75

76
        return httpResponse;
3✔
77
    }
3✔
78

79

80
    private async Task SaveContent(HttpResponseMessage response, string contentPath)
81
    {
82
        // don't save content if not success
83
        if (!response.IsSuccessStatusCode || response.Content == null || response.StatusCode == HttpStatusCode.NoContent)
×
84
            return;
×
85

86
        var contents = await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
×
87
        File.WriteAllBytes(contentPath, contents);
×
88
    }
×
89

90
    private Task SaveResponse(HttpResponseMessage response, string responsePath)
91
    {
92
        return Task.Factory.StartNew(() =>
×
93
        {
×
94
            var fakeResponse = Convert(response);
×
95
            var options = new JsonSerializerOptions { WriteIndented = true };
×
96
            var json = JsonSerializer.Serialize(fakeResponse, options);
×
97
            File.WriteAllText(responsePath, json);
×
98
        });
×
99
    }
100

101

102
    private HttpContent LoadContent(string contentPath)
103
    {
104
        if (!File.Exists(contentPath))
3!
105
            return null;
×
106

107
        // need to leave stream open
108
        var fileStream = new FileStream(contentPath, FileMode.Open, FileAccess.Read, FileShare.Read, _bufferSize);
3✔
109
        var httpContent = new StreamContent(fileStream, _bufferSize);
3✔
110

111
        return httpContent;
3✔
112
    }
113

114
    private async Task<HttpResponseMessage> LoadResponse(HttpContent httpContent, string responsePath)
115
    {
116
        FakeResponseMessage fakeResponse;
117
        using (var reader = File.OpenRead(responsePath))
3✔
118
            fakeResponse = await JsonSerializer.DeserializeAsync<FakeResponseMessage>(reader);
3✔
119

120
        var httpResponse = Convert(fakeResponse);
3✔
121
        if (httpContent == null)
3!
122
            return httpResponse;
×
123

124
        // copy headers
125
        foreach (var header in fakeResponse.ResponseHeaders)
42✔
126
            httpContent.Headers.TryAddWithoutValidation(header.Key, header.Value);
18✔
127

128
        httpResponse.Content = httpContent;
3✔
129

130
        return httpResponse;
3✔
131

132
    }
3✔
133

134

135
    private void GetPaths(HttpRequestMessage request, out string responsePath, out string contentPath)
136
    {
137
        var key = GenerateKey(request);
3✔
138
        var hash = GenerateHash(key);
3✔
139
        var rootPath = Path.GetFullPath(StorePath ?? @".\");
3!
140
        if (!Directory.Exists(rootPath))
3!
141
            Directory.CreateDirectory(rootPath);
×
142

143
        var contentFile = string.Concat(hash, ".data");
3✔
144
        contentPath = Path.Combine(rootPath, contentFile);
3✔
145

146
        var responseFile = string.Concat(hash, ".json");
3✔
147
        responsePath = Path.Combine(rootPath, responseFile);
3✔
148
    }
3✔
149

150

151
    /// <summary>
152
    /// Generates a hash for the specified <paramref name="text"/>.
153
    /// </summary>
154
    /// <param name="text">The value to hash.</param>
155
    /// <returns>An SH1 hash of the text.</returns>
156
    public static string GenerateHash(string text)
157
    {
158
        var inputBytes = Encoding.UTF8.GetBytes(text);
3✔
159

160
        byte[] hashBytes;
161

162
        using (var sha1 = System.Security.Cryptography.SHA1.Create())
3✔
163
            hashBytes = sha1.ComputeHash(inputBytes);
3✔
164

165
        var sb = new StringBuilder();
3✔
166
        foreach (byte b in hashBytes)
126✔
167
            sb.Append(b.ToString("X2"));
60✔
168

169
        return sb.ToString();
3✔
170
    }
171

172
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc