Skip to content

Commit 61a8475

Browse files
committed
green: implemented PackagesWithDuplicateAssemblies scenario
1 parent 9457a09 commit 61a8475

8 files changed

Lines changed: 135 additions & 116 deletions

File tree

Lines changed: 85 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,111 @@
1-
using System.Collections.Generic;
2-
using System.Linq;
3-
using System.Reflection;
4-
5-
namespace ScriptCs.Contracts
1+
namespace ScriptCs.Contracts
62
{
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Reflection;
6+
using System;
7+
using System.IO;
8+
79
public class AssemblyReferences
810
{
11+
private readonly Dictionary<string, Assembly> _assemblies = new Dictionary<string, Assembly>();
12+
private readonly Dictionary<string, string> _paths = new Dictionary<string, string>();
13+
914
public AssemblyReferences()
1015
: this(Enumerable.Empty<string>())
1116
{
1217
}
1318

14-
public AssemblyReferences(IEnumerable<string> pathReferences)
15-
: this(pathReferences, Enumerable.Empty<Assembly>())
19+
public AssemblyReferences(IEnumerable<string> paths)
20+
: this(paths, Enumerable.Empty<Assembly>())
1621
{
1722
}
1823

19-
public AssemblyReferences(IEnumerable<string> pathReferences, IEnumerable<Assembly> assemblies)
24+
public AssemblyReferences(IEnumerable<string> paths, IEnumerable<Assembly> assemblies)
2025
{
21-
Guard.AgainstNullArgument("pathReferences", pathReferences);
26+
Guard.AgainstNullArgument("paths", paths);
2227
Guard.AgainstNullArgument("assemblies", assemblies);
2328

24-
PathReferences = new HashSet<string>(pathReferences);
25-
Assemblies = new HashSet<Assembly>(assemblies);
29+
foreach (var assembly in assemblies.Where(assembly => assembly != null))
30+
{
31+
var name = assembly.GetName().Name;
32+
if (!_assemblies.ContainsKey(name))
33+
{
34+
_assemblies.Add(name, assembly);
35+
}
36+
}
37+
38+
foreach (var path in paths)
39+
{
40+
var name = Path.GetFileName(path);
41+
if (name == null)
42+
{
43+
continue;
44+
}
45+
46+
if (name.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) ||
47+
name.EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
48+
{
49+
name = Path.GetFileNameWithoutExtension(name);
50+
}
51+
52+
if (!_paths.ContainsKey(name) && !_assemblies.ContainsKey(name))
53+
{
54+
_paths.Add(name, path);
55+
}
56+
}
2657
}
2758

28-
public HashSet<string> PathReferences { get; private set; }
29-
public HashSet<Assembly> Assemblies { get; private set; }
59+
public IEnumerable<Assembly> Assemblies
60+
{
61+
get { return _assemblies.Values.ToArray(); }
62+
}
63+
64+
public IEnumerable<string> PathReferences
65+
{
66+
get { return _paths.Values.ToArray(); }
67+
}
68+
69+
public AssemblyReferences Union(AssemblyReferences references)
70+
{
71+
Guard.AgainstNullArgument("references", references);
72+
73+
return new AssemblyReferences(PathReferences.Union(references.PathReferences), Assemblies.Union(references.Assemblies));
74+
}
3075

31-
public AssemblyReferences Except(AssemblyReferences obj)
76+
public AssemblyReferences Union(IEnumerable<Assembly> assemblies)
3277
{
33-
Guard.AgainstNullArgument("obj", obj);
78+
Guard.AgainstNullArgument("assemblies", assemblies);
79+
80+
return new AssemblyReferences(PathReferences, Assemblies.Union(assemblies));
81+
}
82+
83+
public AssemblyReferences Union(IEnumerable<string> paths)
84+
{
85+
Guard.AgainstNullArgument("paths", paths);
86+
87+
return new AssemblyReferences(PathReferences.Union(paths), Assemblies);
88+
}
89+
90+
public AssemblyReferences Except(AssemblyReferences references)
91+
{
92+
Guard.AgainstNullArgument("references", references);
93+
94+
return new AssemblyReferences(PathReferences.Except(references.PathReferences), Assemblies.Except(references.Assemblies));
95+
}
96+
97+
public AssemblyReferences Except(IEnumerable<Assembly> assemblies)
98+
{
99+
Guard.AgainstNullArgument("assemblies", assemblies);
34100

35-
return new AssemblyReferences(PathReferences.Except(obj.PathReferences), Assemblies.Except(obj.Assemblies));
101+
return new AssemblyReferences(PathReferences, Assemblies.Except(assemblies));
36102
}
37103

38-
public void Union(AssemblyReferences obj)
104+
public AssemblyReferences Except(IEnumerable<string> paths)
39105
{
40-
Guard.AgainstNullArgument("obj", obj);
106+
Guard.AgainstNullArgument("paths", paths);
41107

42-
PathReferences.UnionWith(obj.PathReferences);
43-
Assemblies.UnionWith(obj.Assemblies);
108+
return new AssemblyReferences(PathReferences.Except(paths), Assemblies);
44109
}
45110
}
46111
}

src/ScriptCs.Core/ScriptExecutor.cs

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -62,51 +62,28 @@ public void AddReferences(params Assembly[] assemblies)
6262
{
6363
Guard.AgainstNullArgument("assemblies", assemblies);
6464

65-
foreach (var assembly in assemblies
66-
.Where(assembly =>
67-
assembly != typeof(ScriptExecutor).Assembly && assembly != typeof(IScriptEnvironment).Assembly))
68-
{
69-
References.Assemblies.Add(assembly);
70-
}
65+
References = References.Union(assemblies);
7166
}
7267

7368
public void RemoveReferences(params Assembly[] assemblies)
7469
{
7570
Guard.AgainstNullArgument("assemblies", assemblies);
7671

77-
foreach (var assembly in assemblies)
78-
{
79-
References.Assemblies.Remove(assembly);
80-
}
72+
References = References.Except(assemblies);
8173
}
8274

8375
public void AddReferences(params string[] paths)
8476
{
8577
Guard.AgainstNullArgument("paths", paths);
8678

87-
foreach (var path in paths
88-
.Where(path =>
89-
!string.Equals(
90-
Path.GetFileName(path),
91-
Path.GetFileName(typeof(ScriptExecutor).Assembly.Location),
92-
StringComparison.OrdinalIgnoreCase) &&
93-
!string.Equals(
94-
Path.GetFileName(path),
95-
Path.GetFileName(typeof(IScriptEnvironment).Assembly.Location),
96-
StringComparison.OrdinalIgnoreCase)))
97-
{
98-
References.PathReferences.Add(path);
99-
}
79+
References = References.Union(paths);
10080
}
10181

10282
public void RemoveReferences(params string[] paths)
10383
{
10484
Guard.AgainstNullArgument("paths", paths);
10585

106-
foreach (var path in paths)
107-
{
108-
References.PathReferences.Remove(path);
109-
}
86+
References = References.Except(paths);
11087
}
11188

11289
public void RemoveNamespaces(params string[] namespaces)
@@ -153,7 +130,7 @@ public virtual ScriptResult Execute(string script, params string[] scriptArgs)
153130
{
154131
var path = Path.IsPathRooted(script) ? script : Path.Combine(FileSystem.CurrentDirectory, script);
155132
var result = FilePreProcessor.ProcessFile(path);
156-
References.PathReferences.UnionWith(result.References);
133+
References = References.Union(result.References);
157134
var namespaces = Namespaces.Union(result.Namespaces);
158135
ScriptEngine.FileName = Path.GetFileName(path);
159136

@@ -179,7 +156,7 @@ protected internal void AddContractsIfNotPresent(HashSet<string> references )
179156
public virtual ScriptResult ExecuteScript(string script, params string[] scriptArgs)
180157
{
181158
var result = FilePreProcessor.ProcessScript(script);
182-
References.PathReferences.UnionWith(result.References);
159+
References = References.Union(result.References);
183160
var namespaces = Namespaces.Union(result.Namespaces);
184161

185162
Logger.Debug("Starting execution in engine");

src/ScriptCs.Engine.Mono/MonoScriptEngine.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public ScriptResult Execute(
5555
Guard.AgainstNullArgument("references", references);
5656
Guard.AgainstNullArgument("scriptPackSession", scriptPackSession);
5757

58-
references.PathReferences.UnionWith(scriptPackSession.References);
58+
references = references.Union(scriptPackSession.References);
5959

6060
SessionState<Evaluator> sessionState;
6161
var isFirstExecution = !scriptPackSession.State.ContainsKey(SessionKey);

src/ScriptCs.Engine.Roslyn/RoslynScriptEngine.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ public ScriptResult Execute(string code, string[] scriptArgs, AssemblyReferences
4747
Logger.Debug("Starting to create execution components");
4848
Logger.Debug("Creating script host");
4949

50-
var executionReferences = new AssemblyReferences(references.PathReferences, references.Assemblies);
51-
executionReferences.PathReferences.UnionWith(scriptPackSession.References);
50+
var executionReferences = new AssemblyReferences(references.PathReferences, references.Assemblies)
51+
.Union(scriptPackSession.References);
5252

5353
SessionState<Session> sessionState;
5454

@@ -108,14 +108,14 @@ public ScriptResult Execute(string code, string[] scriptArgs, AssemblyReferences
108108
{
109109
Logger.DebugFormat("Adding reference to {0}", reference);
110110
sessionState.Session.AddReference(reference);
111-
sessionState.References.PathReferences.Add(reference);
111+
sessionState.References = sessionState.References.Union(new[] { reference });
112112
}
113113

114114
foreach (var assembly in newReferences.Assemblies)
115115
{
116116
Logger.DebugFormat("Adding reference to {0}", assembly.FullName);
117117
sessionState.Session.AddReference(assembly);
118-
sessionState.References.Assemblies.Add(assembly);
118+
sessionState.References = sessionState.References.Union(new[] { assembly });
119119
}
120120

121121
var newNamespaces = namespaces.Except(sessionState.Namespaces);

test/ScriptCs.Core.Tests/ScriptExecutorTests.cs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -519,18 +519,18 @@ public class TheAddReferencesMethod
519519
public void ShouldAddReferenceToEachAssembly(ScriptExecutor executor)
520520
{
521521
// arrange
522-
var calling = Assembly.GetCallingAssembly();
523-
var executing = Assembly.GetExecutingAssembly();
524-
var entry = Assembly.GetEntryAssembly();
522+
var assembly1 = typeof(Mock).Assembly;
523+
var assembly2 = typeof(FrozenAttribute).Assembly;
524+
var assembly3 = typeof(Assert).Assembly;
525525

526526
// act
527-
executor.AddReferences(calling, executing, entry, entry);
527+
executor.AddReferences(assembly1, assembly2, assembly3, assembly3);
528528

529529
// assert
530-
executor.References.Assemblies.ShouldContain(calling);
531-
executor.References.Assemblies.ShouldContain(executing);
532-
executor.References.Assemblies.ShouldContain(entry);
533-
executor.References.Assemblies.Count.ShouldEqual(3);
530+
executor.References.Assemblies.ShouldContain(assembly1);
531+
executor.References.Assemblies.ShouldContain(assembly2);
532+
executor.References.Assemblies.ShouldContain(assembly3);
533+
executor.References.Assemblies.Count().ShouldEqual(3);
534534
}
535535
}
536536

@@ -540,19 +540,19 @@ public class TheRemoveReferencesMethod
540540
public void ShouldRemoveReferenceToEachAssembly(ScriptExecutor executor)
541541
{
542542
// arrange
543-
var calling = Assembly.GetCallingAssembly();
544-
var executing = Assembly.GetExecutingAssembly();
545-
var entry = Assembly.GetEntryAssembly();
546-
executor.AddReferences(calling, executing, entry);
543+
var assembly1 = typeof(Mock).Assembly;
544+
var assembly2 = typeof(FrozenAttribute).Assembly;
545+
var assembly3 = typeof(Assert).Assembly;
546+
executor.AddReferences(assembly1, assembly2, assembly3);
547547

548548
// act
549-
executor.RemoveReferences(calling, executing);
549+
executor.RemoveReferences(assembly1, assembly2);
550550

551551
// assert
552-
executor.References.Assemblies.ShouldNotContain(calling);
553-
executor.References.Assemblies.ShouldNotContain(executing);
554-
executor.References.Assemblies.ShouldContain(entry);
555-
executor.References.Assemblies.Count.ShouldEqual(1);
552+
executor.References.Assemblies.ShouldNotContain(assembly1);
553+
executor.References.Assemblies.ShouldNotContain(assembly2);
554+
executor.References.Assemblies.ShouldContain(assembly3);
555+
executor.References.Assemblies.Count().ShouldEqual(1);
556556
}
557557
}
558558
}

test/ScriptCs.Engine.Mono.Tests/MonoScriptEngineTests.cs

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,7 @@ public void ShouldAddNewReferencesIfTheyAreProvided(
139139

140140
var session = new SessionState<Evaluator> { Session = new Evaluator(new CompilerContext( new CompilerSettings(), new ConsoleReportPrinter())) };
141141
scriptPackSession.State[MonoScriptEngine.SessionKey] = session;
142-
var refs = new AssemblyReferences();
143-
refs.PathReferences.Add("System");
142+
var refs = new AssemblyReferences(new[] { "System" });
144143

145144
// Act
146145
engine.Execute(Code, new string[0], refs, Enumerable.Empty<string>(), scriptPackSession);
@@ -163,8 +162,7 @@ public void ShouldReturnAScriptResult(
163162

164163
var session = new SessionState<Evaluator> { Session = new Evaluator(new CompilerContext( new CompilerSettings(), new ConsoleReportPrinter())) };
165164
scriptPackSession.State[MonoScriptEngine.SessionKey] = session;
166-
var refs = new AssemblyReferences();
167-
refs.PathReferences.Add("System");
165+
var refs = new AssemblyReferences(new[] { "System" });
168166

169167
// Act
170168
var result = engine.Execute(code, new string[0], refs, Enumerable.Empty<string>(), scriptPackSession);
@@ -217,8 +215,7 @@ public void ShouldNotReturnCompileExceptionIfCodeDoesCompile(
217215

218216
var session = new SessionState<Evaluator> { Session = new Evaluator(new CompilerContext( new CompilerSettings(), new ConsoleReportPrinter())) };
219217
scriptPackSession.State[MonoScriptEngine.SessionKey] = session;
220-
var refs = new AssemblyReferences();
221-
refs.PathReferences.Add("System");
218+
var refs = new AssemblyReferences(new[] { "System" });
222219

223220
// Act
224221
var result = engine.Execute(Code, new string[0], refs, Enumerable.Empty<string>(), scriptPackSession);
@@ -243,8 +240,7 @@ public void ShouldReturnExecuteExceptionIfCodeExecutionThrowsException(
243240

244241
var session = new SessionState<Evaluator> { Session = new Evaluator(new CompilerContext( new CompilerSettings(), new ConsoleReportPrinter())) };
245242
scriptPackSession.State[MonoScriptEngine.SessionKey] = session;
246-
var refs = new AssemblyReferences();
247-
refs.PathReferences.Add("System");
243+
var refs = new AssemblyReferences(new[] { "System" });
248244

249245
// Act
250246
var result = engine.Execute(Code, new string[0], refs, Enumerable.Empty<string>(), scriptPackSession);
@@ -267,8 +263,7 @@ public void ShouldNotReturnExecuteExceptionIfCodeExecutionDoesNotThrowAnExceptio
267263

268264
var session = new SessionState<Evaluator> { Session = new Evaluator(new CompilerContext( new CompilerSettings(), new ConsoleReportPrinter())) };
269265
scriptPackSession.State[MonoScriptEngine.SessionKey] = session;
270-
var refs = new AssemblyReferences();
271-
refs.PathReferences.Add("System");
266+
var refs = new AssemblyReferences(new[] { "System" });
272267

273268
// Act
274269
var result = engine.Execute(Code, new string[0], refs, Enumerable.Empty<string>(), scriptPackSession);
@@ -292,8 +287,7 @@ public void ShouldReturnReturnValueIfCodeExecutionReturnsValue(
292287

293288
var session = new SessionState<Evaluator> { Session = new Evaluator(new CompilerContext( new CompilerSettings(), new ConsoleReportPrinter())) };
294289
scriptPackSession.State[MonoScriptEngine.SessionKey] = session;
295-
var refs = new AssemblyReferences();
296-
refs.PathReferences.Add("System");
290+
var refs = new AssemblyReferences(new[] { "System" });
297291

298292
// Act
299293
var result = engine.Execute(Code, new string[0], refs, Enumerable.Empty<string>(), scriptPackSession);
@@ -316,8 +310,7 @@ public void ShouldNotReturnReturnValueIfCodeExecutionDoesNotReturnValue(
316310

317311
var session = new SessionState<Evaluator> { Session = new Evaluator(new CompilerContext( new CompilerSettings(), new ConsoleReportPrinter())) };
318312
scriptPackSession.State[MonoScriptEngine.SessionKey] = session;
319-
var refs = new AssemblyReferences();
320-
refs.PathReferences.Add("System");
313+
var refs = new AssemblyReferences(new[] { "System" });
321314

322315
// Act
323316
var result = engine.Execute(Code, new string[0], refs, Enumerable.Empty<string>(), scriptPackSession);
@@ -337,8 +330,7 @@ ScriptPackSession scriptPackSession
337330
// Arrange
338331
const string Code = "var theNumber = 42; //this should compile";
339332

340-
var refs = new AssemblyReferences();
341-
refs.PathReferences.Add("System");
333+
var refs = new AssemblyReferences(new[] { "System" });
342334

343335
scriptHostFactory.Setup(s => s.CreateScriptHost(It.IsAny<IScriptPackManager>(), It.IsAny<string[]>()))
344336
.Returns(new ScriptHost(manager.Object, null));

0 commit comments

Comments
 (0)