Newer
Older
TIASShot / TIASshot.Tests / GainCalcCalcGainValueTests.cs
using NUnit.Framework;

namespace TIASshot.Tests {
    /// <summary>
    /// GainCalc.CalcGainValue のテスト.
    /// カメラのゲインプロパティ(VCDRangeProperty)は範囲外の値を代入すると
    /// 例外を投げるため,設定値は必ず [rangeMin, rangeMax] に収まる必要がある.
    /// </summary>
    [TestFixture]
    public class GainCalcCalcGainValueTests {

        // ---------------------------------------------------------------
        // 正常ケース(特性化: 従来の四捨五入挙動を保つこと)
        // ---------------------------------------------------------------

        /// <summary>
        /// CalcGainValue_比率が範囲内_従来どおり四捨五入した値を返す:
        /// 100 * 1.5 = 150.0 → (int)(0.5 + 150.0) = 150
        /// </summary>
        [Test]
        public void CalcGainValue_比率が範囲内_従来どおり四捨五入した値を返す() {
            int result = GainCalc.CalcGainValue(100, 1.5f, 0, 255);
            Assert.That(result, Is.EqualTo(150));
        }

        /// <summary>
        /// CalcGainValue_小数部が切り上がる場合_四捨五入した値を返す:
        /// 100 * 1.006 = 100.6 → (int)(0.5 + 100.6) = 101
        /// </summary>
        [Test]
        public void CalcGainValue_小数部が切り上がる場合_四捨五入した値を返す() {
            int result = GainCalc.CalcGainValue(100, 1.006f, 0, 255);
            Assert.That(result, Is.EqualTo(101));
        }

        /// <summary>
        /// CalcGainValue_比率が1_現在値をそのまま返す:
        /// 更新が不要なとき値が変化しないこと
        /// </summary>
        [Test]
        public void CalcGainValue_比率が1_現在値をそのまま返す() {
            int result = GainCalc.CalcGainValue(133, 1.0f, 0, 255);
            Assert.That(result, Is.EqualTo(133));
        }

        // ---------------------------------------------------------------
        // 範囲クランプ(再現テスト)
        // ---------------------------------------------------------------

        /// <summary>
        /// CalcGainValue_結果がrangeMaxを超える_rangeMaxを返す:
        /// 暗いフレームで比率が大きくなると 133 * 2.008 = 267 となり
        /// 設定可能な最大値 255 を超える.範囲上限に飽和させること
        /// </summary>
        [Test]
        public void CalcGainValue_結果がrangeMaxを超える_rangeMaxを返す() {
            int result = GainCalc.CalcGainValue(133, 2.008f, 0, 255);
            Assert.That(result, Is.EqualTo(255));
        }

        /// <summary>
        /// CalcGainValue_結果がrangeMin未満_rangeMinを返す:
        /// 比率が極端に小さいとき範囲下限に飽和させること
        /// </summary>
        [Test]
        public void CalcGainValue_結果がrangeMin未満_rangeMinを返す() {
            int result = GainCalc.CalcGainValue(10, 0.01f, 8, 255);
            Assert.That(result, Is.EqualTo(8));
        }

        /// <summary>
        /// CalcGainValue_比率が負_rangeMinを返す:
        /// 負の比率が渡っても負値を設定しないこと
        /// </summary>
        [Test]
        public void CalcGainValue_比率が負_rangeMinを返す() {
            int result = GainCalc.CalcGainValue(100, -3.0f, 0, 255);
            Assert.That(result, Is.EqualTo(0));
        }

        // ---------------------------------------------------------------
        // 非有限値(ゼロ除算由来)の再現テスト
        // ---------------------------------------------------------------

        /// <summary>
        /// CalcGainValue_比率がInfinity_rangeMaxを返す:
        /// 計測値 0(照明 OFF 等)では CalcRatio が Infinity を返す
        /// (GainCalcTests.CalcRatio_value0_戻り値はInfinityまたはNaN_例外は出ない).
        /// このとき float→int キャストは未定義値(int.MinValue)になるため,
        /// 範囲上限に飽和させること
        /// </summary>
        [Test]
        public void CalcGainValue_比率がInfinity_rangeMaxを返す() {
            int result = GainCalc.CalcGainValue(133, float.PositiveInfinity, 0, 255);
            Assert.That(result, Is.EqualTo(255));
        }

        /// <summary>
        /// CalcGainValue_比率が負のInfinity_rangeMinを返す
        /// </summary>
        [Test]
        public void CalcGainValue_比率が負のInfinity_rangeMinを返す() {
            int result = GainCalc.CalcGainValue(133, float.NegativeInfinity, 0, 255);
            Assert.That(result, Is.EqualTo(0));
        }

        /// <summary>
        /// CalcGainValue_比率がNaN_現在値を維持する:
        /// 計測値 0・目標値 0 では比率が NaN になり更新量を決められないため,
        /// 現在値を維持する(未定義値を設定しない)
        /// </summary>
        [Test]
        public void CalcGainValue_比率がNaN_現在値を維持する() {
            int result = GainCalc.CalcGainValue(133, float.NaN, 0, 255);
            Assert.That(result, Is.EqualTo(133));
        }

        /// <summary>
        /// CalcGainValue_現在値0で比率がInfinity_範囲内に収まる:
        /// ホワイトバランスが下限 0 に張り付いた状態で白パッチの計測値が 0 になると
        /// 0 * Infinity = NaN となり範囲判定をすり抜ける.未定義値(int.MinValue)を
        /// 設定せず,必ず [rangeMin, rangeMax] に収まること
        /// </summary>
        [Test]
        public void CalcGainValue_現在値0で比率がInfinity_範囲内に収まる() {
            int result = GainCalc.CalcGainValue(0, float.PositiveInfinity, 0, 255);
            Assert.That(result, Is.InRange(0, 255));
        }

        // ---------------------------------------------------------------
        // CalcRatio との結合(実際の校正経路の再現)
        // ---------------------------------------------------------------

        /// <summary>
        /// CalcGainValue_CalcRatioの計測値0の結果を渡す_範囲内に収まる:
        /// 校正フローと同じく CalcRatio の戻り値をそのまま渡しても
        /// 設定値が必ず [rangeMin, rangeMax] に収まること
        /// </summary>
        [Test]
        public void CalcGainValue_CalcRatioの計測値0の結果を渡す_範囲内に収まる() {
            float ratio = GainCalc.CalcRatio(0.0f, 226.0f, 0.8f);
            int result = GainCalc.CalcGainValue(133, ratio, 0, 255);
            Assert.That(result, Is.InRange(0, 255));
        }
    }
}