Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crossplat #10

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/Mongo2Go/Helper/IMongoBinaryLocator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Mongo2Go.Helper
{
public interface IMongoBinaryLocator
{
string ResolveBinariesDirectory ();
}
}
37 changes: 37 additions & 0 deletions src/Mongo2Go/Helper/MongoBinaryLocator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;

namespace Mongo2Go.Helper
{

public class MongoBinaryLocator : IMongoBinaryLocator
{
private string nugetPrefix = @"packages\Mongo2Go*";
private string searchPattern = "";

public MongoBinaryLocator (string binSearchPattern)
{
if (string.IsNullOrEmpty (binSearchPattern)) {
throw new ArgumentException ("Missing the search pattern for finding the mongoDb binaries.", "binSearchPattern");
}

searchPattern = binSearchPattern;
}

public string ResolveBinariesDirectory ()
{
// 1st: path when installed via nuget
// 2nd: path when started from solution
string binariesFolder = FolderSearch.CurrentExecutingDirectory ().FindFolderUpwards (System.IO.Path.Combine (nugetPrefix, searchPattern)) ??
FolderSearch.CurrentExecutingDirectory ().FindFolderUpwards (searchPattern);

if (binariesFolder == null) {
throw new MonogDbBinariesNotFoundException (string.Format (
"Could not find Mongo binaries using {0}. We walk up the directories {1} levels from {2}",
searchPattern,
FolderSearch.MaxLevelOfRecursion,
FolderSearch.CurrentExecutingDirectory ()));
}
return binariesFolder;
}
}
}
2 changes: 1 addition & 1 deletion src/Mongo2Go/Helper/PortPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public int GetNextOpenPort()
{
lock (_lock)
{
PortWatcher portWatcher = new PortWatcher();
IPortWatcher portWatcher = PortWatcherFactory.CreatePortWatcher();
int newAvailablePort = portWatcher.FindOpenPort(_startPort);

_startPort = newAvailablePort + 1;
Expand Down
29 changes: 29 additions & 0 deletions src/Mongo2Go/Helper/PortWatcherFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;

namespace Mongo2Go.Helper
{
public class PortWatcherFactory
{
public static IPortWatcher CreatePortWatcher()
{
IPortWatcher portwatcher = null;

switch (Environment.OSVersion.Platform)
{
case PlatformID.Unix:
portwatcher = new UnixPortWatcher ();
break;

default:
portwatcher = new PortWatcher ();
break;
}

return portwatcher;
}
}
}
47 changes: 47 additions & 0 deletions src/Mongo2Go/Helper/UnixPortWatcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System.Net;
using System.Net.Sockets;

namespace Mongo2Go.Helper
{

public class UnixPortWatcher : IPortWatcher
{
public int FindOpenPort (int startPort)
{
int port = startPort;
do {
if (IsPortAvailable (port)) {
break;
}

if (port == MongoDbDefaults.TestStartPort + 100) {
throw new NoFreePortFoundException ();
}

++port;

} while (true);

return port;
}

public bool IsPortAvailable (int portNumber)
{
bool result = false;

TcpListener tcpListener = new TcpListener (IPAddress.Loopback, portNumber);
try {
tcpListener.Start ();
} catch (SocketException) {
result = false;

} finally
{
tcpListener.Stop ();
result = true;
}

return result;
}
}
}
4 changes: 4 additions & 0 deletions src/Mongo2Go/Mongo2Go.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@
<Compile Include="State.cs">
<DependentUpon>MongoDbRunner.cs</DependentUpon>
</Compile>
<Compile Include="Helper\MongoBinaryLocator.cs" />
<Compile Include="Helper\IMongoBinaryLocator.cs" />
<Compile Include="Helper\UnixPortWatcher.cs" />
<Compile Include="Helper\PortWatcherFactory.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Expand Down
56 changes: 17 additions & 39 deletions src/Mongo2Go/MongoDbRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ public partial class MongoDbRunner : IDisposable
private readonly IFileSystem _fileSystem;
private readonly string _dataDirectoryWithPort;
private readonly int _port;

private const string BinariesSearchPattern = @"packages\Mongo2Go*\tools\mongodb-win32*\bin";
private const string BinariesSearchPatternSolution = @"tools\mongodb-win32*\bin";
private readonly IMongoBinaryLocator _mongoBin;

/// <summary>
/// State of the current MongoDB instance
Expand All @@ -31,14 +29,14 @@ public partial class MongoDbRunner : IDisposable
/// On dispose: kills them and deletes their data directory
/// </summary>
/// <remarks>Should be used for integration tests</remarks>
public static MongoDbRunner Start(string dataDirectory = MongoDbDefaults.DataDirectory)
public static MongoDbRunner Start(string mongoBinSearchPattern = @"tools\mongodb-win32*\bin", string dataDirectory = MongoDbDefaults.DataDirectory)
{
return new MongoDbRunner(PortPool.GetInstance, new FileSystem(), new MongoDbProcessStarter(), dataDirectory);
return new MongoDbRunner(PortPool.GetInstance, new FileSystem(), new MongoDbProcessStarter(), new MongoBinaryLocator (mongoBinSearchPattern), dataDirectory);
}

internal static MongoDbRunner StartUnitTest(IPortPool portPool, IFileSystem fileSystem, IMongoDbProcessStarter processStarter)
internal static MongoDbRunner StartUnitTest(IPortPool portPool, IFileSystem fileSystem, IMongoDbProcessStarter processStarter, IMongoBinaryLocator mongoBin)
{
return new MongoDbRunner(portPool, fileSystem, processStarter, MongoDbDefaults.DataDirectory);
return new MongoDbRunner(portPool, fileSystem, processStarter, mongoBin, MongoDbDefaults.DataDirectory);
}

/// <summary>
Expand All @@ -48,39 +46,40 @@ internal static MongoDbRunner StartUnitTest(IPortPool portPool, IFileSystem file
/// Should be used for local debugging only
/// WARNING: one single instance on one single machine is not a suitable setup for productive environments!!!
/// </remarks>
public static MongoDbRunner StartForDebugging(string dataDirectory = MongoDbDefaults.DataDirectory)
public static MongoDbRunner StartForDebugging(string mongoBinSearchPattern = @"tools\mongodb-win32*\bin", string dataDirectory = MongoDbDefaults.DataDirectory)
{
return new MongoDbRunner(new ProcessWatcher(), new PortWatcher(), new FileSystem(), new MongoDbProcessStarter(), dataDirectory);
return new MongoDbRunner(new ProcessWatcher(), new PortWatcher(), new FileSystem(), new MongoDbProcessStarter(), new MongoBinaryLocator(mongoBinSearchPattern), dataDirectory);
}

internal static MongoDbRunner StartForDebuggingUnitTest(IProcessWatcher processWatcher, IPortWatcher portWatcher, IFileSystem fileSystem, IMongoDbProcessStarter processStarter)
internal static MongoDbRunner StartForDebuggingUnitTest(IProcessWatcher processWatcher, IPortWatcher portWatcher, IFileSystem fileSystem, IMongoDbProcessStarter processStarter, IMongoBinaryLocator mongoBin)
{
return new MongoDbRunner(processWatcher, portWatcher, fileSystem, processStarter, MongoDbDefaults.DataDirectory);
return new MongoDbRunner(processWatcher, portWatcher, fileSystem, processStarter,mongoBin, MongoDbDefaults.DataDirectory);
}

/// <summary>
/// Executes Mongoimport on the associated MongoDB Instace
/// </summary>
public void Import(string database, string collection, string inputFile, bool drop)
{
MongoImportExport.Import(BinariesDirectory, _port, database, collection, inputFile, drop);
MongoImportExport.Import(_mongoBin.ResolveBinariesDirectory(), _port, database, collection, inputFile, drop);
}

/// <summary>
/// Executes Mongoexport on the associated MongoDB Instace
/// </summary>
public void Export(string database, string collection, string outputFile)
{
MongoImportExport.Export(BinariesDirectory, _port, database, collection, outputFile);
MongoImportExport.Export(_mongoBin.ResolveBinariesDirectory(), _port, database, collection, outputFile);
}

/// <summary>
/// usage: local debugging
/// </summary>
private MongoDbRunner(IProcessWatcher processWatcher, IPortWatcher portWatcher, IFileSystem fileSystem, IMongoDbProcessStarter processStarter, string dataDirectory)
private MongoDbRunner(IProcessWatcher processWatcher, IPortWatcher portWatcher, IFileSystem fileSystem, IMongoDbProcessStarter processStarter,IMongoBinaryLocator mongoBin, string dataDirectory)
{
_fileSystem = fileSystem;
_port = MongoDbDefaults.DefaultPort;
_mongoBin = mongoBin;

ConnectionString = "mongodb://localhost:{0}/".Formatted(_port);

Expand All @@ -97,49 +96,28 @@ private MongoDbRunner(IProcessWatcher processWatcher, IPortWatcher portWatcher,

_fileSystem.CreateFolder(dataDirectory);
_fileSystem.DeleteFile(@"{0}\{1}".Formatted(dataDirectory, MongoDbDefaults.Lockfile));
_mongoDbProcess = processStarter.Start(BinariesDirectory, dataDirectory, _port, true);
_mongoDbProcess = processStarter.Start(_mongoBin.ResolveBinariesDirectory(), dataDirectory, _port, true);

State = State.Running;
}

/// <summary>
/// usage: integration tests
/// </summary>
private MongoDbRunner(IPortPool portPool, IFileSystem fileSystem, IMongoDbProcessStarter processStarter, string dataDirectory)
private MongoDbRunner(IPortPool portPool, IFileSystem fileSystem, IMongoDbProcessStarter processStarter, IMongoBinaryLocator mongoBin, string dataDirectory)
{
_fileSystem = fileSystem;
_port = portPool.GetNextOpenPort();
_mongoBin = mongoBin;

ConnectionString = "mongodb://localhost:{0}/".Formatted(_port);

_dataDirectoryWithPort = "{0}_{1}".Formatted(dataDirectory, _port);
_fileSystem.CreateFolder(_dataDirectoryWithPort);
_fileSystem.DeleteFile(@"{0}\{1}".Formatted(_dataDirectoryWithPort, MongoDbDefaults.Lockfile));
_mongoDbProcess = processStarter.Start(BinariesDirectory, _dataDirectoryWithPort, _port);
_mongoDbProcess = processStarter.Start(_mongoBin.ResolveBinariesDirectory(), _dataDirectoryWithPort, _port);

State = State.Running;
}

private static string BinariesDirectory
{
get
{
// 1st: path when installed via nuget
// 2nd: path when started from solution
string binariesFolder = FolderSearch.CurrentExecutingDirectory().FindFolderUpwards(BinariesSearchPattern) ??
FolderSearch.CurrentExecutingDirectory().FindFolderUpwards(BinariesSearchPatternSolution);

if (binariesFolder == null)
{
throw new MonogDbBinariesNotFoundException(string.Format(
"Could not find Mongo binaries using {0} or {1}. We walk up the directories {2} levels from {3}",
BinariesSearchPattern,
BinariesSearchPatternSolution,
FolderSearch.MaxLevelOfRecursion,
FolderSearch.CurrentExecutingDirectory()));
}
return binariesFolder;
}
}
}
}
3 changes: 3 additions & 0 deletions src/Mongo2GoTests/Mongo2GoTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@
<Name>Mongo2Go</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Expand Down
13 changes: 10 additions & 3 deletions src/Mongo2GoTests/Runner/RunnerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class when_instanciating_the_runner_for_integration_test
static Mock<IPortPool> portPoolMock;
static Mock<IFileSystem> fileSystemMock;
static Mock<IMongoDbProcessStarter> processStarterMock;
static Mock<IMongoBinaryLocator> binaryLocatorMock;

static readonly string exptectedDataDirectory = "{0}_{1}".Formatted(MongoDbDefaults.DataDirectory, MongoDbDefaults.TestStartPort + 1);
static readonly string exptectedLogfile = @"{0}_{1}\{2}".Formatted(MongoDbDefaults.DataDirectory, MongoDbDefaults.TestStartPort + 1, MongoDbDefaults.Lockfile);
Expand All @@ -32,9 +33,12 @@ public class when_instanciating_the_runner_for_integration_test

processStarterMock = new Mock<IMongoDbProcessStarter>();
processStarterMock.Setup(m => m.Start(Moq.It.IsAny<string>(), Moq.It.IsAny<string>(), Moq.It.IsAny<int>())).Returns(processMock.Object);

binaryLocatorMock = new Mock<IMongoBinaryLocator> ();

};

Because of = () => runner = MongoDbRunner.StartUnitTest(portPoolMock.Object, fileSystemMock.Object, processStarterMock.Object);
Because of = () => runner = MongoDbRunner.StartUnitTest(portPoolMock.Object, fileSystemMock.Object, processStarterMock.Object, binaryLocatorMock.Object);

It should_create_the_data_directory = () => fileSystemMock.Verify(x => x.CreateFolder(exptectedDataDirectory), Times.Exactly(1));
It should_delete_old_lock_file = () => fileSystemMock.Verify(x => x.DeleteFile(exptectedLogfile), Times.Exactly(1));
Expand All @@ -53,6 +57,7 @@ public class when_instanciating_the_runner_for_local_debugging
static Mock<IProcessWatcher> processWatcherMock;
static Mock<IFileSystem> fileSystemMock;
static Mock<IMongoDbProcessStarter> processStarterMock;
static Mock<IMongoBinaryLocator> binaryLocatorMock;

static readonly string exptectedLogfile = @"{0}\{1}".Formatted(MongoDbDefaults.DataDirectory, MongoDbDefaults.Lockfile);

Expand All @@ -68,10 +73,12 @@ public class when_instanciating_the_runner_for_local_debugging

var processMock = new Mock<IMongoDbProcess>();
processStarterMock = new Mock<IMongoDbProcessStarter>();
processStarterMock.Setup(m => m.Start(Moq.It.IsAny<string>(), MongoDbDefaults.DataDirectory, MongoDbDefaults.DefaultPort, true)).Returns(processMock.Object);
processStarterMock.Setup(m => m.Start(Moq.It.IsAny<string>(), MongoDbDefaults.DataDirectory, MongoDbDefaults.DefaultPort, true)).Returns(processMock.Object);

binaryLocatorMock = new Mock<IMongoBinaryLocator> ();
};

Because of = () => runner = MongoDbRunner.StartForDebuggingUnitTest(processWatcherMock.Object, portWatcherMock.Object, fileSystemMock.Object, processStarterMock.Object);
Because of = () => runner = MongoDbRunner.StartForDebuggingUnitTest(processWatcherMock.Object, portWatcherMock.Object, fileSystemMock.Object, processStarterMock.Object, binaryLocatorMock.Object);

It should_check_for_already_running_process = () => processWatcherMock.Verify(x => x.IsProcessRunning(MongoDbDefaults.ProcessName), Times.Exactly(1));
It should_check_the_default_port = () => portWatcherMock.Verify(x => x.IsPortAvailable(MongoDbDefaults.DefaultPort), Times.Exactly(1));
Expand Down