blob: a3285e5f8fac2bab0293ae9291f47d9e8b9e995d [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
using System;
using System.Collections.Generic;
using Org.Apache.REEF.Tang.Annotations;
using Org.Apache.REEF.Tang.Exceptions;
using Org.Apache.REEF.Tang.Formats;
using Org.Apache.REEF.Tang.Implementations.Tang;
using Org.Apache.REEF.Tang.Interface;
using Org.Apache.REEF.Tang.Util;
using Xunit;
namespace Org.Apache.REEF.Tang.Tests.Format
{
public interface IFoo
{
int getFooness();
}
interface ISuper
{
}
public class TestConfigurationModule
{
[Fact]
public void SmokeTest()
{
// Here we set some configuration values. In true tang style,
// you won't be able to set them more than once ConfigurationModule's
// implementation is complete.
Type fooType = typeof(Org.Apache.REEF.Tang.Tests.Format.IFoo);
IConfiguration c = MyConfigurationModule.Conf
.Set(MyConfigurationModule.TheFoo, GenericType<FooImpl>.Class)
.Set(MyConfigurationModule.FooNess, "12")
.Build();
IFoo f = (IFoo)TangFactory.GetTang().NewInjector(c).GetInstance(fooType);
Assert.Equal(f.getFooness(), 12);
}
[Fact]
public void SmokeTestConfig()
{
// Here we set some configuration values. In true tang style,
// you won't be able to set them more than once ConfigurationModule's
// implementation is complete.
Type fooType = typeof(Org.Apache.REEF.Tang.Tests.Format.IFoo);
IConfiguration c = MyConfigurationModule.Conf
.Set(MyConfigurationModule.TheFoo, GenericType<FooImpl>.Class)
.Set(MyConfigurationModule.FooNess, "12")
.Build();
IFoo f = (IFoo)TangFactory.GetTang().NewInjector(c).GetInstance(fooType);
Assert.Equal(f.getFooness(), 12);
AvroConfigurationSerializer serializerCs = new AvroConfigurationSerializer();
serializerCs.ToFileStream(c, "TangTestCs.avroconf");
var c3 = serializerCs.FromFileStream("TangTestCs.avroconf");
IFoo f3 = (IFoo)TangFactory.GetTang().NewInjector(c3).GetInstance(fooType);
Assert.Equal(f3.getFooness(), 12);
serializerCs.ToFile(c, "TangTestCs1.avro");
var c4 = serializerCs.FromFile("TangTestCs1.avro");
IFoo f4 = (IFoo)TangFactory.GetTang().NewInjector(c4).GetInstance(fooType);
Assert.Equal(f4.getFooness(), 12);
IConfigurationSerializer serializerImpl =
(IConfigurationSerializer)
TangFactory.GetTang().NewInjector().GetInstance(typeof(IConfigurationSerializer));
serializerImpl.ToFile(c, "TangTestCs1.avro");
var c5 = serializerImpl.FromFile("TangTestCs1.avro");
IFoo f5 = (IFoo)TangFactory.GetTang().NewInjector(c5).GetInstance(fooType);
Assert.Equal(f5.getFooness(), 12);
}
[Fact]
public void OmitOptionalTest()
{
Type fooType = typeof(Org.Apache.REEF.Tang.Tests.Format.IFoo);
IConfiguration c = MyConfigurationModule.Conf
.Set(MyConfigurationModule.TheFoo, GenericType<FooImpl>.Class)
.Build();
IFoo f = (IFoo)TangFactory.GetTang().NewInjector(c).GetInstance(fooType);
Assert.Equal(f.getFooness(), 42);
}
[Fact]
public void OmitRequiredTest()
{
string msg = null;
try
{
MyConfigurationModule.Conf
.Set(MyConfigurationModule.FooNess, "12")
.Build();
msg = "Attempt to build configuration before setting required option(s): { THE_FOO }";
}
catch (Exception)
{
}
Assert.Null(msg);
}
[Fact]
public void BadConfTest()
{
string msg = null;
try
{
object obj = MyMissingBindConfigurationModule.BadConf;
msg = "Found declared options that were not used in binds: { FOO_NESS }" + obj;
}
catch (Exception)
{
}
Assert.Null(msg);
}
[Fact]
public void NonExistentStringBindOK()
{
new MyBadConfigurationModule().BindImplementation(GenericType<IFoo>.Class, "i.do.not.exist");
}
[Fact]
public void NonExistentStringBindNotOK()
{
string msg = null;
try
{
new MyBadConfigurationModule().BindImplementation(GenericType<IFoo>.Class, "i.do.not.exist").Build();
msg = "ConfigurationModule refers to unknown class: i.do.not.exist";
}
catch (Exception)
{
}
Assert.Null(msg);
}
[Fact]
public void MultiBindTest()
{
// Here we set some configuration values. In true tang style,
// you won't be able to set them more than once ConfigurationModule's
// implementation is complete.
IConfiguration c = MultiBindConfigurationModule.Conf
.Set(MultiBindConfigurationModule.TheFoo, GenericType<FooImpl>.Class)
.Set(MultiBindConfigurationModule.FOONESS, "12")
.Build();
IFoo f = (IFoo)TangFactory.GetTang().NewInjector(c).GetInstance(typeof(IFoo));
IFoo g = (IFoo)TangFactory.GetTang().NewInjector(c).GetInstance(typeof(object));
Assert.Equal(f.getFooness(), 12);
Assert.Equal(g.getFooness(), 12);
Assert.False(f == g);
}
[Fact]
public void ForeignSetTest()
{
string msg = null;
try
{
MultiBindConfigurationModule.Conf.Set(MyConfigurationModule.TheFoo, GenericType<FooImpl>.Class);
msg = "Unknown Impl/Param when setting RequiredImpl. Did you pass in a field from some other module?";
}
catch (Exception)
{
}
Assert.Null(msg);
}
[Fact]
public void ForeignBindTest()
{
string msg = null;
try
{
new MyConfigurationModule().BindImplementation(GenericType<object>.Class, MultiBindConfigurationModule.TheFoo);
msg = "Unknown Impl/Param when binding RequiredImpl. Did you pass in a field from some other module?";
}
catch (Exception)
{
}
Assert.Null(msg);
}
[Fact]
public void SingletonTest()
{
IConfiguration c = new MyConfigurationModule()
.BindImplementation(GenericType<IFoo>.Class, MyConfigurationModule.TheFoo)
.BindNamedParameter(GenericType<Fooness>.Class, MyConfigurationModule.FooNess)
.Build()
.Set(MyConfigurationModule.TheFoo, GenericType<FooImpl>.Class)
.Build();
IInjector i = TangFactory.GetTang().NewInjector(c);
Assert.True(i.GetInstance(typeof(IFoo)) == i.GetInstance(typeof(IFoo)));
}
[Fact]
public void ImmutablilityTest()
{
// builder methods return copies; the original module is immutable
ConfigurationModule builder1 = MyConfigurationModule.Conf
.Set(MyConfigurationModule.TheFoo, GenericType<FooImpl>.Class);
Assert.False(builder1 == MyConfigurationModule.Conf);
IConfiguration config1 = builder1.Build();
// reusable
IConfiguration config2 = MyConfigurationModule.Conf
.Set(MyConfigurationModule.TheFoo, GenericType<FooAltImpl>.Class)
.Build();
// instantiation of each just to be sure everything is fine in this situation
IInjector i1 = TangFactory.GetTang().NewInjector(config1);
IInjector i2 = TangFactory.GetTang().NewInjector(config2);
Assert.Equal(42, ((IFoo)i1.GetInstance(typeof(IFoo))).getFooness());
Assert.Equal(7, ((IFoo)i2.GetInstance(typeof(IFoo))).getFooness());
}
[Fact]
public void SetParamTest()
{
IConfiguration c = SetConfigurationModule.CONF
.Set(SetConfigurationModule.P, "a")
.Set(SetConfigurationModule.P, "b")
.Build();
ISet<string> s = (ISet<string>)TangFactory.GetTang().NewInjector(c).GetNamedInstance(typeof(SetName));
Assert.Equal(s.Count, 2);
Assert.True(s.Contains("a"));
Assert.True(s.Contains("b"));
}
[Fact]
public void SetClassTest()
{
IConfiguration c = SetClassConfigurationModule.CONF
.Set(SetClassConfigurationModule.P, GenericType<SubA>.Class)
.Set(SetClassConfigurationModule.P, GenericType<SubB>.Class)
.Build();
ISet<ISuper> s = (ISet<ISuper>)TangFactory.GetTang().NewInjector(c).GetNamedInstance(typeof(SetClass));
Assert.Equal(2, s.Count);
bool sawA = false, sawB = false;
foreach (ISuper sup in s)
{
if (sup is SubA)
{
sawA = true;
}
else if (sup is SubB)
{
sawB = true;
}
else
{
Assert.True(false);
}
}
Assert.True(sawA && sawB);
}
[Fact]
public void SetClassRoundTripTest()
{
IConfiguration c = SetClassConfigurationModule.CONF
.Set(SetClassConfigurationModule.P, GenericType<SubA>.Class)
.Set(SetClassConfigurationModule.P, GenericType<SubB>.Class)
.Build();
IConfigurationBuilder cb = TangFactory.GetTang().NewConfigurationBuilder(c);
AvroConfigurationSerializer serializer = new AvroConfigurationSerializer();
IConfiguration c2 = serializer.FromString(serializer.ToString(cb.Build()));
// ConfigurationFile.AddConfiguration(cb, ConfigurationFile.ToConfigurationString(c));
ISet<ISuper> s = (ISet<ISuper>)TangFactory.GetTang().NewInjector(c2).GetNamedInstance(typeof(SetClass));
Assert.Equal(2, s.Count);
bool sawA = false, sawB = false;
foreach (ISuper sup in s)
{
if (sup is SubA)
{
sawA = true;
}
else if (sup is SubB)
{
sawB = true;
}
else
{
Assert.True(false);
}
}
Assert.True(sawA && sawB);
}
[Fact]
public void ErrorOnStaticTimeSet()
{
string msg = null;
try
{
StaticTimeSet.CONF.AssertStaticClean();
msg =
" Detected statically set ConfigurationModule Parameter / Implementation. set() should only be used dynamically. Use bind...() instead.";
}
catch (ClassHierarchyException)
{
}
Assert.Null(msg);
}
[Fact]
public void ErrorOnSetMerge()
{
ConfigurationModuleBuilder cb = null;
try
{
ConfigurationModuleBuilder b = new ConfigurationModuleBuilder();
cb = b.Merge(StaticTimeSet.CONF);
}
catch (ClassHierarchyException e)
{
System.Diagnostics.Debug.WriteLine(e);
}
Assert.Null(cb);
}
}
[NamedParameter("Fooness", "Fooness", "42")]
public class Fooness : Name<int>
{
}
public class FooImpl : IFoo
{
private readonly int fooness;
[Inject]
FooImpl([Parameter(typeof(Fooness))] int fooness)
{
this.fooness = fooness;
}
public int getFooness()
{
return this.fooness;
}
}
public class FooAltImpl : IFoo
{
private readonly int fooness;
[Inject]
FooAltImpl([Parameter(Value = typeof(Fooness))] int fooness)
{
this.fooness = fooness;
}
public int getFooness()
{
return 7;
}
}
public sealed class MyConfigurationModule : ConfigurationModuleBuilder
{
// Tell us what implementation you want, or else!!
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Required by Tang")]
public static readonly RequiredImpl<IFoo> TheFoo = new RequiredImpl<IFoo>();
// If you want, you can change the fooness.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Required by Tang")]
public static readonly OptionalParameter<int> FooNess = new OptionalParameter<int>();
// This binds the above to tang configuration stuff. You can use parameters more than
// once, but you'd better use them all at least once, or I'll throw exceptions at you.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Required by Tang")]
public static readonly ConfigurationModule Conf = new MyConfigurationModule()
.BindImplementation(GenericType<IFoo>.Class, MyConfigurationModule.TheFoo)
.BindNamedParameter(GenericType<Fooness>.Class, MyConfigurationModule.FooNess)
.Build();
}
public class MyMissingBindConfigurationModule : ConfigurationModuleBuilder
{
// Tell us what implementation you want, or else!!
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Required by Tang")]
public static readonly RequiredImpl<IFoo> TheFoo = new RequiredImpl<IFoo>();
// If you want, you can change the fooness.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Required by Tang")]
public static readonly OptionalParameter<int> FooNess = new OptionalParameter<int>();
// This conf doesn't use FOO_NESS. Expect trouble below
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Required by Tang")]
public static readonly ConfigurationModule BadConf = new MyMissingBindConfigurationModule()
.BindImplementation(GenericType<IFoo>.Class, MyMissingBindConfigurationModule.TheFoo)
.Build();
}
public class MyBadConfigurationModule : ConfigurationModuleBuilder
{
}
public class MultiBindConfigurationModule : ConfigurationModuleBuilder
{
// Tell us what implementation you want, or else!!
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Required by Tang")]
public static readonly RequiredImpl<IFoo> TheFoo = new RequiredImpl<IFoo>();
// If you want, you can change the fooness.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Required by Tang")]
public static readonly OptionalParameter<int> FOONESS = new OptionalParameter<int>();
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Required by Tang")]
public static readonly ConfigurationModule Conf = new MultiBindConfigurationModule()
.BindImplementation(GenericType<IFoo>.Class, MultiBindConfigurationModule.TheFoo)
.BindImplementation(GenericType<object>.Class, MultiBindConfigurationModule.TheFoo)
.BindNamedParameter(GenericType<Fooness>.Class, MultiBindConfigurationModule.FOONESS)
.Build();
}
[NamedParameter]
class SetName : Name<ISet<string>>
{
}
class SetConfigurationModule : ConfigurationModuleBuilder
{
public static readonly RequiredParameter<string> P = new RequiredParameter<string>();
public static readonly ConfigurationModule CONF = new SetConfigurationModule()
.BindSetEntry(GenericType<SetName>.Class, SetConfigurationModule.P)
.Build();
}
[NamedParameter]
class SetClass : Name<ISet<ISuper>>
{
}
class SetClassConfigurationModule : ConfigurationModuleBuilder
{
public static readonly RequiredParameter<ISuper> P = new RequiredParameter<ISuper>();
public static readonly ConfigurationModule CONF = new SetClassConfigurationModule()
.BindSetEntry(GenericType<SetClass>.Class, SetClassConfigurationModule.P)
.Build();
}
class SubA : ISuper
{
[Inject]
public SubA()
{
}
}
class SubB : ISuper
{
[Inject]
public SubB()
{
}
}
class StaticTimeSet : ConfigurationModuleBuilder
{
public static readonly OptionalImpl<ISuper> X = new OptionalImpl<ISuper>();
public static readonly ConfigurationModule CONF = new StaticTimeSet()
.BindImplementation(GenericType<ISuper>.Class, X)
.Build()
.Set(X, GenericType<SubA>.Class);
}
}