using Microsoft.Research.DryadLinq; using Microsoft.Research.Peloponnese.Storage; using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; namespace DryadLinqTests { public class ApplyAndForkTests { public static void Run(DryadLinqContext context, string matchPattern) { TestLog.Message(" **********************"); TestLog.Message(" ApplyAndForkTests "); TestLog.Message(" **********************"); var tests = new Dictionary() { {"NonHomomorphicUnaryApply", () => NonHomomorphicUnaryApply(context) }, {"HomomorphicUnaryApply", () => HomomorphicUnaryApply(context) }, {"NonHomomorphicBinaryApply", () => NonHomomorphicBinaryApply(context) }, {"LeftHomomorphicBinaryApply", () => LeftHomomorphicBinaryApply(context) }, {"FullHomomorphicBinaryApply_DifferentDataSets", () => FullHomomorphicBinaryApply_DifferentDataSets(context) }, {"FullHomomorphicBinaryApply_IdenticalDataSets", () => FullHomomorphicBinaryApply_IdenticalDataSets(context) }, {"Aggregate_WithCombiner", () => Aggregate_WithCombiner(context) }, }; foreach (var test in tests) { if (Regex.IsMatch(test.Key, matchPattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase)) { test.Value.Invoke(); } } } public static IEnumerable NonHomomorphic_Unary_Func(IEnumerable input) { return input; } // [DistributiveOverConcat] public static IEnumerable Homomorphic_Unary_Func(IEnumerable input) { return input; } public static IEnumerable NonHomomorphic_Binary_Func(IEnumerable left, IEnumerable right) { return left; } // [LeftDistributiveOverConcat] public static IEnumerable LeftHomomorphic_Binary_Func(IEnumerable left, IEnumerable right) { return left; } // Note: an apply function must only consume each enumerable once, and it must produce an enumerable // So for a simple pass-through function that does a little work, we must enumerate only once. // Else we get the error: "An HpcLinq channel can't be read more than once." // [DistributiveOverConcat] public static IEnumerable FullHomomorphic_Binary_Func(IEnumerable left, IEnumerable right) { long cLeft = 0; foreach (int x in left) { cLeft++; yield return x; } long cRight = 0; foreach (int x in right) { cRight++; yield return x; } if (cLeft == 0) throw new Exception("a node received empty left-data"); if (cRight == 0) throw new Exception("a node received empty right-data"); } public static bool NonHomomorphicUnaryApply(DryadLinqContext context) { string testName = "NonHomomorphicUnaryApply"; TestLog.TestStart(testName); bool passed = true; try { IEnumerable[] result = new IEnumerable[2]; // cluster { context.LocalDebug = false; string outFile = "unittest/output/NonHomomorphicUnaryApply"; IQueryable pt1 = DataGenerator.GetSimpleFileSets(context); var q1 = pt1.ApplyPerPartition(x => NonHomomorphic_Unary_Func(x)); var jobInfo = q1.ToStore(AzureUtils.ToAzureUri(Config.accountName, Config.containerName, outFile), true).Submit(); jobInfo.Wait(); passed &= Validate.outFileExists(outFile); result[0] = q1; } // local { context.LocalDebug = true; IQueryable pt1 = DataGenerator.GetSimpleFileSets(context); IQueryable q1 = pt1.ApplyPerPartition(x => NonHomomorphic_Unary_Func(x)); result[1] = q1; } // compare result try { Validate.Check(result); } catch (Exception ex) { TestLog.Message("Error: " + ex.Message); passed &= false; } } catch (Exception Ex) { TestLog.Message("Error: " + Ex.Message); passed &= false; } TestLog.LogResult(new TestResult(testName, context, passed)); return passed; } public static bool HomomorphicUnaryApply(DryadLinqContext context) { string testName = "HomomorphicUnaryApply"; TestLog.TestStart(testName); bool passed = true; try { IEnumerable[] result = new IEnumerable[2]; // cluster { context.LocalDebug = false; string outFile = "unittest/output/HomomorphicUnaryApply"; IQueryable pt1 = DataGenerator.GetSimpleFileSets(context); IQueryable q1 = pt1.ApplyPerPartition(x => Homomorphic_Unary_Func(x)); var jobInfo = q1.ToStore(AzureUtils.ToAzureUri(Config.accountName, Config.containerName, outFile), true).Submit(); jobInfo.Wait(); passed &= Validate.outFileExists(outFile); result[0] = q1; } // local { context.LocalDebug = true; IQueryable pt1 = DataGenerator.GetSimpleFileSets(context); IQueryable q1 = pt1.ApplyPerPartition(x => Homomorphic_Unary_Func(x)); result[1] = q1; } // compare result try { Validate.Check(result); } catch (Exception ex) { TestLog.Message("Error: " + ex.Message); passed &= false; } } catch (Exception Ex) { TestLog.Message("Error: " + Ex.Message); passed &= false; } TestLog.LogResult(new TestResult(testName, context, passed)); return passed; } public static bool NonHomomorphicBinaryApply(DryadLinqContext context) { string testName = "NonHomomorphicBinaryApply"; TestLog.TestStart(testName); bool passed = true; try { IEnumerable[] result = new IEnumerable[2]; // cluster { context.LocalDebug = false; string outFile = "unittest/output/NonHomomorphicBinaryApply"; IQueryable pt1 = DataGenerator.GetSimpleFileSets(context); IQueryable q1 = pt1.Apply(pt1, (x, y) => NonHomomorphic_Binary_Func(x, y)); var jobInfo = q1.ToStore(AzureUtils.ToAzureUri(Config.accountName, Config.containerName, outFile), true).Submit(); jobInfo.Wait(); passed &= Validate.outFileExists(outFile); result[0] = q1; } // local { context.LocalDebug = true; IQueryable pt1 = DataGenerator.GetSimpleFileSets(context); IQueryable q1 = pt1.Apply(pt1, (x, y) => NonHomomorphic_Binary_Func(x, y)); result[1] = q1; } // compare result try { Validate.Check(result); } catch (Exception ex) { TestLog.Message("Error: " + ex.Message); passed &= false; } } catch (Exception Ex) { TestLog.Message("Error: " + Ex.Message); passed &= false; } TestLog.LogResult(new TestResult(testName, context, passed)); return passed; } public static bool LeftHomomorphicBinaryApply(DryadLinqContext context) { string testName = "LeftHomomorphicBinaryApply"; TestLog.TestStart(testName); bool passed = true; try { IEnumerable[] result = new IEnumerable[2]; // cluster { context.LocalDebug = false; string outFile = "unittest/output/LeftHomomorphicBinaryApply"; IQueryable pt1 = DataGenerator.GetSimpleFileSets(context); IQueryable q1 = pt1.ApplyPerPartition(pt1, (x, y) => LeftHomomorphic_Binary_Func(x, y), true); var jobInfo = q1.ToStore(AzureUtils.ToAzureUri(Config.accountName, Config.containerName, outFile), true).Submit(); jobInfo.Wait(); passed &= Validate.outFileExists(outFile); result[0] = q1; } // local { context.LocalDebug = true; IQueryable pt1 = DataGenerator.GetSimpleFileSets(context); IQueryable q1 = pt1.ApplyPerPartition(pt1, (x, y) => LeftHomomorphic_Binary_Func(x, y), true); result[1] = q1; } // compare result try { Validate.Check(result); } catch (Exception ex) { TestLog.Message("Error: " + ex.Message); passed &= false; } } catch (Exception Ex) { TestLog.Message("Error: " + Ex.Message); passed &= false; } TestLog.LogResult(new TestResult(testName, context, passed)); return passed; } public static bool FullHomomorphicBinaryApply_DifferentDataSets(DryadLinqContext context) { string testName = "FullHomomorphicBinaryApply_DifferentDataSets"; TestLog.TestStart(testName); bool passed = true; try { IEnumerable[] result = new IEnumerable[2]; // cluster { context.LocalDebug = false; string outFile = "unittest/output/FullHomomorphicBinaryApply_DifferentDataSets"; IQueryable pt1 = DataGenerator.GetSimpleFileSets(context); IQueryable pt2 = DataGenerator.GetSimpleFileSets(context); IQueryable q1 = pt1.ApplyPerPartition(pt2, (x, y) => FullHomomorphic_Binary_Func(x, y), false); var jobInfo = q1.ToStore(AzureUtils.ToAzureUri(Config.accountName, Config.containerName, outFile), true).Submit(); jobInfo.Wait(); passed &= Validate.outFileExists(outFile); result[0] = q1; } // local { context.LocalDebug = true; IQueryable pt1 = DataGenerator.GetSimpleFileSets(context); IQueryable pt2 = DataGenerator.GetSimpleFileSets(context); IQueryable q1 = pt1.ApplyPerPartition(pt2, (x, y) => FullHomomorphic_Binary_Func(x, y), false); result[1] = q1; } // compare result try { Validate.Check(result); } catch (Exception ex) { TestLog.Message("Error: " + ex.Message); passed &= false; } } catch (Exception Ex) { TestLog.Message("Error: " + Ex.Message); passed &= false; } TestLog.LogResult(new TestResult(testName, context, passed)); return passed; } public static bool FullHomomorphicBinaryApply_IdenticalDataSets(DryadLinqContext context) { string testName = "FullHomomorphicBinaryApply_IdenticalDataSets"; TestLog.TestStart(testName); bool passed = true; try { IEnumerable[] result = new IEnumerable[2]; // cluster { context.LocalDebug = false; string outFile = "unittest/output/FullHomomorphicBinaryApply_2"; IQueryable pt1 = DataGenerator.GetSimpleFileSets(context); IQueryable q1 = pt1.ApplyPerPartition(pt1, (x, y) => FullHomomorphic_Binary_Func(x, y), false); var jobInfo = q1.ToStore(AzureUtils.ToAzureUri(Config.accountName, Config.containerName, outFile), true).Submit(); jobInfo.Wait(); passed &= Validate.outFileExists(outFile); result[0] = q1; } // local { context.LocalDebug = true; IQueryable pt1 = DataGenerator.GetSimpleFileSets(context); IQueryable q1 = pt1.ApplyPerPartition(pt1, (x, y) => FullHomomorphic_Binary_Func(x, y), false); result[1] = q1; } // compare result try { Validate.Check(result); } catch (Exception ex) { TestLog.Message("Error: " + ex.Message); passed &= false; } } catch (Exception Ex) { TestLog.Message("Error: " + Ex.Message); passed &= false; } TestLog.LogResult(new TestResult(testName, context, passed)); return passed; } [Associative(typeof(AssociativeRecursive1))] public static string IntToStringCSVAggregator(string agg, int next) { return agg + "," + next.ToString(); } public class AssociativeRecursive1 : IAssociative { public string Seed() { return ""; } public string RecursiveAccumulate(string first, string second) { return first + second; } } public static bool Aggregate_WithCombiner(DryadLinqContext context) { string testName = "Aggregate_WithCombiner"; TestLog.TestStart(testName); bool passed = true; try { // cluster { context.LocalDebug = false; IQueryable pt1 = DataGenerator.GetSimpleFileSets(context); string q1 = pt1.Aggregate("", (str, x) => IntToStringCSVAggregator(str, x)); passed &= (q1.Length == 27); // string should have numbers 1..12 separated by commas } } catch (Exception Ex) { TestLog.Message("Error: " + Ex.Message); passed &= false; } TestLog.LogResult(new TestResult(testName, context, passed)); return passed; } } }