Merge pull request #2227 from livarcocc/runtime_config_from_project_json

Copy runtimeoptions from project.json to runtimeconfig.json
This commit is contained in:
Livar 2016-04-04 14:06:16 -07:00
commit f665c28173
24 changed files with 1771 additions and 247 deletions

View file

@ -16,5 +16,14 @@
}
}
}
},
"runtimeOptions": {
"somethingString": "anything",
"somethingBoolean": true,
"someArray": ["one", "two"],
"someObject": {
"someProperty": "someValue"
}
}
}

View file

@ -22,5 +22,14 @@
"centos.7-x64": {},
"rhel.7.2-x64": {},
"debian.8.2-x64": {}
},
"runtimeOptions": {
"somethingString": "anything",
"somethingBoolean": true,
"someArray": ["one", "two"],
"someObject": {
"someProperty": "someValue"
}
}
}

View file

@ -131,31 +131,8 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common
var runtimeOptions = new JObject();
json.Add("runtimeOptions", runtimeOptions);
var redistPackage = _context.RootProject.Dependencies
.Where(r => r.Type.Equals(LibraryDependencyType.Platform))
.ToList();
if(redistPackage.Count > 0)
{
if(redistPackage.Count > 1)
{
throw new InvalidOperationException("Multiple packages with type: \"platform\" were specified!");
}
var packageName = redistPackage.Single().Name;
var redistExport = exporter.GetAllExports()
.FirstOrDefault(e => e.Library.Identity.Name.Equals(packageName));
if (redistExport == null)
{
throw new InvalidOperationException($"Platform package '{packageName}' was not present in the graph.");
}
else
{
var framework = new JObject(
new JProperty("name", redistExport.Library.Identity.Name),
new JProperty("version", redistExport.Library.Identity.Version.ToNormalizedString()));
runtimeOptions.Add("framework", framework);
}
}
WriteFramework(runtimeOptions, exporter);
WriteRuntimeOptions(runtimeOptions);
var runtimeConfigJsonFile =
Path.Combine(_runtimeOutputPath, _compilerOptions.OutputName + FileNameSuffixes.RuntimeConfigJson);
@ -168,6 +145,49 @@ namespace Microsoft.Dotnet.Cli.Compiler.Common
}
}
private void WriteFramework(JObject runtimeOptions, LibraryExporter exporter)
{
var redistPackage = _context.RootProject.Dependencies
.Where(r => r.Type.Equals(LibraryDependencyType.Platform))
.ToList();
if (redistPackage.Count > 0)
{
if (redistPackage.Count > 1)
{
throw new InvalidOperationException("Multiple packages with type: \"platform\" were specified!");
}
var packageName = redistPackage.Single().Name;
var redistExport = exporter.GetAllExports()
.FirstOrDefault(e => e.Library.Identity.Name.Equals(packageName));
if (redistExport == null)
{
throw new InvalidOperationException($"Platform package '{packageName}' was not present in the graph.");
}
else
{
var framework = new JObject(
new JProperty("name", redistExport.Library.Identity.Name),
new JProperty("version", redistExport.Library.Identity.Version.ToNormalizedString()));
runtimeOptions.Add("framework", framework);
}
}
}
private void WriteRuntimeOptions(JObject runtimeOptions)
{
if (string.IsNullOrEmpty(_context.ProjectFile.RawRuntimeOptions))
{
return;
}
var runtimeOptionsFromProjectJson = JObject.Parse(_context.ProjectFile.RawRuntimeOptions);
foreach (var runtimeOption in runtimeOptionsFromProjectJson)
{
runtimeOptions.Add(runtimeOption.Key, runtimeOption.Value);
}
}
private void WriteDevRuntimeConfig(LibraryExporter exporter)
{
if (_context.TargetFramework.IsDesktop())

View file

@ -2,6 +2,8 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Microsoft.Extensions.JsonParser.Sources;
namespace Microsoft.DotNet.ProjectModel
@ -21,7 +23,7 @@ namespace Microsoft.DotNet.ProjectModel
public string Path { get; private set; }
public int Line { get; private set; }
public int Column { get; private set; }
public override string ToString()
{
return $"{Path}({Line},{Column}): Error: {base.ToString()}";
@ -29,20 +31,12 @@ namespace Microsoft.DotNet.ProjectModel
internal static FileFormatException Create(Exception exception, string filePath)
{
if (exception is JsonDeserializerException)
{
return new FileFormatException(exception.Message, exception)
.WithFilePath(filePath)
.WithLineInfo((JsonDeserializerException)exception);
}
else
{
return new FileFormatException(exception.Message, exception)
.WithFilePath(filePath);
}
return new FileFormatException(exception.Message, exception)
.WithFilePath(filePath)
.WithLineInfo(exception);
}
internal static FileFormatException Create(Exception exception, JsonValue jsonValue, string filePath)
internal static FileFormatException Create(Exception exception, JToken jsonValue, string filePath)
{
var result = Create(exception, jsonValue)
.WithFilePath(filePath);
@ -50,7 +44,7 @@ namespace Microsoft.DotNet.ProjectModel
return result;
}
internal static FileFormatException Create(Exception exception, JsonValue jsonValue)
internal static FileFormatException Create(Exception exception, JToken jsonValue)
{
var result = new FileFormatException(exception.Message, exception)
.WithLineInfo(jsonValue);
@ -58,7 +52,7 @@ namespace Microsoft.DotNet.ProjectModel
return result;
}
internal static FileFormatException Create(string message, JsonValue jsonValue, string filePath)
internal static FileFormatException Create(string message, JToken jsonValue, string filePath)
{
var result = Create(message, jsonValue)
.WithFilePath(filePath);
@ -74,6 +68,14 @@ namespace Microsoft.DotNet.ProjectModel
return result;
}
internal static FileFormatException Create(string message, JToken jsonValue)
{
var result = new FileFormatException(message)
.WithLineInfo(jsonValue);
return result;
}
internal static FileFormatException Create(string message, JsonValue jsonValue)
{
var result = new FileFormatException(message)
@ -82,6 +84,14 @@ namespace Microsoft.DotNet.ProjectModel
return result;
}
internal static FileFormatException Create(Exception exception, JsonValue jsonValue)
{
var result = new FileFormatException(exception.Message, exception)
.WithLineInfo(jsonValue);
return result;
}
internal FileFormatException WithFilePath(string path)
{
if (path == null)
@ -94,15 +104,17 @@ namespace Microsoft.DotNet.ProjectModel
return this;
}
private FileFormatException WithLineInfo(JsonValue value)
private FileFormatException WithLineInfo(Exception exception)
{
if (value == null)
if (exception is JsonDeserializerException)
{
throw new ArgumentNullException(nameof(value));
WithLineInfo((JsonDeserializerException) exception);
}
Line = value.Line;
Column = value.Column;
if (exception is JsonReaderException)
{
WithLineInfo((JsonReaderException) exception);
}
return this;
}
@ -119,5 +131,45 @@ namespace Microsoft.DotNet.ProjectModel
return this;
}
private FileFormatException WithLineInfo(JsonReaderException exception)
{
if (exception == null)
{
throw new ArgumentNullException(nameof(exception));
}
Line = exception.LineNumber;
Column = exception.LinePosition;
return this;
}
private FileFormatException WithLineInfo(JsonValue value)
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
Line = value.Line;
Column = value.Column;
return this;
}
private FileFormatException WithLineInfo(JToken value)
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
var lineInfo = (IJsonLineInfo)value;
Line = lineInfo.LineNumber;
Column = lineInfo.LinePosition;
return this;
}
}
}

View file

@ -3,53 +3,53 @@
using System.Collections.Generic;
using System.IO;
using Microsoft.Extensions.JsonParser.Sources;
using Newtonsoft.Json.Linq;
namespace Microsoft.DotNet.ProjectModel.Files
{
internal static class NamedResourceReader
{
public static IDictionary<string, string> ReadNamedResources(JsonObject rawProject, string projectFilePath)
public static IDictionary<string, string> ReadNamedResources(JObject rawProject, string projectFilePath)
{
if (!rawProject.Keys.Contains("namedResource"))
JToken namedResourceToken;
if (!rawProject.TryGetValue("namedResource", out namedResourceToken))
{
return new Dictionary<string, string>();
}
var namedResourceToken = rawProject.ValueAsJsonObject("namedResource");
if (namedResourceToken == null)
if (namedResourceToken.Type != JTokenType.Object)
{
throw FileFormatException.Create("Value must be object.", rawProject.Value("namedResource"), projectFilePath);
throw FileFormatException.Create(
"Value must be object.",
rawProject.Value<JToken>("namedResource"), projectFilePath);
}
var namedResources = new Dictionary<string, string>();
foreach (var namedResourceKey in namedResourceToken.Keys)
foreach (var namedResource in (JObject)namedResourceToken)
{
var resourcePath = namedResourceToken.ValueAsString(namedResourceKey);
if (resourcePath == null)
if (namedResource.Value.Type != JTokenType.String)
{
throw FileFormatException.Create("Value must be string.", namedResourceToken.Value(namedResourceKey), projectFilePath);
throw FileFormatException.Create("Value must be string.", namedResource.Key, projectFilePath);
}
if (resourcePath.Value.Contains("*"))
var resourcePath = namedResource.Value.ToString();
if (resourcePath.Contains("*"))
{
throw FileFormatException.Create("Value cannot contain wildcards.", resourcePath, projectFilePath);
}
var resourceFileFullPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(projectFilePath), resourcePath));
var resourceFileFullPath =
Path.GetFullPath(Path.Combine(Path.GetDirectoryName(projectFilePath), resourcePath));
if (namedResources.ContainsKey(namedResourceKey))
if (namedResources.ContainsKey(namedResource.Key))
{
throw FileFormatException.Create(
string.Format("The named resource {0} already exists.", namedResourceKey),
string.Format("The named resource {0} already exists.", namedResource.Key),
resourcePath,
projectFilePath);
}
namedResources.Add(
namedResourceKey,
resourceFileFullPath);
namedResources.Add(namedResource.Key, resourceFileFullPath);
}
return namedResources;

View file

@ -2,7 +2,8 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Linq;
using Microsoft.Extensions.JsonParser.Sources;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Microsoft.DotNet.ProjectModel.Files
{
@ -13,9 +14,14 @@ namespace Microsoft.DotNet.ProjectModel.Files
public int Line { get; }
public int Column { get; }
internal PackIncludeEntry(string target, JsonValue json)
: this(target, ExtractValues(json), json.Line, json.Column)
internal PackIncludeEntry(string target, JToken json)
{
Target = target;
SourceGlobs = ExtractValues(json);
var lineInfo = (IJsonLineInfo)json;
Line = lineInfo.LineNumber;
Column = lineInfo.LinePosition;
}
public PackIncludeEntry(string target, string[] sourceGlobs, int line, int column)
@ -26,18 +32,16 @@ namespace Microsoft.DotNet.ProjectModel.Files
Column = column;
}
private static string[] ExtractValues(JsonValue json)
private static string[] ExtractValues(JToken json)
{
var valueAsString = json as JsonString;
if (valueAsString != null)
if (json.Type == JTokenType.String)
{
return new string[] { valueAsString.Value };
return new string[] { json.Value<string>() };
}
var valueAsArray = json as JsonArray;
if(valueAsArray != null)
if(json.Type == JTokenType.Array)
{
return valueAsArray.Values.Select(v => v.ToString()).ToArray();
return json.Select(v => v.ToString()).ToArray();
}
return new string[0];
}

View file

@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Extensions.FileSystemGlobbing;
using Microsoft.Extensions.JsonParser.Sources;
using Newtonsoft.Json.Linq;
namespace Microsoft.DotNet.ProjectModel.Files
{
@ -33,7 +33,7 @@ namespace Microsoft.DotNet.ProjectModel.Files
_matcher.AddExcludePatterns(ExcludePatterns);
}
internal static PatternGroup Build(JsonObject rawProject,
internal static PatternGroup Build(JObject rawProject,
string projectDirectory,
string projectFilePath,
string name,

View file

@ -1,11 +1,11 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Extensions.JsonParser.Sources;
namespace Microsoft.DotNet.ProjectModel.Files
{
@ -13,7 +13,7 @@ namespace Microsoft.DotNet.ProjectModel.Files
{
private static readonly char[] PatternSeparator = new[] { ';' };
public static IEnumerable<string> GetPatternsCollection(JsonObject rawProject,
public static IEnumerable<string> GetPatternsCollection(JObject rawProject,
string projectDirectory,
string projectFilePath,
string propertyName,
@ -24,29 +24,29 @@ namespace Microsoft.DotNet.ProjectModel.Files
try
{
if (!rawProject.Keys.Contains(propertyName))
JToken propertyNameToken;
if (!rawProject.TryGetValue(propertyName, out propertyNameToken))
{
return CreateCollection(projectDirectory, propertyName, defaultPatterns, literalPath);
}
var valueInString = rawProject.ValueAsString(propertyName);
if (valueInString != null)
if (propertyNameToken.Type == JTokenType.String)
{
return CreateCollection(projectDirectory, propertyName, new string[] { valueInString }, literalPath);
return CreateCollection(projectDirectory, propertyName, new string[] { propertyNameToken.Value<string>() }, literalPath);
}
var valuesInArray = rawProject.ValueAsStringArray(propertyName);
if (valuesInArray != null)
if (propertyNameToken.Type == JTokenType.Array)
{
var valuesInArray = propertyNameToken.Values<string>();
return CreateCollection(projectDirectory, propertyName, valuesInArray.Select(s => s.ToString()), literalPath);
}
}
catch (Exception ex)
{
throw FileFormatException.Create(ex, rawProject.Value(propertyName), projectFilePath);
throw FileFormatException.Create(ex, rawProject.Value<JToken>(propertyName), projectFilePath);
}
throw FileFormatException.Create("Value must be either string or array.", rawProject.Value(propertyName), projectFilePath);
throw FileFormatException.Create("Value must be either string or array.", rawProject.Value<JToken>(propertyName), projectFilePath);
}
private static IEnumerable<string> CreateCollection(string projectDirectory, string propertyName, IEnumerable<string> patternsStrings, bool literalPath)

View file

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Microsoft.Extensions.JsonParser.Sources;
using Newtonsoft.Json.Linq;
namespace Microsoft.DotNet.ProjectModel.Files
{
@ -35,10 +35,10 @@ namespace Microsoft.DotNet.ProjectModel.Files
private readonly string _projectDirectory;
private readonly string _projectFilePath;
private JsonObject _rawProject;
private JObject _rawProject;
private bool _initialized;
internal ProjectFilesCollection(JsonObject rawProject, string projectDirectory, string projectFilePath)
internal ProjectFilesCollection(JObject rawProject, string projectDirectory, string projectFilePath)
{
_projectDirectory = projectDirectory;
_projectFilePath = projectFilePath;
@ -79,13 +79,16 @@ namespace Microsoft.DotNet.ProjectModel.Files
_namedResources = NamedResourceReader.ReadNamedResources(_rawProject, _projectFilePath);
// Files to be packed along with the project
var packIncludeJson = _rawProject.ValueAsJsonObject(PackIncludePropertyName);
var packIncludeJson = _rawProject.Value<JToken>(PackIncludePropertyName) as JObject;
if (packIncludeJson != null)
{
_packInclude = packIncludeJson
.Keys
.Select(k => new PackIncludeEntry(k, packIncludeJson.Value(k)))
.ToList();
var packIncludeEntries = new List<PackIncludeEntry>();
foreach (var token in packIncludeJson)
{
packIncludeEntries.Add(new PackIncludeEntry(token.Key, token.Value));
}
_packInclude = packIncludeEntries;
}
else
{

View file

@ -1,10 +1,12 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Extensions.JsonParser.Sources;
using Newtonsoft.Json;
using System.Linq;
namespace Microsoft.DotNet.ProjectModel
{
@ -42,27 +44,11 @@ namespace Microsoft.DotNet.ProjectModel
globalJsonPath = Path.Combine(path, FileName);
}
globalSettings = new GlobalSettings();
try
{
using (var fs = File.OpenRead(globalJsonPath))
{
var reader = new StreamReader(fs);
var jobject = JsonDeserializer.Deserialize(reader) as JsonObject;
if (jobject == null)
{
throw new InvalidOperationException("The JSON file can't be deserialized to a JSON object.");
}
var projectSearchPaths = jobject.ValueAsStringArray("projects") ??
jobject.ValueAsStringArray("sources") ??
new string[] { };
globalSettings.ProjectSearchPaths = new List<string>(projectSearchPaths);
globalSettings.PackagesPath = jobject.ValueAsString("packages");
globalSettings.FilePath = globalJsonPath;
globalSettings = GetGlobalSettings(fs, globalJsonPath);
}
}
catch (Exception ex)
@ -73,6 +59,41 @@ namespace Microsoft.DotNet.ProjectModel
return true;
}
public static GlobalSettings GetGlobalSettings(Stream fs, string globalJsonPath)
{
var globalSettings = new GlobalSettings();
var reader = new StreamReader(fs);
JObject jobject;
try
{
jobject = JObject.Parse(reader.ReadToEnd());
}
catch (JsonReaderException)
{
throw new InvalidOperationException("The JSON file can't be deserialized to a JSON object.");
}
IEnumerable<string> projectSearchPaths = Enumerable.Empty<string>();
JToken projectSearchPathsToken;
if (jobject.TryGetValue("projects", out projectSearchPathsToken) &&
projectSearchPathsToken.Type == JTokenType.Array)
{
projectSearchPaths = projectSearchPathsToken.Values<string>();
}
else if (jobject.TryGetValue("sources", out projectSearchPathsToken) &&
projectSearchPathsToken.Type == JTokenType.Array)
{
projectSearchPaths = projectSearchPathsToken.Values<string>();
}
globalSettings.ProjectSearchPaths = new List<string>(projectSearchPaths);
globalSettings.PackagesPath = jobject.Value<string>("packages");
globalSettings.FilePath = globalJsonPath;
return globalSettings;
}
public static bool HasGlobalFile(string path)
{
string projectPath = Path.Combine(path, FileName);

View file

@ -88,6 +88,8 @@ namespace Microsoft.DotNet.ProjectModel
public IDictionary<string, IEnumerable<string>> Scripts { get; } = new Dictionary<string, IEnumerable<string>>(StringComparer.OrdinalIgnoreCase);
public string RawRuntimeOptions { get; set; }
public bool IsTestProject => !string.IsNullOrEmpty(TestRunner);
public IEnumerable<TargetFrameworkInformation> GetTargetFrameworks()

View file

@ -8,7 +8,8 @@ using System.Linq;
using Microsoft.DotNet.ProjectModel.Files;
using Microsoft.DotNet.ProjectModel.Graph;
using Microsoft.DotNet.ProjectModel.Utilities;
using Microsoft.Extensions.JsonParser.Sources;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NuGet.Frameworks;
using NuGet.Versioning;
@ -84,7 +85,8 @@ namespace Microsoft.DotNet.ProjectModel
var project = new Project();
var reader = new StreamReader(stream);
var rawProject = JsonDeserializer.Deserialize(reader) as JsonObject;
var rawProject = JObject.Parse(reader.ReadToEnd());
if (rawProject == null)
{
throw FileFormatException.Create(
@ -93,10 +95,10 @@ namespace Microsoft.DotNet.ProjectModel
}
// Meta-data properties
project.Name = rawProject.ValueAsString("name") ?? projectName;
project.Name = rawProject.Value<string>("name") ?? projectName;
project.ProjectFilePath = Path.GetFullPath(projectPath);
var version = rawProject.Value("version") as JsonString;
var version = rawProject.Value<string>("version");
if (version == null)
{
project.Version = new NuGetVersion("1.0.0");
@ -135,28 +137,29 @@ namespace Microsoft.DotNet.ProjectModel
}
}
project.Description = rawProject.ValueAsString("description");
project.Summary = rawProject.ValueAsString("summary");
project.Copyright = rawProject.ValueAsString("copyright");
project.Title = rawProject.ValueAsString("title");
project.EntryPoint = rawProject.ValueAsString("entryPoint");
project.ProjectUrl = rawProject.ValueAsString("projectUrl");
project.LicenseUrl = rawProject.ValueAsString("licenseUrl");
project.IconUrl = rawProject.ValueAsString("iconUrl");
project.CompilerName = rawProject.ValueAsString("compilerName") ?? "csc";
project.TestRunner = rawProject.ValueAsString("testRunner");
project.Description = rawProject.Value<string>("description");
project.Summary = rawProject.Value<string>("summary");
project.Copyright = rawProject.Value<string>("copyright");
project.Title = rawProject.Value<string>("title");
project.EntryPoint = rawProject.Value<string>("entryPoint");
project.ProjectUrl = rawProject.Value<string>("projectUrl");
project.LicenseUrl = rawProject.Value<string>("licenseUrl");
project.IconUrl = rawProject.Value<string>("iconUrl");
project.CompilerName = rawProject.Value<string>("compilerName") ?? "csc";
project.TestRunner = rawProject.Value<string>("testRunner");
project.Authors = rawProject.ValueAsStringArray("authors") ?? EmptyArray<string>.Value;
project.Owners = rawProject.ValueAsStringArray("owners") ?? EmptyArray<string>.Value;
project.Tags = rawProject.ValueAsStringArray("tags") ?? EmptyArray<string>.Value;
project.Authors =
rawProject.Value<JToken>("authors")?.Values<string>().ToArray() ?? EmptyArray<string>.Value;
project.Owners = rawProject.Value<JToken>("owners")?.Values<string>().ToArray() ?? EmptyArray<string>.Value;
project.Tags = rawProject.Value<JToken>("tags")?.Values<string>().ToArray() ?? EmptyArray<string>.Value;
project.Language = rawProject.ValueAsString("language");
project.ReleaseNotes = rawProject.ValueAsString("releaseNotes");
project.Language = rawProject.Value<string>("language");
project.ReleaseNotes = rawProject.Value<string>("releaseNotes");
project.RequireLicenseAcceptance = rawProject.ValueAsBoolean("requireLicenseAcceptance", defaultValue: false);
project.RequireLicenseAcceptance = rawProject.Value<bool>("requireLicenseAcceptance");
// REVIEW: Move this to the dependencies node?
project.EmbedInteropTypes = rawProject.ValueAsBoolean("embedInteropTypes", defaultValue: false);
project.EmbedInteropTypes = rawProject.Value<bool>("embedInteropTypes");
project.Dependencies = new List<LibraryRange>();
project.Tools = new List<LibraryRange>();
@ -164,41 +167,42 @@ namespace Microsoft.DotNet.ProjectModel
// Project files
project.Files = new ProjectFilesCollection(rawProject, project.ProjectDirectory, project.ProjectFilePath);
var commands = rawProject.Value("commands") as JsonObject;
var commands = rawProject.Value<JToken>("commands") as JObject;
if (commands != null)
{
foreach (var key in commands.Keys)
foreach (var command in commands)
{
var value = commands.ValueAsString(key);
if (value != null)
var commandValue = command.Value.Type == JTokenType.String ? command.Value.Value<string>() : null;
if (commandValue != null)
{
project.Commands[key] = value;
project.Commands[command.Key] = commandValue;
}
}
}
var scripts = rawProject.Value("scripts") as JsonObject;
var scripts = rawProject.Value<JToken>("scripts") as JObject;
if (scripts != null)
{
foreach (var key in scripts.Keys)
foreach (var script in scripts)
{
var stringValue = scripts.ValueAsString(key);
var stringValue = script.Value.Type == JTokenType.String ? script.Value.Value<string>() : null;
if (stringValue != null)
{
project.Scripts[key] = new string[] { stringValue };
project.Scripts[script.Key] = new string[] { stringValue };
continue;
}
var arrayValue = scripts.ValueAsStringArray(key);
var arrayValue =
script.Value.Type == JTokenType.Array ? script.Value.Values<string>().ToArray() : null;
if (arrayValue != null)
{
project.Scripts[key] = arrayValue;
project.Scripts[script.Key] = arrayValue;
continue;
}
throw FileFormatException.Create(
string.Format("The value of a script in {0} can only be a string or an array of strings", Project.FileName),
scripts.Value(key),
script.Value,
project.ProjectFilePath);
}
}
@ -219,6 +223,18 @@ namespace Microsoft.DotNet.ProjectModel
"tools",
isGacOrFrameworkReference: false);
JToken runtimeOptionsToken;
if (rawProject.TryGetValue("runtimeOptions", out runtimeOptionsToken))
{
var runtimeOptions = runtimeOptionsToken as JObject;
if (runtimeOptions == null)
{
throw FileFormatException.Create("The runtimeOptions must be an object", runtimeOptionsToken);
}
project.RawRuntimeOptions = runtimeOptions.ToString();
}
return project;
}
@ -242,124 +258,96 @@ namespace Microsoft.DotNet.ProjectModel
private static void PopulateDependencies(
string projectPath,
IList<LibraryRange> results,
JsonObject settings,
JObject settings,
string propertyName,
bool isGacOrFrameworkReference)
{
var dependencies = settings.ValueAsJsonObject(propertyName);
var dependencies = settings.Value<JToken>(propertyName) as JObject;
if (dependencies != null)
{
foreach (var dependencyKey in dependencies.Keys)
foreach (var dependency in dependencies)
{
if (string.IsNullOrEmpty(dependencyKey))
if (string.IsNullOrEmpty(dependency.Key))
{
throw FileFormatException.Create(
"Unable to resolve dependency ''.",
dependencies.Value(dependencyKey),
dependency.Key,
projectPath);
}
var dependencyValue = dependencies.Value(dependencyKey);
var dependencyValue = dependency.Value;
var dependencyTypeValue = LibraryDependencyType.Default;
JsonString dependencyVersionAsString = null;
string dependencyVersionAsString = null;
LibraryType target = isGacOrFrameworkReference ? LibraryType.ReferenceAssembly : LibraryType.Unspecified;
if (dependencyValue is JsonObject)
if (dependencyValue.Type == JTokenType.Object)
{
// "dependencies" : { "Name" : { "version": "1.0", "type": "build", "target": "project" } }
var dependencyValueAsObject = (JsonObject)dependencyValue;
dependencyVersionAsString = dependencyValueAsObject.ValueAsString("version");
dependencyVersionAsString = dependencyValue.Value<string>("version");
var type = dependencyValueAsObject.ValueAsString("type");
var type = dependencyValue.Value<string>("type");
if (type != null)
{
dependencyTypeValue = LibraryDependencyType.Parse(type.Value);
dependencyTypeValue = LibraryDependencyType.Parse(type);
}
// Read the target if specified
if (!isGacOrFrameworkReference)
{
LibraryType parsedTarget;
var targetStr = dependencyValueAsObject.ValueAsString("target");
var targetStr = dependencyValue.Value<string>("target");
if (!string.IsNullOrEmpty(targetStr) && LibraryType.TryParse(targetStr, out parsedTarget))
{
target = parsedTarget;
}
}
}
else if (dependencyValue is JsonString)
else if (dependencyValue.Type == JTokenType.String)
{
// "dependencies" : { "Name" : "1.0" }
dependencyVersionAsString = (JsonString)dependencyValue;
dependencyVersionAsString = dependencyValue.Value<string>();
}
else
{
throw FileFormatException.Create(
string.Format("Invalid dependency version: {0}. The format is not recognizable.", dependencyKey),
string.Format(
"Invalid dependency version: {0}. The format is not recognizable.",
dependency.Key),
dependencyValue,
projectPath);
}
VersionRange dependencyVersionRange = null;
if (!string.IsNullOrEmpty(dependencyVersionAsString?.Value))
if (!string.IsNullOrEmpty(dependencyVersionAsString))
{
try
{
dependencyVersionRange = VersionRange.Parse(dependencyVersionAsString.Value);
dependencyVersionRange = VersionRange.Parse(dependencyVersionAsString);
}
catch (Exception ex)
{
throw FileFormatException.Create(
ex,
dependencyValue,
projectPath);
throw FileFormatException.Create(ex, dependencyValue, projectPath);
}
}
var lineInfo = (IJsonLineInfo)dependencyValue;
results.Add(new LibraryRange(
dependencyKey,
dependency.Key,
dependencyVersionRange,
target,
dependencyTypeValue,
projectPath,
dependencies.Value(dependencyKey).Line,
dependencies.Value(dependencyKey).Column));
lineInfo.LineNumber,
lineInfo.LinePosition));
}
}
}
private static bool TryGetStringEnumerable(JsonObject parent, string property, out IEnumerable<string> result)
{
var collection = new List<string>();
var valueInString = parent.ValueAsString(property);
if (valueInString != null)
{
collection.Add(valueInString);
}
else
{
var valueInArray = parent.ValueAsStringArray(property);
if (valueInArray != null)
{
collection.AddRange(valueInArray);
}
else
{
result = null;
return false;
}
}
result = collection.SelectMany(value => value.Split(new[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries));
return true;
}
private void BuildTargetFrameworksAndConfigurations(Project project, JsonObject projectJsonObject, ICollection<DiagnosticMessage> diagnostics)
private void BuildTargetFrameworksAndConfigurations(Project project, JObject projectJsonObject, ICollection<DiagnosticMessage> diagnostics)
{
// Get the shared compilationOptions
project._defaultCompilerOptions = GetCompilationOptions(projectJsonObject,
project)
?? new CommonCompilerOptions();
project._defaultCompilerOptions =
GetCompilationOptions(projectJsonObject, project) ?? new CommonCompilerOptions();
project._defaultTargetFrameworkConfiguration = new TargetFrameworkInformation
{
@ -391,16 +379,15 @@ namespace Microsoft.DotNet.ProjectModel
}
*/
var configurationsSection = projectJsonObject.ValueAsJsonObject("configurations");
var configurationsSection = projectJsonObject.Value<JToken>("configurations") as JObject;
if (configurationsSection != null)
{
foreach (var configKey in configurationsSection.Keys)
foreach (var configKey in configurationsSection)
{
var compilerOptions = GetCompilationOptions(configurationsSection.ValueAsJsonObject(configKey),
project);
var compilerOptions = GetCompilationOptions(configKey.Value as JObject, project);
// Only use this as a configuration if it's not a target framework
project._compilerOptionsByConfiguration[configKey] = compilerOptions;
project._compilerOptionsByConfiguration[configKey.Key] = compilerOptions;
}
}
@ -416,30 +403,31 @@ namespace Microsoft.DotNet.ProjectModel
}
*/
var frameworks = projectJsonObject.ValueAsJsonObject("frameworks");
var frameworks = projectJsonObject.Value<JToken>("frameworks") as JObject;
if (frameworks != null)
{
foreach (var frameworkKey in frameworks.Keys)
foreach (var framework in frameworks)
{
try
{
var frameworkToken = frameworks.ValueAsJsonObject(frameworkKey);
var success = BuildTargetFrameworkNode(project, frameworkKey, frameworkToken);
var frameworkToken = framework.Value as JObject;
var success = BuildTargetFrameworkNode(project, framework.Key, frameworkToken);
if (!success)
{
var lineInfo = (IJsonLineInfo)framework.Value;
diagnostics?.Add(
new DiagnosticMessage(
ErrorCodes.NU1008,
$"\"{frameworkKey}\" is an unsupported framework.",
$"\"{framework.Key}\" is an unsupported framework.",
project.ProjectFilePath,
DiagnosticMessageSeverity.Error,
frameworkToken.Line,
frameworkToken.Column));
lineInfo.LineNumber,
lineInfo.LinePosition));
}
}
catch (Exception ex)
{
throw FileFormatException.Create(ex, frameworks.Value(frameworkKey), project.ProjectFilePath);
throw FileFormatException.Create(ex, framework.Value, project.ProjectFilePath);
}
}
}
@ -451,7 +439,7 @@ namespace Microsoft.DotNet.ProjectModel
/// <param name="frameworkKey">The name of the framework</param>
/// <param name="frameworkValue">The Json object represent the settings</param>
/// <returns>Returns true if it successes.</returns>
private bool BuildTargetFrameworkNode(Project project, string frameworkKey, JsonObject frameworkValue)
private bool BuildTargetFrameworkNode(Project project, string frameworkKey, JObject frameworkValue)
{
// If no compilation options are provided then figure them out from the node
var compilerOptions = GetCompilationOptions(frameworkValue, project) ??
@ -477,13 +465,14 @@ namespace Microsoft.DotNet.ProjectModel
compilerOptions.Defines = defines;
var lineInfo = (IJsonLineInfo)frameworkValue;
var targetFrameworkInformation = new TargetFrameworkInformation
{
FrameworkName = frameworkName,
Dependencies = new List<LibraryRange>(),
CompilerOptions = compilerOptions,
Line = frameworkValue.Line,
Column = frameworkValue.Column
Line = lineInfo.LineNumber,
Column = lineInfo.LinePosition
};
var frameworkDependencies = new List<LibraryRange>();
@ -506,12 +495,12 @@ namespace Microsoft.DotNet.ProjectModel
frameworkDependencies.AddRange(frameworkAssemblies);
targetFrameworkInformation.Dependencies = frameworkDependencies;
targetFrameworkInformation.WrappedProject = frameworkValue.ValueAsString("wrappedProject");
targetFrameworkInformation.WrappedProject = frameworkValue.Value<string>("wrappedProject");
var binNode = frameworkValue.ValueAsJsonObject("bin");
var binNode = frameworkValue.Value<JToken>("bin") as JObject;
if (binNode != null)
{
targetFrameworkInformation.AssemblyPath = binNode.ValueAsString("assembly");
targetFrameworkInformation.AssemblyPath = binNode.Value<string>("assembly");
}
project._targetFrameworks[frameworkName] = targetFrameworkInformation;
@ -519,39 +508,37 @@ namespace Microsoft.DotNet.ProjectModel
return true;
}
private static CommonCompilerOptions GetCompilationOptions(JsonObject rawObject, Project project)
private static CommonCompilerOptions GetCompilationOptions(JObject rawObject, Project project)
{
var rawOptions = rawObject.ValueAsJsonObject("compilationOptions");
var rawOptions = rawObject.Value<JToken>("compilationOptions") as JObject;
if (rawOptions == null)
{
return null;
}
var analyzerOptionsJson = rawOptions.Value("analyzerOptions") as JsonObject;
var analyzerOptionsJson = rawOptions.Value<JToken>("analyzerOptions") as JObject;
if (analyzerOptionsJson != null)
{
var analyzerOptions = new AnalyzerOptions();
foreach (var key in analyzerOptionsJson.Keys)
foreach (var analyzerOption in analyzerOptionsJson)
{
switch (key)
switch (analyzerOption.Key)
{
case "languageId":
var languageId = analyzerOptionsJson.ValueAsString(key);
if (languageId == null)
if (analyzerOption.Value.Type != JTokenType.String)
{
throw FileFormatException.Create(
"The analyzer languageId must be a string",
analyzerOptionsJson.Value(key),
analyzerOption.Value.ToString(),
project.ProjectFilePath);
}
analyzerOptions.LanguageId = languageId;
analyzerOptions.LanguageId = analyzerOption.Value.ToString();
break;
default:
;
throw FileFormatException.Create(
$"Unrecognized analyzerOption key: {key}",
$"Unrecognized analyzerOption key: {analyzerOption.Key}",
project.ProjectFilePath);
}
}
@ -561,22 +548,22 @@ namespace Microsoft.DotNet.ProjectModel
return new CommonCompilerOptions
{
Defines = rawOptions.ValueAsStringArray("define"),
SuppressWarnings = rawOptions.ValueAsStringArray("nowarn"),
AdditionalArguments = rawOptions.ValueAsStringArray("additionalArguments"),
LanguageVersion = rawOptions.ValueAsString("languageVersion"),
AllowUnsafe = rawOptions.ValueAsNullableBoolean("allowUnsafe"),
Platform = rawOptions.ValueAsString("platform"),
WarningsAsErrors = rawOptions.ValueAsNullableBoolean("warningsAsErrors"),
Optimize = rawOptions.ValueAsNullableBoolean("optimize"),
KeyFile = rawOptions.ValueAsString("keyFile"),
DelaySign = rawOptions.ValueAsNullableBoolean("delaySign"),
PublicSign = rawOptions.ValueAsNullableBoolean("publicSign"),
DebugType = rawOptions.ValueAsString("debugType"),
EmitEntryPoint = rawOptions.ValueAsNullableBoolean("emitEntryPoint"),
GenerateXmlDocumentation = rawOptions.ValueAsNullableBoolean("xmlDoc"),
PreserveCompilationContext = rawOptions.ValueAsNullableBoolean("preserveCompilationContext"),
OutputName = rawOptions.ValueAsString("outputName")
Defines = rawOptions.Value<JToken>("define")?.Values<string>().ToArray(),
SuppressWarnings = rawOptions.Value<JToken>("nowarn")?.Values<string>().ToArray(),
AdditionalArguments = rawOptions.Value<JToken>("additionalArguments")?.Values<string>().ToArray(),
LanguageVersion = rawOptions.Value<string>("languageVersion"),
AllowUnsafe = rawOptions.Value<bool?>("allowUnsafe"),
Platform = rawOptions.Value<string>("platform"),
WarningsAsErrors = rawOptions.Value<bool?>("warningsAsErrors"),
Optimize = rawOptions.Value<bool?>("optimize"),
KeyFile = rawOptions.Value<string>("keyFile"),
DelaySign = rawOptions.Value<bool?>("delaySign"),
PublicSign = rawOptions.Value<bool?>("publicSign"),
DebugType = rawOptions.Value<string>("debugType"),
EmitEntryPoint = rawOptions.Value<bool?>("emitEntryPoint"),
GenerateXmlDocumentation = rawOptions.Value<bool?>("xmlDoc"),
PreserveCompilationContext = rawOptions.Value<bool?>("preserveCompilationContext"),
OutputName = rawOptions.Value<string>("outputName")
};
}

View file

@ -2,6 +2,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
@ -23,3 +24,5 @@ using System.Runtime.InteropServices;
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("303677d5-7312-4c3f-baee-beb1a9bd9fe6")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.ProjectModel.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100039ac461fa5c82c7dd2557400c4fd4e9dcdf7ac47e3d572548c04cd4673e004916610f4ea5cbf86f2b1ca1cb824f2a7b3976afecfcf4eb72d9a899aa6786effa10c30399e6580ed848231fec48374e41b3acf8811931343fc2f73acf72dae745adbcb7063cc4b50550618383202875223fc75401351cd89c44bf9b50e7fa3796")]

View file

@ -12,6 +12,8 @@
"type": "build",
"version": "1.0.0-rc2-16453"
},
"Newtonsoft.Json": "7.0.1",
"System.Runtime.Serialization.Primitives": "4.1.1-rc2-23931",
"Microsoft.Extensions.HashCodeCombiner.Sources": {
"type": "build",
"version": "1.0.0-rc2-16054"
@ -30,6 +32,9 @@
"System.IO": {
"type": "build"
}
},
"dependencies": {
"System.Linq": "4.0.1-rc3-23727"
}
},
"netstandard1.5": {

View file

@ -0,0 +1,92 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Microsoft.DotNet.ProjectModel;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Xunit;
using System.Linq;
using FluentAssertions;
namespace Microsoft.DotNet.ProjectModel.Tests
{
public class GivenThatIWantToCreateFileCollectionsFromJson
{
private const string ProjectName = "some project name";
private readonly string ProjectFilePath = AppContext.BaseDirectory;
[Fact]
public void PackInclude_is_empty_when_it_is_not_set_in_the_ProjectJson()
{
var json = new JObject();
var project = GetProject(json);
project.Files.PackInclude.Should().BeEmpty();
}
[Fact]
public void It_sets_PackInclude_when_packInclude_is_set_in_the_ProjectJson()
{
const string somePackTarget = "some pack target";
const string somePackValue = "some pack value";
var json = new JObject();
var packIncludeJson = new JObject();
json.Add("packInclude", packIncludeJson);
packIncludeJson.Add(somePackTarget, somePackValue);
var project = GetProject(json);
var packInclude = project.Files.PackInclude.FirstOrDefault();
packInclude.Target.Should().Be(somePackTarget);
packInclude.SourceGlobs.Should().Contain(somePackValue);
}
[Fact]
public void It_parses_namedResources_successfully()
{
const string someString = "some string";
var json = new JObject();
var namedResources= new JObject();
json.Add("namedResource", namedResources);
namedResources.Add(someString, "Some/Resource.resx");
var project = GetProject(json);
var key = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(ProjectFilePath), "Some", "Resource.resx"));
project.Files.ResourceFiles[key].Should().Be(someString);
}
private Project GetProject(JObject json, ProjectReaderSettings settings = null)
{
using (var stream = new MemoryStream())
{
using (var sw = new StreamWriter(stream, Encoding.UTF8, 256, true))
{
using (var writer = new JsonTextWriter(sw))
{
writer.Formatting = Formatting.Indented;
json.WriteTo(writer);
}
stream.Position = 0;
var projectReader = new ProjectReader();
return projectReader.ReadProject(
stream,
ProjectName,
ProjectFilePath,
new List<DiagnosticMessage>(),
settings);
}
}
}
}
}

View file

@ -0,0 +1,883 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.IO;
using System.Text;
using Xunit;
using Microsoft.DotNet.ProjectModel;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using FluentAssertions;
using NuGet.Versioning;
using System.Linq;
using NuGet.ProjectModel;
using Microsoft.DotNet.ProjectModel.Graph;
namespace Microsoft.DotNet.ProjectModel.Tests
{
public class GivenThatIWantToLoadAProjectJsonFile
{
private const string ProjectName = "some project name";
private const string SomeLanguageVersion = "some language version";
private const string SomeOutputName = "some output name";
private const string SomePlatform = "some platform";
private const string SomeKeyFile = "some key file";
private const string SomeDebugType = "some debug type";
private const string DependencyName = "some dependency";
private const string ToolName = "some tool";
private const string Version = "1.0.0";
private readonly string ProjectFilePath = AppContext.BaseDirectory;
private Project _emptyProject;
private readonly string[] _someDefines = new[] {"DEFINE1", "DEFINE2"};
private readonly string[] _noWarnings = new[] {"warn1", "warn2"};
private readonly string[] _someAdditionalArguments = new[] {"additional argument 1", "additional argument 2"};
private readonly VersionRange _versionRange = VersionRange.Parse(Version);
private readonly JObject _jsonCompilationOptions;
private CommonCompilerOptions _commonCompilerOptions;
public GivenThatIWantToLoadAProjectJsonFile()
{
var json = new JObject();
_emptyProject = GetProject(json);
_jsonCompilationOptions = new JObject();
_jsonCompilationOptions.Add("define", new JArray(_someDefines));
_jsonCompilationOptions.Add("nowarn", new JArray(_noWarnings));
_jsonCompilationOptions.Add("additionalArguments", new JArray(_someAdditionalArguments));
_jsonCompilationOptions.Add("languageVersion", SomeLanguageVersion);
_jsonCompilationOptions.Add("outputName", SomeOutputName);
_jsonCompilationOptions.Add("platform", SomePlatform);
_jsonCompilationOptions.Add("keyFile", SomeKeyFile);
_jsonCompilationOptions.Add("debugType", SomeDebugType);
_jsonCompilationOptions.Add("allowUnsafe", true);
_jsonCompilationOptions.Add("warningsAsErrors", true);
_jsonCompilationOptions.Add("optimize", true);
_jsonCompilationOptions.Add("delaySign", true);
_jsonCompilationOptions.Add("publicSign", true);
_jsonCompilationOptions.Add("emitEntryPoint", true);
_jsonCompilationOptions.Add("xmlDoc", true);
_jsonCompilationOptions.Add("preserveCompilationContext", true);
_commonCompilerOptions = new CommonCompilerOptions
{
Defines = _someDefines,
SuppressWarnings = _noWarnings,
AdditionalArguments = _someAdditionalArguments,
LanguageVersion = SomeLanguageVersion,
OutputName = SomeOutputName,
Platform = SomePlatform,
KeyFile = SomeKeyFile,
DebugType = SomeDebugType,
AllowUnsafe = true,
WarningsAsErrors = true,
Optimize = true,
DelaySign = true,
PublicSign = true,
EmitEntryPoint = true,
GenerateXmlDocumentation = true,
PreserveCompilationContext = true
};
}
[Fact]
public void It_does_not_throw_when_the_project_json_is_empty()
{
var json = new JObject();
Action action = () => GetProject(json);
action.ShouldNotThrow<Exception>();
}
[Fact]
public void It_sets_Name_to_the_passed_ProjectName_if_one_is_not_set_in_the_ProjectJson()
{
_emptyProject.Name.Should().Be(ProjectName);
}
[Fact]
public void It_sets_Name_to_the_Name_in_the_ProjectJson_when_one_is_set()
{
const string nameInProjectJson = "some name in the project.json";
var json = new JObject();
json.Add("name", nameInProjectJson);
var project = GetProject(json);
project.Name.Should().Be(nameInProjectJson);
}
[Fact]
public void It_sets_the_project_file_path()
{
_emptyProject.ProjectFilePath.Should().Be(ProjectFilePath);
}
[Fact]
public void It_sets_the_version_to_one_when_it_is_not_set()
{
_emptyProject.Version.Should().Be(new NuGetVersion("1.0.0"));
}
[Fact]
public void It_sets_the_version_to_the_one_in_the_ProjectJson_when_one_is_set()
{
var json = new JObject();
json.Add("version", "1.1");
var project = GetProject(json);
project.Version.Should().Be(new NuGetVersion("1.1"));
}
[Fact]
public void It_sets_AssemblyFileVersion_to_the_ProjectJson_version_when_AssemblyFileVersion_is_not_passed_in_the_settings()
{
var json = new JObject();
json.Add("version", "1.1");
var project = GetProject(json);
project.AssemblyFileVersion.Should().Be(new NuGetVersion("1.1").Version);
}
[Fact]
public void It_sets_AssemblyFileVersion_Revision_to_the_AssemblyFileVersion_passed_in_the_settings_and_everything_else_to_the_projectJson_Version()
{
const int revision = 1;
var json = new JObject();
json.Add("version", "1.1");
var project = GetProject(json, new ProjectReaderSettings { AssemblyFileVersion = revision.ToString() });
var version = new NuGetVersion("1.1").Version;
project.AssemblyFileVersion.Should().Be(
new Version(version.Major, version.Minor, version.Build, revision));
}
[Fact]
public void It_throws_a_FormatException_when_AssemblyFileVersion_passed_in_the_settings_is_invalid()
{
var json = new JObject();
json.Add("version", "1.1");
Action action = () =>
GetProject(json, new ProjectReaderSettings { AssemblyFileVersion = "not a revision" });
action.ShouldThrow<FormatException>().WithMessage("The assembly file version is invalid: not a revision");
}
[Fact]
public void It_leaves_marketing_information_empty_when_it_is_not_set_in_the_ProjectJson()
{
_emptyProject.Description.Should().BeNull();
_emptyProject.Summary.Should().BeNull();
_emptyProject.Copyright.Should().BeNull();
_emptyProject.Title.Should().BeNull();
_emptyProject.EntryPoint.Should().BeNull();
_emptyProject.ProjectUrl.Should().BeNull();
_emptyProject.LicenseUrl.Should().BeNull();
_emptyProject.IconUrl.Should().BeNull();
_emptyProject.Authors.Should().BeEmpty();
_emptyProject.Owners.Should().BeEmpty();
_emptyProject.Tags.Should().BeEmpty();
_emptyProject.Language.Should().BeNull();
_emptyProject.ReleaseNotes.Should().BeNull();
}
[Fact]
public void It_sets_the_marketing_information_when_it_is_set_in_the_ProjectJson()
{
const string someDescription = "some description";
const string someSummary = "some summary";
const string someCopyright = "some copyright";
const string someTitle = "some title";
const string someEntryPoint = "some entry point";
const string someProjectUrl = "some project url";
const string someLicenseUrl = "some license url";
const string someIconUrl = "some icon url";
const string someLanguage = "some language";
const string someReleaseNotes = "someReleaseNotes";
var authors = new [] {"some author", "and another author"};
var owners = new[] {"some owner", "a second owner"};
var tags = new[] {"tag1", "tag2"};
var json = new JObject();
json.Add("description", someDescription);
json.Add("summary", someSummary);
json.Add("copyright", someCopyright);
json.Add("title", someTitle);
json.Add("entryPoint", someEntryPoint);
json.Add("projectUrl", someProjectUrl);
json.Add("licenseUrl", someLicenseUrl);
json.Add("iconUrl", someIconUrl);
json.Add("authors", new JArray(authors));
json.Add("owners", new JArray(owners));
json.Add("tags", new JArray(tags));
json.Add("language", someLanguage);
json.Add("releaseNotes", someReleaseNotes);
var project = GetProject(json);
project.Description.Should().Be(someDescription);
project.Summary.Should().Be(someSummary);
project.Copyright.Should().Be(someCopyright);
project.Title.Should().Be(someTitle);
project.EntryPoint.Should().Be(someEntryPoint);
project.ProjectUrl.Should().Be(someProjectUrl);
project.LicenseUrl.Should().Be(someLicenseUrl);
project.IconUrl.Should().Be(someIconUrl);
project.Authors.Should().Contain(authors);
project.Owners.Should().Contain(owners);
project.Tags.Should().Contain(tags);
project.Language.Should().Be(someLanguage);
project.ReleaseNotes.Should().Be(someReleaseNotes);
}
[Fact]
public void It_sets_the_compilerName_to_csc_when_one_is_not_set_in_the_ProjectJson()
{
_emptyProject.CompilerName.Should().Be("csc");
}
[Fact]
public void It_sets_the_compilerName_to_the_one_in_the_ProjectJson()
{
const string compilerName = "a compiler different from csc";
var json = new JObject();
json.Add("compilerName", compilerName);
var project = GetProject(json);
project.CompilerName.Should().Be(compilerName);
}
[Fact]
public void It_leaves_testRunner_null_when_one_is_not_set_in_the_ProjectJson()
{
_emptyProject.TestRunner.Should().BeNull();
}
[Fact]
public void It_sets_testRunner_to_the_one_in_the_ProjectJson()
{
const string someTestRunner = "some test runner";
var json = new JObject();
json.Add("testRunner", someTestRunner);
var project = GetProject(json);
project.TestRunner.Should().Be(someTestRunner);
}
[Fact]
public void It_sets_requireLicenseAcceptance_to_false_when_one_is_not_set_in_the_ProjectJson()
{
_emptyProject.RequireLicenseAcceptance.Should().BeFalse();
}
[Fact]
public void It_sets_requireLicenseAcceptance_to_true_when_it_is_true_in_the_ProjectJson()
{
var json = new JObject();
json.Add("requireLicenseAcceptance", true);
var project = GetProject(json);
project.RequireLicenseAcceptance.Should().BeTrue();
}
[Fact]
public void It_sets_requireLicenseAcceptance_to_false_when_it_is_false_in_the_ProjectJson()
{
var json = new JObject();
json.Add("requireLicenseAcceptance", false);
var project = GetProject(json);
project.RequireLicenseAcceptance.Should().BeFalse();
}
[Fact]
public void It_sets_embedInteropTypes_to_false_when_one_is_not_set_in_the_ProjectJson()
{
_emptyProject.EmbedInteropTypes.Should().BeFalse();
}
[Fact]
public void It_sets_embedInteropTypes_to_true_when_it_is_true_in_the_ProjectJson()
{
var json = new JObject();
json.Add("embedInteropTypes", true);
var project = GetProject(json);
project.EmbedInteropTypes.Should().BeTrue();
}
[Fact]
public void It_sets_embedInteropTypes_to_false_when_it_is_false_in_the_ProjectJson()
{
var json = new JObject();
json.Add("embedInteropTypes", false);
var project = GetProject(json);
project.EmbedInteropTypes.Should().BeFalse();
}
[Fact]
public void It_does_not_add_commands_when_commands_is_not_set_in_the_ProjectJson()
{
_emptyProject.Commands.Should().BeEmpty();
}
[Fact]
public void It_does_not_add_commands_when_commands_is_not_a_JsonObject()
{
var json = new JObject();
json.Add("commands", true);
var project = GetProject(json);
project.Commands.Should().BeEmpty();
}
[Fact]
public void It_does_not_add_the_commands_when_its_value_is_not_a_string()
{
var json = new JObject();
var commands = new JObject();
json.Add("commands", commands);
commands.Add("commandKey1", "commandValue1");
commands.Add("commandKey2", true);
var project = GetProject(json);
project.Commands.Count.Should().Be(1);
project.Commands.First().Key.Should().Be("commandKey1");
project.Commands.First().Value.Should().Be("commandValue1");
}
[Fact]
public void It_does_not_add_scripts_when_scripts_is_not_set_in_the_ProjectJson()
{
_emptyProject.Scripts.Should().BeEmpty();
}
[Fact]
public void It_does_not_add_scripts_when_scripts_is_not_a_JsonObject()
{
var json = new JObject();
json.Add("scripts", true);
var project = GetProject(json);
project.Scripts.Should().BeEmpty();
}
[Fact]
public void It_adds_the_scripts_when_its_value_is_either_a_string_or_an_array_of_strings()
{
var scriptArrayValues = new [] {"scriptValue2", "scriptValue3"};
var json = new JObject();
var scripts = new JObject();
json.Add("scripts", scripts);
scripts.Add("scriptKey1", "scriptValue1");
scripts.Add("scriptKey3", new JArray(scriptArrayValues));
var project = GetProject(json);
project.Scripts.Count.Should().Be(2);
project.Scripts.First().Key.Should().Be("scriptKey1");
project.Scripts.First().Value.Should().Contain("scriptValue1");
project.Scripts["scriptKey3"].Should().Contain(scriptArrayValues);
}
[Fact]
public void It_throws_when_the_value_of_a_script_is_neither_a_string_nor_array_of_strings()
{
var json = new JObject();
var scripts = new JObject();
json.Add("scripts", scripts);
scripts.Add("scriptKey2", true);
Action action = () => GetProject(json);
action.ShouldThrow<FileFormatException>()
.WithMessage("The value of a script in project.json can only be a string or an array of strings");
}
[Fact]
public void It_uses_an_empty_compiler_options_when_one_is_not_set_in_the_ProjectJson()
{
_emptyProject.GetCompilerOptions(null, null).Should().Be(new CommonCompilerOptions
{
OutputName = ProjectName
});
}
[Fact]
public void It_sets_analyzerOptions_when_it_is_set_in_the_compilationOptions_in_the_ProjectJson()
{
var json = new JObject();
var compilationOptions = new JObject();
json.Add("compilationOptions", compilationOptions);
var analyzerOptions = new JObject();
compilationOptions.Add("analyzerOptions", analyzerOptions);
analyzerOptions.Add("languageId", "C#");
var project = GetProject(json);
project.AnalyzerOptions.LanguageId.Should().Be("C#");
}
[Fact]
public void It_throws_when_the_analyzerOptions_languageId_is_not_a_string()
{
var json = new JObject();
var compilationOptions = new JObject();
json.Add("compilationOptions", compilationOptions);
var analyzerOptions = new JObject();
compilationOptions.Add("analyzerOptions", analyzerOptions);
analyzerOptions.Add("languageId", true);
Action action = () => GetProject(json);
action.ShouldThrow<FileFormatException>().WithMessage("The analyzer languageId must be a string");
}
[Fact]
public void It_throws_when_the_analyzerOptions_has_no_languageId()
{
var json = new JObject();
var compilationOptions = new JObject();
json.Add("compilationOptions", compilationOptions);
var analyzerOptions = new JObject();
compilationOptions.Add("analyzerOptions", analyzerOptions);
analyzerOptions.Add("differentFromLanguageId", "C#");
Action action = () => GetProject(json);
action.ShouldThrow<FileFormatException>()
.WithMessage("Unrecognized analyzerOption key: differentFromLanguageId");
}
[Fact]
public void It_sets_compilationOptions_when_it_is_set_in_the_compilationOptions_in_the_ProjectJson()
{
var json = new JObject();
json.Add("compilationOptions", _jsonCompilationOptions);
var project = GetProject(json);
project.GetCompilerOptions(null, null).Should().Be(_commonCompilerOptions);
}
[Fact]
public void It_merges_configuration_sections_set_in_the_ProjectJson()
{
var json = new JObject();
var configurations = new JObject();
json.Add("compilationOptions", _jsonCompilationOptions);
json.Add("configurations", configurations);
_jsonCompilationOptions["allowUnsafe"] = null;
var someConfiguration = new JObject();
configurations.Add("some configuration", someConfiguration);
var someConfigurationCompilationOptions = new JObject();
someConfiguration.Add("compilationOptions", someConfigurationCompilationOptions);
someConfigurationCompilationOptions.Add("allowUnsafe", false);
var project = GetProject(json);
_commonCompilerOptions.AllowUnsafe = false;
project.GetCompilerOptions(null, "some configuration").Should().Be(_commonCompilerOptions);
}
[Fact]
public void It_does_not_set_rawRuntimeOptions_when_it_is_not_set_in_the_ProjectJson()
{
_emptyProject.RawRuntimeOptions.Should().BeNull();
}
[Fact]
public void It_throws_when_runtimeOptions_is_not_a_Json_object()
{
var json = new JObject();
json.Add("runtimeOptions", "not a json object");
Action action = () => GetProject(json);
action.ShouldThrow<FileFormatException>().WithMessage("The runtimeOptions must be an object");
}
[Fact]
public void It_sets_the_rawRuntimeOptions_serialized_when_it_is_set_in_the_ProjectJson()
{
var configProperties = new JObject();
configProperties.Add("System.GC.Server", true);
var runtimeOptions = new JObject();
runtimeOptions.Add("configProperties", configProperties);
var json = new JObject();
json.Add("runtimeOptions", runtimeOptions);
var project = GetProject(json);
project.RawRuntimeOptions.Should().Be(runtimeOptions.ToString());
}
[Fact]
public void Dependencies_is_empty_when_no_dependencies_and_no_tools_are_set_in_the_ProjectJson()
{
_emptyProject.Dependencies.Should().BeEmpty();
}
[Fact]
public void It_throws_when_the_dependency_has_no_name_set()
{
var dependencies = new JObject();
dependencies.Add("", "1.0.0");
var json = new JObject();
json.Add("dependencies", dependencies);
Action action = () => GetProject(json);
action.ShouldThrow<FileFormatException>().WithMessage("Unable to resolve dependency ''.");
}
[Fact]
public void It_throws_when_the_dependency_value_is_not_an_object_not_a_string()
{
var dependencies = new JObject();
dependencies.Add(DependencyName, true);
var json = new JObject();
json.Add("dependencies", dependencies);
Action action = () => GetProject(json);
action.ShouldThrow<FileFormatException>()
.WithMessage($"Invalid dependency version: {DependencyName}. The format is not recognizable.");
}
[Fact]
public void It_throws_when_the_dependency_version_is_not_valid_when_set_directly()
{
var dependencies = new JObject();
dependencies.Add(DependencyName, "some invalid version");
var json = new JObject();
json.Add("dependencies", dependencies);
Action action = () => GetProject(json);
action.ShouldThrow<FileFormatException>()
.WithMessage("'some invalid version' is not a valid version string.");
}
[Fact]
public void It_throws_when_the_dependency_version_is_not_valid_when_set_in_an_object()
{
var dependency = new JObject();
dependency.Add("version", "some invalid version");
var dependencies = new JObject();
dependencies.Add(DependencyName, dependency);
var json = new JObject();
json.Add("dependencies", dependencies);
Action action = () => GetProject(json);
action.ShouldThrow<FileFormatException>()
.WithMessage("'some invalid version' is not a valid version string.");
}
[Fact]
public void It_leaves_version_null_when_it_is_set_to_empty_string()
{
var dependencies = new JObject();
dependencies.Add(DependencyName, string.Empty);
var json = new JObject();
json.Add("dependencies", dependencies);
var project = GetProject(json);
var dependency = project.Dependencies.First();
dependency.VersionRange.Should().BeNull();
}
[Fact]
public void It_adds_the_dependency_when_the_version_is_set_directly()
{
var dependencies = new JObject();
dependencies.Add(DependencyName, Version);
var json = new JObject();
json.Add("dependencies", dependencies);
var project = GetProject(json);
var dependency = project.Dependencies.First();
dependency.Name.Should().Be(DependencyName);
dependency.VersionRange.Should().Be(_versionRange);
dependency.Target.Should().Be(LibraryType.Unspecified);
dependency.Type.Should().Be(LibraryDependencyType.Default);
dependency.SourceFilePath.Should().Be(ProjectFilePath);
dependency.SourceLine.Should().Be(3);
dependency.SourceColumn.Should().Be(31);
}
[Fact]
public void It_adds_the_dependency_when_the_version_is_set_in_an_object()
{
var dependencyJson = new JObject();
dependencyJson.Add("version", Version);
var dependencies = new JObject();
dependencies.Add(DependencyName, dependencyJson);
var json = new JObject();
json.Add("dependencies", dependencies);
var project = GetProject(json);
var dependency = project.Dependencies.First();
dependency.Name.Should().Be(DependencyName);
dependency.VersionRange.Should().Be(_versionRange);
dependency.Target.Should().Be(LibraryType.Unspecified);
dependency.Type.Should().Be(LibraryDependencyType.Default);
dependency.SourceFilePath.Should().Be(ProjectFilePath);
dependency.SourceLine.Should().Be(3);
dependency.SourceColumn.Should().Be(25);
}
[Fact]
public void It_sets_the_dependency_type_when_it_is_set_in_the_dependency_in_the_ProjectJson()
{
var dependencyJson = new JObject();
dependencyJson.Add("type", "build");
var dependencies = new JObject();
dependencies.Add(DependencyName, dependencyJson);
var json = new JObject();
json.Add("dependencies", dependencies);
var project = GetProject(json);
var dependency = project.Dependencies.First();
dependency.Type.Should().Be(LibraryDependencyType.Build);
}
[Fact]
public void It_leaves_the_dependency_target_Unspecified_when_it_fails_to_parse_the_set_target_in_the_ProjectJson()
{
var dependencyJson = new JObject();
dependencyJson.Add("target", "not a valid target");
var dependencies = new JObject();
dependencies.Add(DependencyName, dependencyJson);
var json = new JObject();
json.Add("dependencies", dependencies);
var project = GetProject(json);
var dependency = project.Dependencies.First();
dependency.Target.Should().Be(LibraryType.Unspecified);
}
[Fact]
public void It_sets_the_dependency_target_when_it_is_set_in_the_ProjectJson()
{
var dependencyJson = new JObject();
dependencyJson.Add("target", "Project");
var dependencies = new JObject();
dependencies.Add(DependencyName, dependencyJson);
var json = new JObject();
json.Add("dependencies", dependencies);
var project = GetProject(json);
var dependency = project.Dependencies.First();
dependency.Target.Should().Be(LibraryType.Project);
}
[Fact]
public void It_throws_when_the_tool_has_no_name_set()
{
var tools = new JObject();
tools.Add("", "1.0.0");
var json = new JObject();
json.Add("tools", tools);
Action action = () => GetProject(json);
action.ShouldThrow<FileFormatException>().WithMessage("Unable to resolve dependency ''.");
}
[Fact]
public void It_throws_when_the_tool_value_is_not_an_object_not_a_string()
{
var tools = new JObject();
tools.Add(ToolName, true);
var json = new JObject();
json.Add("tools", tools);
Action action = () => GetProject(json);
action.ShouldThrow<FileFormatException>()
.WithMessage($"Invalid dependency version: {ToolName}. The format is not recognizable.");
}
[Fact]
public void It_throws_when_the_tool_version_is_not_valid_when_set_directly()
{
var tools = new JObject();
tools.Add(ToolName, "some invalid version");
var json = new JObject();
json.Add("tools", tools);
Action action = () => GetProject(json);
action.ShouldThrow<FileFormatException>()
.WithMessage("'some invalid version' is not a valid version string.");
}
[Fact]
public void It_throws_when_the_tool_version_is_not_valid_when_set_in_an_object()
{
var tool = new JObject();
tool.Add("version", "some invalid version");
var tools = new JObject();
tools.Add(ToolName, tool);
var json = new JObject();
json.Add("tools", tools);
Action action = () => GetProject(json);
action.ShouldThrow<FileFormatException>()
.WithMessage("'some invalid version' is not a valid version string.");
}
[Fact]
public void It_leaves_the_tools_version_null_when_it_is_set_to_empty_string()
{
var tools = new JObject();
tools.Add(ToolName, string.Empty);
var json = new JObject();
json.Add("tools", tools);
var project = GetProject(json);
var tool = project.Tools.First();
tool.VersionRange.Should().BeNull();
}
[Fact]
public void It_adds_the_tool_when_the_version_is_set_directly()
{
var tools = new JObject();
tools.Add(ToolName, Version);
var json = new JObject();
json.Add("tools", tools);
var project = GetProject(json);
var tool = project.Tools.First();
tool.Name.Should().Be(ToolName);
tool.VersionRange.Should().Be(_versionRange);
tool.Target.Should().Be(LibraryType.Unspecified);
tool.Type.Should().Be(LibraryDependencyType.Default);
tool.SourceFilePath.Should().Be(ProjectFilePath);
tool.SourceLine.Should().Be(3);
tool.SourceColumn.Should().Be(25);
}
[Fact]
public void It_adds_the_tool_when_the_version_is_set_in_an_object()
{
var toolJson = new JObject();
toolJson.Add("version", Version);
var tools = new JObject();
tools.Add(ToolName, toolJson);
var json = new JObject();
json.Add("tools", tools);
var project = GetProject(json);
var tool = project.Tools.First();
tool.Name.Should().Be(ToolName);
tool.VersionRange.Should().Be(_versionRange);
tool.Target.Should().Be(LibraryType.Unspecified);
tool.Type.Should().Be(LibraryDependencyType.Default);
tool.SourceFilePath.Should().Be(ProjectFilePath);
tool.SourceLine.Should().Be(3);
tool.SourceColumn.Should().Be(19);
}
[Fact]
public void It_sets_the_tool_type_when_it_is_set_in_the_tool_in_the_ProjectJson()
{
var toolJson = new JObject();
toolJson.Add("type", "build");
var tools = new JObject();
tools.Add(ToolName, toolJson);
var json = new JObject();
json.Add("tools", tools);
var project = GetProject(json);
var tool = project.Tools.First();
tool.Type.Should().Be(LibraryDependencyType.Build);
}
[Fact]
public void It_leaves_the_tool_target_Unspecified_when_it_fails_to_parse_the_set_target_in_the_ProjectJson()
{
var toolJson = new JObject();
toolJson.Add("target", "not a valid target");
var tools = new JObject();
tools.Add(ToolName, toolJson);
var json = new JObject();
json.Add("tools", tools);
var project = GetProject(json);
var tool = project.Tools.First();
tool.Target.Should().Be(LibraryType.Unspecified);
}
[Fact]
public void It_sets_the_tool_target_when_it_is_set_in_the_ProjectJson()
{
var toolJson = new JObject();
toolJson.Add("target", "Project");
var tools = new JObject();
tools.Add(ToolName, toolJson);
var json = new JObject();
json.Add("tools", tools);
var project = GetProject(json);
var tool = project.Tools.First();
tool.Target.Should().Be(LibraryType.Project);
}
public Project GetProject(JObject json, ProjectReaderSettings settings = null)
{
using (var stream = new MemoryStream())
{
using (var sw = new StreamWriter(stream, Encoding.UTF8, 256, true))
{
using (var writer = new JsonTextWriter(sw))
{
writer.Formatting = Formatting.Indented;
json.WriteTo(writer);
}
stream.Position = 0;
var projectReader = new ProjectReader();
return projectReader.ReadProject(
stream,
ProjectName,
ProjectFilePath,
new List<DiagnosticMessage>(),
settings);
}
}
}
}
}

View file

@ -0,0 +1,125 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.IO;
using Microsoft.DotNet.ProjectModel.Files;
using Newtonsoft.Json.Linq;
using Xunit;
using FluentAssertions;
namespace Microsoft.DotNet.ProjectModel.Tests
{
public class GivenThatIWantToReadFilePatternsFromJson
{
private const string SomeProperty = "some property";
private static readonly string[] SomeDefaultValues = { $"**{Path.DirectorySeparatorChar}*.cs" };
[Fact]
public void It_returns_empty_when_there_is_no_property_and_no_default_pattern()
{
var json = new JObject();
var patternsCollection = PatternsCollectionHelper.GetPatternsCollection(
json,
AppContext.BaseDirectory,
string.Empty,
"some non-existing property");
patternsCollection.Should().BeEmpty();
}
[Fact]
public void It_uses_the_passed_in_default_collection_when_the_property_is_not_in_the_json()
{
var json = new JObject();
var patternsCollection = PatternsCollectionHelper.GetPatternsCollection(
json,
AppContext.BaseDirectory,
string.Empty,
"some non-existing property",
SomeDefaultValues);
patternsCollection.Should().Contain(SomeDefaultValues);
}
[Fact]
public void It_uses_the_value_in_the_property_when_it_is_a_string()
{
var json = new JObject();
json.Add(SomeProperty, "*");
var patternsCollection = PatternsCollectionHelper.GetPatternsCollection(
json,
AppContext.BaseDirectory,
string.Empty,
SomeProperty,
SomeDefaultValues);
patternsCollection.Should().Contain("*");
}
[Fact]
public void It_uses_the_values_in_the_property_when_it_is_a_string_array()
{
var patterns = new[] {"*", $"**{Path.DirectorySeparatorChar}*.fs"};
var json = new JObject();
json.Add(SomeProperty, new JArray(patterns));
var patternsCollection = PatternsCollectionHelper.GetPatternsCollection(
json,
AppContext.BaseDirectory,
string.Empty,
SomeProperty,
SomeDefaultValues);
patternsCollection.Should().Contain(patterns);
}
[Fact]
public void It_throws_when_the_property_value_is_neither_a_string_nor_an_array()
{
var json = new JObject();
json.Add(SomeProperty, new JObject());
Action action = () => PatternsCollectionHelper.GetPatternsCollection(
json,
AppContext.BaseDirectory,
string.Empty,
SomeProperty,
SomeDefaultValues);
action.ShouldThrow<FileFormatException>().WithMessage("Value must be either string or array.");
}
[Fact]
public void It_throws_when_we_ask_for_a_literal_and_specify_a_pattern()
{
var json = new JObject();
json.Add(SomeProperty, "*");
Action action = () => PatternsCollectionHelper.GetPatternsCollection(
json,
AppContext.BaseDirectory,
string.Empty,
SomeProperty,
SomeDefaultValues,
true);
action.ShouldThrow<FileFormatException>()
.WithMessage($"The '{SomeProperty}' property cannot contain wildcard characters.");
}
[Fact]
public void It_throws_when_the_property_value_is_a_rooted_path()
{
var json = new JObject();
json.Add(SomeProperty, AppContext.BaseDirectory);
Action action = () => PatternsCollectionHelper.GetPatternsCollection(
json,
AppContext.BaseDirectory,
string.Empty,
SomeProperty,
SomeDefaultValues,
true);
action.ShouldThrow<FileFormatException>()
.WithMessage($"The '{SomeProperty}' property cannot be a rooted path.");
}
}
}

View file

@ -0,0 +1,159 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using FluentAssertions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NuGet.ProjectModel;
using Xunit;
namespace Microsoft.DotNet.ProjectModel.Tests
{
public class GivenThatIWantToReadGlobalSettingsFromJson
{
private const string SomePath = "some path";
[Fact]
public void It_throws_if_the_stream_is_not_valid_JSON()
{
Action action = () =>
{
using (var stream = new MemoryStream())
{
using (var sw = new StreamWriter(stream, Encoding.UTF8, 256, true))
{
using (var writer = new JsonTextWriter(sw))
{
writer.Formatting = Formatting.Indented;
new JValue("not an object").WriteTo(writer);
}
stream.Position = 0;
GlobalSettings.GetGlobalSettings(stream, string.Empty);
}
}
};
action.ShouldThrow<InvalidOperationException>();
}
[Fact]
public void It_leaves_the_searchPaths_empty_when_no_project_and_sources_are_set_in_the_GlobalJson()
{
var json = new JObject();
var globalSettings = GetGlobalSettings(json);
globalSettings.ProjectSearchPaths.Should().BeEmpty();
}
[Fact]
public void It_leaves_the_searchPaths_empty_when_projects_is_not_an_array_in_the_GlobalJson()
{
var json = new JObject();
json.Add("projects", "not an array");
var globalSettings = GetGlobalSettings(json);
globalSettings.ProjectSearchPaths.Should().BeEmpty();
}
[Fact]
public void It_leaves_the_searchPaths_empty_when_sources_is_not_an_array_in_the_GlobalJson()
{
var json = new JObject();
json.Add("sources", "not an array");
var globalSettings = GetGlobalSettings(json);
globalSettings.ProjectSearchPaths.Should().BeEmpty();
}
[Fact]
public void It_sets_searchPaths_to_projects_when_projects_is_an_array_in_the_GlobalJson()
{
var projectsSearchPaths = new[] {"somepath1", "somepath2"};
var json = new JObject();
json.Add("projects", new JArray(projectsSearchPaths));
var globalSettings = GetGlobalSettings(json);
globalSettings.ProjectSearchPaths.Should().Contain(projectsSearchPaths);
}
[Fact]
public void It_sets_searchPaths_to_sources_when_sources_is_an_array_in_the_GlobalJson()
{
var sourcesSearchPaths = new[] { "somepath1", "somepath2" };
var json = new JObject();
json.Add("sources", new JArray(sourcesSearchPaths));
var globalSettings = GetGlobalSettings(json);
globalSettings.ProjectSearchPaths.Should().Contain(sourcesSearchPaths);
}
[Fact]
public void It_sets_searchPaths_to_projects_when_both_projects_and_sources_are_arrays_in_the_GlobalJson()
{
var projectsSearchPaths = new[] { "somepath1", "somepath2" };
var sourcesSearchPaths = new[] { "someotherpath1", "someotherpath2" };
var json = new JObject();
json.Add("projects", new JArray(projectsSearchPaths));
json.Add("sources", new JArray(sourcesSearchPaths));
var globalSettings = GetGlobalSettings(json);
globalSettings.ProjectSearchPaths.Should().Contain(projectsSearchPaths);
}
[Fact]
public void It_leaves_packagesPath_null_when_packages_is_not_set_in_the_GlobalJson()
{
var json = new JObject();
var globalSettings = GetGlobalSettings(json);
globalSettings.PackagesPath.Should().BeNull();
}
[Fact]
public void It_sets_packagesPath_to_packages_when_it_is_set_in_the_GlobalJson()
{
const string somePackagesPath = "some packages path";
var json = new JObject();
json.Add("packages", somePackagesPath);
var globalSettings = GetGlobalSettings(json);
globalSettings.PackagesPath.Should().Be(somePackagesPath);
}
[Fact]
public void It_sets_filePath_to_the_path_passed_in()
{
var json = new JObject();
var globalSettings = GetGlobalSettings(json);
globalSettings.FilePath.Should().Be(SomePath);
}
public GlobalSettings GetGlobalSettings(JObject json)
{
using (var stream = new MemoryStream())
{
using (var sw = new StreamWriter(stream, Encoding.UTF8, 256, true))
{
using (var writer = new JsonTextWriter(sw))
{
writer.Formatting = Formatting.Indented;
json.WriteTo(writer);
}
stream.Position = 0;
return GlobalSettings.GetGlobalSettings(stream, SomePath);
}
}
}
}
}

View file

@ -0,0 +1,84 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Newtonsoft.Json.Linq;
using Xunit;
using Microsoft.DotNet.ProjectModel.Files;
using FluentAssertions;
using System.IO;
namespace Microsoft.DotNet.ProjectModel.Tests
{
public class GivenThatIWantToReadNamedResources
{
private readonly string ProjectFilePath = AppContext.BaseDirectory;
[Fact]
public void It_returns_an_empty_dictionary_when_no_namedResource_is_set()
{
var json = new JObject();
var namedResources = NamedResourceReader.ReadNamedResources(json, ProjectFilePath);
namedResources.Should().BeEmpty();
}
[Fact]
public void It_throws_when_the_namedResource_is_not_a_Json_object()
{
var json = new JObject();
json.Add("namedResource", "not an object");
Action action = () => NamedResourceReader.ReadNamedResources(json, ProjectFilePath);
action.ShouldThrow<FileFormatException>("Value must be an object");
}
[Fact]
public void It_throws_when_a_specified_namedResource_value_is_not_a_string()
{
var json = new JObject();
var namedResources = new JObject();
json.Add("namedResource", namedResources);
namedResources.Add("System.Strings", new JObject());
Action action = () => NamedResourceReader.ReadNamedResources(json, ProjectFilePath);
action.ShouldThrow<FileFormatException>("Value must be string.");
}
[Fact]
public void It_throws_when_a_specified_namedResource_value_contains_a_wild_card()
{
var json = new JObject();
var namedResources = new JObject();
json.Add("namedResource", namedResources);
namedResources.Add("System.Strings", "*");
Action action = () => NamedResourceReader.ReadNamedResources(json, ProjectFilePath);
action.ShouldThrow<FileFormatException>("Value cannot contain wildcards.");
}
[Fact]
public void It_adds_named_resources_and_uses_the_full_path_for_their_values()
{
var json = new JObject();
var namedResourcesJson = new JObject();
json.Add("namedResource", namedResourcesJson);
namedResourcesJson.Add("System.Strings", "System.Strings.resx");
namedResourcesJson.Add("Another.System.Strings", "Another.System.Strings.resx");
var namedResources = NamedResourceReader.ReadNamedResources(json, ProjectFilePath);
namedResources["System.Strings"].Should().Be(
Path.GetFullPath(Path.Combine(Path.GetDirectoryName(ProjectFilePath), "System.Strings.resx")));
namedResources["Another.System.Strings"].Should().Be(
Path.GetFullPath(Path.Combine(Path.GetDirectoryName(ProjectFilePath), "Another.System.Strings.resx")));
}
}
}

View file

@ -1,5 +1,8 @@
{
"version": "1.0.0-*",
"compilationOptions": {
"keyFile": "../../tools/test_key.snk"
},
"dependencies": {
"Microsoft.NETCore.App": "1.0.0-rc2-23931",
"System.Runtime.Serialization.Primitives": "4.1.1-rc2-23931",

View file

@ -2,13 +2,13 @@
using Microsoft.DotNet.Tools.Test.Utilities;
using Xunit;
using Microsoft.DotNet.TestFramework;
using Newtonsoft.Json.Linq;
using FluentAssertions;
namespace Microsoft.DotNet.Tools.Builder.Tests
{
public class BuildPortableTests : TestBase
{
[Fact]
public void BuildingAPortableProjectProducesDepsJsonFile()
{
@ -49,6 +49,30 @@ namespace Microsoft.DotNet.Tools.Builder.Tests
netstandardappOutput.Should().Exist().And.HaveFile("PortableApp.runtimeconfig.json");
}
[Fact]
public void TheRuntimeOptionsGetsCopiedFromProjectJsonToRuntimeConfigJson()
{
var testInstance = TestAssetsManager.CreateTestInstance("PortableTests")
.WithLockFiles();
var netstandardappOutput = Build(testInstance);
var runtimeConfigJsonPath = Path.Combine(netstandardappOutput.FullName, "PortableApp.runtimeconfig.json");
using (var stream = new FileStream(runtimeConfigJsonPath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var reader = new StreamReader(stream);
var rawProject = JObject.Parse(reader.ReadToEnd());
var runtimeOptions = rawProject["runtimeOptions"];
runtimeOptions["somethingString"].Value<string>().Should().Be("anything");
runtimeOptions["somethingBoolean"].Value<bool>().Should().BeTrue();
runtimeOptions["someArray"].ToObject<string[]>().Should().Contain("one", "two");
runtimeOptions["someObject"].Value<JObject>()["someProperty"].Value<string>().Should().Be("someValue");
}
}
[Fact]
public void BuildingAPortableProjectProducesARuntimeConfigDevJsonFile()
{

View file

@ -8,6 +8,8 @@ using Microsoft.Extensions.PlatformAbstractions;
using Xunit;
using System.Linq;
using Microsoft.DotNet.TestFramework;
using Newtonsoft.Json.Linq;
using FluentAssertions;
namespace Microsoft.DotNet.Tools.Builder.Tests
{
@ -24,6 +26,41 @@ namespace Microsoft.DotNet.Tools.Builder.Tests
netstandardappOutput.Should().Exist().And.HaveFile("StandaloneApp.runtimeconfig.dev.json");
}
[Fact]
public void BuildingAStandAloneProjectProducesARuntimeConfigJsonFile()
{
var testInstance = TestAssetsManager.CreateTestInstance("PortableTests")
.WithLockFiles();
var netstandardappOutput = Build(testInstance);
netstandardappOutput.Should().Exist().And.HaveFile("StandaloneApp.runtimeconfig.json");
}
[Fact]
public void TheRuntimeOptionsGetsCopiedFromProjectJsonToRuntimeConfigJson()
{
var testInstance = TestAssetsManager.CreateTestInstance("PortableTests")
.WithLockFiles();
var netstandardappOutput = Build(testInstance);
var runtimeConfigJsonPath = Path.Combine(netstandardappOutput.FullName, "StandaloneApp.runtimeconfig.json");
using (var stream = new FileStream(runtimeConfigJsonPath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var reader = new StreamReader(stream);
var rawProject = JObject.Parse(reader.ReadToEnd());
var runtimeOptions = rawProject["runtimeOptions"];
runtimeOptions["somethingString"].Value<string>().Should().Be("anything");
runtimeOptions["somethingBoolean"].Value<bool>().Should().BeTrue();
runtimeOptions["someArray"].ToObject<string[]>().Should().Contain("one", "two");
runtimeOptions["someObject"].Value<JObject>()["someProperty"].Value<string>().Should().Be("someValue");
}
}
public DirectoryInfo Build(TestInstance testInstance)
{
var projectPath = Path.Combine(testInstance.TestRoot, "StandaloneApp");

View file

@ -9,6 +9,8 @@
"Microsoft.DotNet.Cli.Utils": {
"target": "project"
},
"Newtonsoft.Json": "7.0.1",
"System.Runtime.Serialization.Primitives": "4.1.1-rc2-23929",
"xunit": "2.1.0",
"dotnet-test-xunit": "1.0.0-dev-128011-22"
},

BIN
tools/test_key.snk Normal file

Binary file not shown.