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

Build directory; download files (in progress) #7

Merged
merged 10 commits into from
Nov 13, 2023
30 changes: 30 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: tests

on:
push:
branches: [ "master" ]
pull_request:
branches: [ "*" ]

jobs:
build:

runs-on: ${{ matrix.os }}-latest
strategy:
matrix:
os:
- ubuntu
- windows

steps:
- uses: actions/checkout@v4
- name: Setup dotnet
uses: actions/setup-dotnet@v3
with:
dotnet-version: '7.0.x'
- name: Install dependencies
run: dotnet restore
- name: Build
run: dotnet build
- name: Test with the dotnet CLI
run: dotnet test
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ Mock/obj/
/Golem/obj/
/Golem.Tests/bin/
/Golem.Tests/obj/
/Golem.Tests/tests/
/MockGUI/bin/
/MockGUI/obj/
1 change: 1 addition & 0 deletions Golem.Tests/Golem.IntegrationTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.1" />
<PackageReference Include="SharpZipLib" Version="1.4.2" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
27 changes: 20 additions & 7 deletions Golem.Tests/GolemTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@

namespace Golem.Tests
{
[Collection("Sequential")]
public class GolemTests
{
string golemPath = "c:\\git\\yagna\\target\\debug";

[Fact]
public async Task StartStop_VerifyStatusAsync()
{
string golemPath = await PackageBuilder.BuildTestDirectory("StartStop_VerifyStatusAsync");
Console.WriteLine("Path: " + golemPath);

var golem = new Golem(golemPath, null);
var golem = new Golem(PackageBuilder.BinariesDir(golemPath), PackageBuilder.DataDir(golemPath));
GolemStatus status = GolemStatus.Off;

Action<GolemStatus> updateStatus = (v) => {
Action<GolemStatus> updateStatus = (v) =>
{
status = v;
};

Expand All @@ -26,21 +27,33 @@ public async Task StartStop_VerifyStatusAsync()
await golem.Start();

Assert.Equal(GolemStatus.Ready, status);

await golem.Stop();

Assert.Equal(GolemStatus.Off, status);
}

[Fact]
public async Task TestDownloadArtifacts()
{
var dir = await PackageBuilder.BuildTestDirectory("TestDownloadArtifacts");

Assert.True(Directory.EnumerateFiles(dir, "modules/golem/yagna*").Any());
Assert.True(Directory.EnumerateFiles(dir, "modules/golem/ya-provider*").Any());
Assert.True(Directory.EnumerateFiles(dir, "modules/plugins/ya-runtime-ai*").Any());
Assert.True(Directory.EnumerateFiles(dir, "modules/plugins/dummy*").Any());
}

[Fact]
public async Task Start_ChangeWallet_VerifyStatusAsync()
{
string golemPath = await PackageBuilder.BuildTestDirectory("Start_ChangeWallet_VerifyStatusAsync");
Console.WriteLine("Path: " + golemPath);

var golem = new Golem(golemPath, null);
var golem = new Golem(PackageBuilder.BinariesDir(golemPath), PackageBuilder.DataDir(golemPath));
GolemStatus status = GolemStatus.Off;

Action<GolemStatus> updateStatus = (v) => {
Action<GolemStatus> updateStatus = (v) =>
{
status = v;
};

Expand Down
231 changes: 231 additions & 0 deletions Golem.Tests/Tools/GolemPackageBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Runtime.InteropServices;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Text;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Tar;

namespace Golem.IntegrationTests.Tools
{
public class PackageBuilder
{
const string GITHUB_RELEASE_URL = "https://github.com/{2}/releases/download/{0}/{3}-{1}-{0}";
const string CURRENT_GOLEM_VERSION = "pre-rel-v0.13.1-rc3";
const string CURRENT_RUNTIME_VERSION = "pre-rel-v0.1.0-rc14";

public static string InitTestDirectory(string name)
{
var build_dir = AppDomain.CurrentDomain.SetupInformation.ApplicationBase ?? Path.GetTempPath();
var tests_dir = Path.Combine(build_dir, "../../../tests");
var dir = Path.GetFullPath(Path.Combine(tests_dir, name));

if (Directory.Exists(dir))
{
Directory.Delete(dir, true);
}
Directory.CreateDirectory(BinariesDir(dir));
return dir;
}

public async static Task<string> BuildTestDirectory(string test_name)
{
var dir = InitTestDirectory(test_name);
var system = System();
BuildDirectoryStructure(dir);

await DownloadExtractPackage(BinariesDir(dir), "golem-provider", "golemfactory/yagna", CURRENT_GOLEM_VERSION, system);
await DownloadExtractPackage(ExeUnitsDir(dir), "runtime", "golemfactory/ya-runtime-ai", CURRENT_RUNTIME_VERSION, system);
await DownloadExtractPackage(ExeUnitsDir(dir), "dummy-framework", "golemfactory/ya-runtime-ai", CURRENT_RUNTIME_VERSION, system);

Directory.SetCurrentDirectory(dir);

return dir;
}

static async Task DownloadExtractPackage(string dir, string artifact, string repo, string tag, string system = "windows")
{
var builds = await DownloadArtifact(dir, artifact, tag, repo, system);
var extract_to = Path.GetDirectoryName(builds) ?? "";

Extract(builds, extract_to);

var extract_package_dir = Path.ChangeExtension(builds, null);
if (Path.GetExtension(extract_package_dir) == ".tar")
{
extract_package_dir = Path.ChangeExtension(extract_package_dir, null);
}

SetPermissions(extract_package_dir);

CopyFilesRecursively(extract_package_dir, dir);
Directory.Delete(extract_package_dir, true);

}

public static void BuildDirectoryStructure(string gamerhash_dir)
{
Directory.CreateDirectory(BinariesDir(gamerhash_dir));
Directory.CreateDirectory(ProviderDataDir(gamerhash_dir));
Directory.CreateDirectory(YagnaDataDir(gamerhash_dir));
Directory.CreateDirectory(ExeUnitsDir(gamerhash_dir));
}

// Based on: https://stackoverflow.com/a/3822913
private static void CopyFilesRecursively(string sourcePath, string targetPath)
{
//Now Create all of the directories
foreach (string dirPath in Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories))
{
Directory.CreateDirectory(dirPath.Replace(sourcePath, targetPath));
}

//Copy all the files & Replaces any files with the same name
foreach (string newPath in Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories))
{
File.Copy(newPath, newPath.Replace(sourcePath, targetPath), true);
}
}

public static string System()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return "linux";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return "windows";
}
else
{
throw new Exception("System not supported.");
}
}

public static string BinariesDir(string gamerhash_dir)
{
return Path.Combine(gamerhash_dir, "modules/golem");
}

public static string DataDir(string gamerhash_dir)
{
return Path.Combine(gamerhash_dir, "modules/golem-data");
}

public static string ProviderDataDir(string gamerhash_dir)
{
return Path.Combine(DataDir(gamerhash_dir), "provider");
}

public static string YagnaDataDir(string gamerhash_dir)
{
return Path.Combine(DataDir(gamerhash_dir), "yagna");
}

public static string ExeUnitsDir(string gamerhash_dir)
{
return Path.Combine(gamerhash_dir, "modules/plugins");
}

static async Task<string> Download(string target_dir, string url)
{
var name = Path.GetFileName(url);
var target_file = Path.Combine(target_dir, name);
using (var httpClient = new HttpClient())
{
var response = await httpClient.GetAsync(url);
if (response.IsSuccessStatusCode)
{
using (var fs = new FileStream(target_file, FileMode.CreateNew))
{
await response.Content.CopyToAsync(fs);
}
}
else
{
throw new Exception("Failed to download: " + response.ToString());
}

}
return target_file;
}

static void Extract(string file, string target_dir)
{
var ext = Path.GetExtension(file);
switch (ext)
{
case ".zip":
var extract_dir_name = Path.GetFileNameWithoutExtension(file);
var extract_package_dir = Path.Combine(target_dir, extract_dir_name);
ZipFile.ExtractToDirectory(file, extract_package_dir);
break;
case ".gz":
ExtractTGZ(file, target_dir);
break;
default:
throw new Exception("Uknonwn archive format. File: " + file);
}

File.Delete(file);
}

// Based on: https://stackoverflow.com/a/52200001
static void ExtractTGZ(String gzArchiveName, String destFolder)
{
Stream inStream = File.OpenRead(gzArchiveName);
Stream gzipStream = new GZipInputStream(inStream);

TarArchive tarArchive = TarArchive.CreateInputTarArchive(gzipStream, Encoding.UTF8);
tarArchive.ExtractContents(destFolder);
tarArchive.Close();

gzipStream.Close();
inStream.Close();
}

public static void SetFilePermissions(string fileName)
{
// Get a FileSecurity object that represents the
// current security settings.
var file = new FileInfo(fileName);
if (OperatingSystem.IsWindows())
{
FileSecurity fSecurity = FileSystemAclExtensions.GetAccessControl(file);
fSecurity.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), FileSystemRights.ExecuteFile, AccessControlType.Allow));
FileSystemAclExtensions.SetAccessControl(file, fSecurity);
}
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
{
file.UnixFileMode |= UnixFileMode.UserExecute | UnixFileMode.OtherExecute | UnixFileMode.GroupExecute;
}
}

public static void SetPermissions(string directory)
{
foreach (var file in Directory.EnumerateFiles(directory))
{
SetFilePermissions(file);
}
}


static async Task<string> DownloadArtifact(string target_dir, string artifact, string tag, string repository, string system = "windows")
{
var ext = system is "windows" ? ".zip" : ".tar.gz";
var url = String.Format(GITHUB_RELEASE_URL, tag, system, repository, artifact);
url += ext;

Console.WriteLine(String.Format("Download URL: {0}", url));
return await Download(target_dir, url);
}



}


}
4 changes: 2 additions & 2 deletions Golem.Tests/Tools/PropertyChangedHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ private void HandlerImpl(object? sender, PropertyChangedEventArgs e)

var value = property.GetValue(sender);

if(value is null)
if (value is null)
return;

Handler((T)value);

if (sender is not Golem golem || e.PropertyName != PropertyName)
throw new NotSupportedException($"Type or {e.PropertyName} is not supported in this context");
return;

Console.WriteLine($"Property has changed: {e.PropertyName} to {golem.Status}");
}
Expand Down
Loading
Loading