Reading a file path from another test project - c#

I have 2 projects as follows:
I have a test in UnitTest1.cs as follows:
public void TestMethod1()
{
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"Models.csproj");
var reader = File.ReadAllText(path);
var a = reader.Contains("PackageReference");
Assert.IsTrue(a);
}
How do read the file Models.csproj from UnitTest1.cs? The above code is showing path as \\Models.Tests\\bin\\Debug\\net6.0\\Models.csproj which is not correct because Models.csproj is not in Debug\net6.0.

Related

SQLite.Net Won't Create In Win IoT Library

I have been struggling to find a way of persisting an SQLite database on a Pi under Win IoT which can be accessed by different background applications (not concurrently).
I thought I had the answer when I discovered Libraries (Music, Pictures, Videos - but perversely not Documents, without more work). I can create a text file in one app and write it to the Pictures library's default folder. I can then read the text file with another app. File.Exists returns true. Bingo (I thought)!
However, SQLite will not create a database in the folder or open an existing database that I copy to the folder. SQLite.Net.SQLiteConnection returns an SQLite exception: "Could not open database file: C:\Data\Users\DefaultAccount\Pictures\MyDb.db (CannotOpen)" - no further clues.
The folder appears to grant full permissions. Does anyone have any ideas, please?
Creating and Writing a text file:
using System;
using Windows.ApplicationModel.Background;
using System.IO;
using System.Diagnostics;
//*** NOTE: Pictures Library checked in Package.appxmanifest 'Capabilities'
namespace LibraryTest
{
public sealed class StartupTask : IBackgroundTask
{
private BackgroundTaskDeferral Deferral;
public async void Run (IBackgroundTaskInstance taskInstance)
{
Deferral = taskInstance.GetDeferral ();
var myPictures = await Windows.Storage.StorageLibrary.GetLibraryAsync
(Windows.Storage.KnownLibraryId.Pictures);
string path = myPictures.SaveFolder.Path;
Debug.WriteLine ($"'Pictures' Folder: {path}");
string newFilePath = Path.Combine (path, "TestTextFile.txt");
Debug.WriteLine ($"New File Path: {newFilePath}");
try {
using ( var stream = File.OpenWrite (newFilePath) ) {
using ( var writer = new StreamWriter (stream) ) {
writer.Write ("This is some test text.");
}
}
Debug.WriteLine ($"File created OK");
}
catch (Exception ex) { Debug.WriteLine ($"Exception: {ex.Message}"); }
}
}
}
Produced:
'Pictures' Folder: C:\Data\Users\DefaultAccount\Pictures
New File Path: C:\Data\Users\DefaultAccount\Pictures\TestTextFile.txt
File created OK
Reading:
using System;
using Windows.ApplicationModel.Background;
using System.IO;
using System.Diagnostics;
//*** NOTE: Pictures Library checked in Package.appxmanifest 'Capabilities'
namespace ReadLibraryTest
{
public sealed class StartupTask : IBackgroundTask
{
private BackgroundTaskDeferral Deferral;
public async void Run (IBackgroundTaskInstance taskInstance)
{
Deferral = taskInstance.GetDeferral ();
var myPictures = await Windows.Storage.StorageLibrary.GetLibraryAsync
(Windows.Storage.KnownLibraryId.Pictures);
string path = myPictures.SaveFolder.Path;
Debug.WriteLine ($"'Pictures' Folder: {path}");
string newFilePath = Path.Combine (path, "TestTextFile.txt");
Debug.WriteLine ($"New File Path: {newFilePath}");
try {
using ( var stream = File.OpenRead (newFilePath) ) {
using ( var reader = new StreamReader (stream) ) {
string fileContents = reader.ReadLine ();
Debug.WriteLine ($"First line of file: '{fileContents}'");
}
}
Debug.WriteLine ($"File read OK");
}
catch ( Exception ex ) { Debug.WriteLine ($"Exception: {ex.Message}"); }
}
}
}
Produced:
'Pictures' Folder: C:\Data\Users\DefaultAccount\Pictures
New File Path: C:\Data\Users\DefaultAccount\Pictures\TestTextFile.txt
First line of file: 'This is some test text.'
File read OK
However, SQLite will not create a database in the folder or open an
existing database that I copy to the folder.
SQLite.Net.SQLiteConnection returns an SQLite exception: "Could not
open database file: C:\Data\Users\DefaultAccount\Pictures\MyDb.db
(CannotOpen)" - no further clues.
Yes, I reproduced this issue. It seems this folder does not work with SQLite file operations but I don't know where the problem is.
As a workaround, you can use PublisherCacheFolder. I create the .db file and write data in one background app. And read the data from another background app. It works.
Contact class:
public sealed class Contact
{
public int Id { get; set; }
public string Name { get; set; }
}
Create and write file:
StorageFolder sharedFonts = Windows.Storage.ApplicationData.Current.GetPublisherCacheFolder("test");
var sqlpath = System.IO.Path.Combine(sharedFonts.Path, "MyDb.db");
using (SQLite.Net.SQLiteConnection conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), sqlpath))
{
conn.CreateTable<Contact>();
for (var i = 0; i < 100; i++)
{
Contact contact = new Contact()
{
Id = i,
Name = "A"
};
conn.Insert(contact);
}
}
Read file:
StorageFolder sharedFonts = Windows.Storage.ApplicationData.Current.GetPublisherCacheFolder("test");
var sqlpath = System.IO.Path.Combine(sharedFonts.Path, "MyDb.db");
using (SQLite.Net.SQLiteConnection conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), sqlpath))
{
var query = conn.Table<Contact>().Where(v => v.Name.Equals("A"));
foreach (var stock in query)
Debug.WriteLine("contact: " + stock.Id);
}
To use this publisher folder you need add the following lines in Package.appxmanifest:
<Extensions>
<Extension Category="windows.publisherCacheFolders">
<PublisherCacheFolders>
<Folder Name="test" />
</PublisherCacheFolders>
</Extension>
</Extensions>
Thanks, Rita. Worked very well. For the benefit of anyone reading, I am using the async version of SqlLite and create the connection as follows:
const string FileName = "MyFile.db";
string DbDir;
string DbPath;
Constructor:
DbDir = Windows.Storage.ApplicationData.Current.GetPublisherCacheFolder("test").Path;
DbPath = Path.Combine (DbDir, DbFileName);
public SQLite.Net.Async.SQLiteAsyncConnection GetConnectionAsync ()
{
var connectionFactory = new Func<SQLite.Net.SQLiteConnectionWithLock>(()=>
new SQLite.Net.SQLiteConnectionWithLock(new SQLitePlatformWinRT(),
new SQLite.Net.SQLiteConnectionString(DbPath, storeDateTimeAsTicks: false)));
var asyncConnection = new SQLiteAsyncConnection(connectionFactory);
return asyncConnection;
}
Then, for instance, read a table of type Parms:
public async Task<Parms> ReadParmsAsync ()
{
var db = GetConnectionAsync ();
var query = db.Table<Parms> ().Where (p => p.Id == 1);
return await query.FirstOrDefaultAsync ();
}
My concern about the SQLite async connection is that it is not IDisposable. Therefore, will the 'factory' eventually run out of steam (memory, handles)? But I guess that is a subject for another thread.

Teamcity - writing tests that access a separate JSON file

I have TeamCity running for a C# project. The Unit tests are written using MSTest and they include an external JSON file. They are loaded in because they're large and I don't want to have to escape them in C#.
I import them like this:
[TestInitialize]
public void Setup()
{
using (StreamReader r = new StreamReader(#".\currency2.json"))
{
_json = r.ReadToEnd();
}
...
They run fine locally. I have 'Copy always set' but when the tests are ran using Teamcity I get an error saying that it can't find them in a temp folder. They are copied over to the build server but they're not in this temp folder.
Could not find file 'E:\TeamCity\buildAgent\temp\buildTmp\SYSTEM_SERVER 2016-07-18 15_28_19\Out\currency2.json'
I have **\bin\release\*test*.dll setup as my Test File Names in the test build step.
Any help appreciated.
I had a similar problem.
I changed the properties of the test file to this
Build Action = Content
Copy to Output Directory = Copy always
Teamcity will copy the file to the build folder, but it does not seem to maintain the same structure you'd expect.
So I created a file lookup loop. That will step down the expected folder until it finds the text file in question.
var pathLookups = new string[]
{
"2ndFolder\\3rdFolder\\test.json", // folder that normally workes
"3rdFolder\\test.json",
"test.json"
};
foreach (var pathLookup in pathLookups)
{
try
{
jsonFileCollection = JsonFileLoader<TestJsonType>.LoadJson(pathLooksup);
if (jsonFileCollection!= null)
{
break;
}
}
catch (Exception)
{
Console.WriteLine("Attempted to load test json from path:" + pathLooksup);
}
}
It's not the cleanest solution, but it will get the job done. You could refactor this to look a little nicer.
You might pass the full pass by argument to your program (and value defined in TeamCity).
Something like this (this is a pseudo-code example only) :
string[] programArgs;
static void Main(string[] args)
{
programArgs = args
}
[TestInitialize]
public void Setup()
{
using (StreamReader r = new StreamReader(programArgs[1]))
{
_json = r.ReadToEnd();
}
...
}

Access denied when copying embedded resource

I have a .exe file as an embedded resource named IDMan.exe in my c# project. I want it to be copied in D:\ directory. i have the following code
public static void extractResource(String embeddedFileName, String destinationPath)
{
Assembly currentAssembly = Assembly.GetExecutingAssembly();
string[] arrResources = currentAssembly.GetManifestResourceNames();
foreach (string resourceName in arrResources)
if (resourceName.ToUpper().EndsWith(embeddedFileName.ToUpper()))
{
Stream resourceToSave = currentAssembly.GetManifestResourceStream(resourceName);
var output = File.OpenWrite(destinationPath);
resourceToSave.CopyTo(output);
resourceToSave.Close();
}
}
But whatever directory I choose it says
Access to path 'D:\' is Denied.

Changing the base path of an assembly from the bin directory to a different directory

I have a Test.cs file in C:\ This test file reads from an input file and writes the same to an output file.
Test.cs
public class Test
{
public static int Main(string[] args)
{
var reader = new StreamReader("in.txt");
string input = reader.ReadLine();
var writer = new StreamWriter("out.txt");
writer.WriteLine(input);
return 0;
}
}
Here it should be noted that the code only uses the filename and not the full file path, which means the file is expected to be in the directory where the program is running. And I have created the in.txt in C:\
Now, there is a c# code called Runner.cs in a solution in C:\Project\Runner.cs, that dynamically compiles the Test.cs code and runs it using reflection. Now, when the Test.cs runs, it expects the in.txt file to be in C:\Project\bin\Debug\in.txt , but it is actually present in C:\in.txt
So, my question is, is there a way to make the code to get the file from C:\in.txt and not from the bin directory without changing the path of the file in the Test.cs code file.
Edit: It is my bad that I forgot to mention why I am in need of this requirement.
The Test.cs file comes from over the wire. And I felt it will not be a good choice to edit this file and set the file path accordingly. I want to compile it and run it as it is.
I hope I am clear. If not, please feel free to ask for more information.
If it is as simple as you show in your code switching the CurrentDirectory works for this example:
var mainMembers = new CSharpCodeProvider()
.CreateCompiler()
.CompileAssemblyFromSource(
new CompilerParameters { GenerateInMemory = true }
, #"
using System;
using System.IO;
public class M {
public static int Main() {
Console.WriteLine(""CurDir = ""+ Environment.CurrentDirectory);
var reader = new StreamReader(""in.txt"");
string input = reader.ReadLine();
var writer = new StreamWriter(""out.txt"");
writer.WriteLine(input);
return 0;
}
}")
.CompiledAssembly
.GetType("M")
.GetMember("Main");
// inspect
Environment.CurrentDirectory.Dump("current");
// keep
var oldcd = Environment.CurrentDirectory;
// switch
Environment.CurrentDirectory = "c:\\temp";
// invoke external code
((MethodInfo) mainMembers[0]).Invoke(null,null);
// restore
Environment.CurrentDirectory = oldcd;
In a multi threaded scenario this becomes unreliable.

nunit test working directory

I have the following code (sample1.evol - file attached to my unit test project):
[Test]
public void LexicalTest1()
{
var codePath = Path.GetFullPath(#"\EvolutionSamples\sample1.evol");
//.....
}
I found that the working directory of test execution is not the assembly directory: (in my case codepath variable assigned to d:\EvolutionSamples\sample1.evol).
So, how can I change the execution working directory (without hardcode)? What will be the best practice to load any files attached to test case?
You can use following to get the directory of assembly running the code something like
var AssemblyDirectory = TestContext.CurrentContext.TestDirectory
I use this for integration tests that need to access data files.
On any machine the test needs to run create a system environment variable named TestDataDirectory that points to the root of where your test data is.
Then have a static method that gets the file path for you..
public static class TestHelper
{
const string EnvironmentVariable = "TestDataDirectory";
static string testDataDir = Environment.GetEnvironmentVariable(EnvironmentVariable);
public static string GetTestFile(string partialPath)
{
return Path.Combine(testDataDir, partialPath);
}
}
...
[Test]
public void LexicalTest1()
{
var codePath = TestHelper.GetTestFile(#"\EvolutionSamples\sample1.evol");
//.....
}
I am using this code:
var str = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase);
if (str.StartsWith(#"file:\")){
str = str.Substring(6);
}
Getting in str variable the assembly directory.
We were having a problem where tests run using ReSharper and NCrunch would work, but the native VS Test Runner would not be able to find the files, when given just a relative file path for the test to use. I solved it by creating a function that you pass the relative test file path into, and it will give you the absolute file path.
private static string _basePath = Path.GetDirectoryName(typeof(NameOfYourTestClassGoesHere).Assembly.Location);
private string GetAbsoluteTestFilePath(string relativePath) => Path.Combine(_basePath, relativePath);
You would then use the function like so:
var input = File.ReadAllLines(GetAbsoluteTestFilePath(#"TestData/YourTestDataFile.txt"));

Categories