Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 103 additions & 16 deletions root/programs/2_RunAllTests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
日時 更新者 内容
---------- ---------------- -------------------------------------------------
2026/08/01 玄人 幸道 新規作成(リリース ワークのエージェント化)
2026/08/17 玄人 幸道 テストごとに Base64 の正規化を選べるようにした(#562)
#>
[CmdletBinding()]
param(
Expand Down Expand Up @@ -166,38 +167,42 @@ function Copy-TestCertificates
# = 期待値でもある(HEAD 版と比較する)
# Bat : ビルドとテスト実行を行うバッチ(root\programs\CS 配下)
# SkipLog4net : log4net の内部トレースを比較対象から外すか
# NormBase64 : Base64 らしき長い値を伏せるか(#562)
# **伏せると、その範囲の変化は差分に出ない。**
# 識別子(IsHankaku/IsZenkaku など)にも当たるため、
# **実行のたびに値が変わるテストだけ $true にする。**
$tests = @(
@{
Name = "TestCode (net48)"; Bat = "y_Build_TestCode_Public.bat"
Result = "TestCode\Result48.txt"; SkipLog4net = $false
Result = "TestCode\Result48.txt"; SkipLog4net = $false; NormBase64 = $false
}
@{
Name = "TestCode (net10.0)"; Bat = "y_Build_TestCode_Public.bat"
Result = "TestCode\ResultCore100.txt"; SkipLog4net = $false
Result = "TestCode\ResultCore100.txt"; SkipLog4net = $false; NormBase64 = $false
}
@{
Name = "TestDataAccess (net48)"; Bat = "y_Build_TestCode_DataAccess.bat"
Result = "TestDataAccess\Result48.txt"; SkipLog4net = $false
Result = "TestDataAccess\Result48.txt"; SkipLog4net = $false; NormBase64 = $false
}
@{
Name = "TestDataAccess (net10.0)"; Bat = "y_Build_TestCode_DataAccess.bat"
Result = "TestDataAccess\ResultCore100.txt"; SkipLog4net = $false
Result = "TestDataAccess\ResultCore100.txt"; SkipLog4net = $false; NormBase64 = $false
}
@{
Name = "SimpleBatch (net48)"; Bat = "y_Build_TestCode_Batch.bat"
Result = "TestBatch\ResultSimpleBatch48.txt"; SkipLog4net = $true
Result = "TestBatch\ResultSimpleBatch48.txt"; SkipLog4net = $true; NormBase64 = $false
}
@{
Name = "SimpleBatch (net10.0)"; Bat = "y_Build_TestCode_Batch.bat"
Result = "TestBatch\ResultSimpleBatchCore100.txt"; SkipLog4net = $true
Result = "TestBatch\ResultSimpleBatchCore100.txt"; SkipLog4net = $true; NormBase64 = $false
}
@{
Name = "EncAndDecUtilCUI (net48)"; Bat = "y_Build_TestCode_SecCUI.bat"
Result = "EncAndDecUtilCUI\Result48.txt"; SkipLog4net = $false
Result = "EncAndDecUtilCUI\Result48.txt"; SkipLog4net = $false; NormBase64 = $true
}
@{
Name = "EncAndDecUtilCUI (net10.0)"; Bat = "y_Build_TestCode_SecCUI.bat"
Result = "EncAndDecUtilCUI\ResultCore100.txt"; SkipLog4net = $false
Result = "EncAndDecUtilCUI\ResultCore100.txt"; SkipLog4net = $false; NormBase64 = $true
}
)

Expand Down Expand Up @@ -241,6 +246,11 @@ Write-Host (" 期待値(HEAD 版)を {0} 件退避しました。" -f $expe
# ------------------------------------------------------------------
# 1 本のバッチが net48 版と .NET (Core) 版の両方をビルド・実行するため、
# 同一バッチは 1 回だけ実行する。
# **ビルドが失敗したバッチ名を覚えておく。**(#564)
# 失敗しても前回の実行ファイルが動くため、
# 結果は期待値と一致し「OK」になってしまう。
$buildFailed = @{}

if (-not $SkipBuild)
{
foreach ($bat in ($tests | ForEach-Object { $_.Bat } | Select-Object -Unique))
Expand All @@ -252,6 +262,7 @@ if (-not $SkipBuild)
if (-not (Test-Path $path))
{
Write-Host " バッチが見つかりません" -ForegroundColor Red
$buildFailed[$bat] = @("バッチが見つかりません : $path")
continue
}

Expand All @@ -264,7 +275,48 @@ if (-not $SkipBuild)
Pop-Location

$sw.Stop()
Write-Host (" 完了 ({0:N1} 秒) ログ : {1}" -f $sw.Elapsed.TotalSeconds, $log)

# ------------------------------------------------------------------
# **ログからビルド エラーを拾う。**(#564)
# ------------------------------------------------------------------
# <終了コードを見ない理由>
# バッチは msbuild を 2 回、テストの実行を 2 回、最後に pause を呼ぶ。
# $LASTEXITCODE は**最後のものしか返らない**ので、
# ビルドの成否を表さない。
#
# <1_BuildAll.ps1 と同じ見方にする>
# コード部分はロケールによらないため、これを拾う。
# "ビルドに失敗しました" 等のサマリ文言は日本語環境でしか出ない。
# コードを伴わない「: error :」形式(NuGet の restore 失敗)もあるため、
# コード部分は省略可能として扱う。
$buildErrors = @(
Get-Content $log -Encoding UTF8 -EA SilentlyContinue |
Where-Object { $_ -match ':\s*error(\s+[A-Za-z]+\d+)?\s*:' -or $_ -match '^\s*\[ERROR\]' } |
ForEach-Object { $_.Trim() } |
Select-Object -Unique)

if ($buildErrors.Count -eq 0)
{
Write-Host (" 完了 ({0:N1} 秒) ログ : {1}" -f $sw.Elapsed.TotalSeconds, $log)
}
else
{
$buildFailed[$bat] = $buildErrors

Write-Host (" **ビルド エラー {0} 件** ({1:N1} 秒) ログ : {2}" -f `
$buildErrors.Count, $sw.Elapsed.TotalSeconds, $log) -ForegroundColor Red

foreach ($e in ($buildErrors | Select-Object -First 5))
{
Write-Host (" " + $e) -ForegroundColor Red
}
if ($buildErrors.Count -gt 5)
{
Write-Host (" ... 他 {0} 件(ログを参照)" -f ($buildErrors.Count - 5)) -ForegroundColor Red
}

Write-Host " **前回の実行ファイルが動くため、比較は当てになりません。**" -ForegroundColor Red
}
}
}

Expand All @@ -281,6 +333,20 @@ foreach ($t in $tests)

$actual = Join-Path $testsRoot $t.Result

# **ビルドが失敗していたら、比較しても意味が無い。**(#564)
# 前回の実行ファイルが動いているため、結果は期待値と一致し「OK」になる。
# 比較を省いて、ビルド失敗として報告する。
if ($buildFailed.ContainsKey($t.Bat))
{
Write-Host " **ビルドに失敗しているため、比較しません。**" -ForegroundColor Red
Write-Host (" ({0} のエラー {1} 件)" -f $t.Bat, $buildFailed[$t.Bat].Count) -ForegroundColor Red

$results += [pscustomobject]@{
テスト = $t.Name; 結果 = "ビルド失敗"; 差分 = "-"
}
continue
}

if (-not $expectedOf.ContainsKey($t.Name))
{
Write-Host " 期待値(HEAD 版)が無いため比較できません" -ForegroundColor Red
Expand All @@ -296,15 +362,20 @@ foreach ($t in $tests)

# CompareResult.ps1 は画面表示に Write-Host を使うため、
# 件数は -PassThru のオブジェクトで受け取る。
if ($t.SkipLog4net)
{
$cmpResult = & $cmp -Expected $expectedOf[$t.Name] -Actual $actual -SkipLog4netTrace -PassThru
}
else
{
$cmpResult = & $cmp -Expected $expectedOf[$t.Name] -Actual $actual -PassThru
#
# **スイッチはスプラッティングで渡す。**(#562)
# if で組み合わせを書き分けると、スイッチが増えるたびに分岐が倍になる。
$cmpArgs = @{
Expected = $expectedOf[$t.Name]
Actual = $actual
PassThru = $true
}

if ($t.SkipLog4net) { $cmpArgs["SkipLog4netTrace"] = $true }
if ($t.NormBase64) { $cmpArgs["NormalizeBase64"] = $true }

$cmpResult = & $cmp @cmpArgs

$results += [pscustomobject]@{
テスト = $t.Name
結果 = $cmpResult.Result
Expand All @@ -323,6 +394,22 @@ Write-Host ""
Write-Host (" 期待値・ログ : {0}" -f $OutputDir)
Write-Host " 実測値 : ワーキング ツリーの Result*.txt(git diff で確認できます)"

# **ビルド失敗は、差分より先に伝える。**(#564)
# 放っておくと前回の実行ファイルの結果を見ることになり、
# 「OK」の意味が変わってしまう。
if ($buildFailed.Count -gt 0)
{
Write-Host ""
Write-Host (" **ビルドに失敗したバッチが {0} 本あります。**" -f $buildFailed.Count) -ForegroundColor Red

foreach ($bat in ($buildFailed.Keys | Sort-Object))
{
Write-Host (" {0} : エラー {1} 件" -f $bat, $buildFailed[$bat].Count) -ForegroundColor Red
}

Write-Host " **直さない限り、テストは前回の実行ファイルで動きます。**" -ForegroundColor Red
}

$ng = @($results | Where-Object { $_.結果 -ne "OK" })
if ($ng.Count -eq 0)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@
//* ・Concurrent Collectionでプールを作成する。
//* 2026/08/13 玄人 幸道 .NET Core版で未対応のprotocolを、nullではなく
//* FrameworkExceptionで返すようにした(#543)。
//* 2021/08/14 西野 大介 デッドコードの整理、メソッド切り出しなど(#546)
//* 2026/08/17 玄人 幸道 WCF_TCPIPの呼び出しを戻した(#561)。#546で実装を
//* メソッドに切り出した際、呼び出しが欠落していた。
//**********************************************************************************

using System;
Expand Down Expand Up @@ -395,7 +398,10 @@ public object Invoke(string serviceName, object parameterValue)
if (protocol == ((int)FxEnum.TmProtocol.WCF_TCPIP).ToString())
{
#region WCF : netTCPBinding


// WCF TCP/IP (netTcpBinding)
ret = this.WCF_TCPIP(serviceName, url, timeout, props,
contextObject, parameterValueObject, out returnValueObject);

#endregion
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
//* 2013/08/30 西野 大介 IsInCodePageメソッドを追加
//* 2018/03/28 西野 大介 .NET Standard対応で、Microsoft.VisualBasicのサポート無し。
//* 2019/10/28 西野 大介 VisualBasic → Zipanguで、IsNumericを復帰
//* 2026/08/17 玄人 幸道 IsNumericとIsNumbersで、空文字列の結果が逆になる
//* 理由をコメントに追記(#552)。挙動は変えていない。
//**********************************************************************************

using System.Text;
Expand Down Expand Up @@ -70,6 +72,15 @@ public class StringChecker
/// double.TryParseでの実装。
/// http://support.microsoft.com/kb/329488/ja
/// 全角文字もチェック可能(半角変換後にチェック)。
///
/// 空文字列が指定された場合は、falseが返ります。
/// 「入力が単体の"数値(Number)"として評価・変換できるか」を見るメソッドであり、
/// 空文字列は数値として評価できないためです。
///
/// IsNumbersとは、空文字列に対する結果が逆になります(あちらはtrue)。
/// あちらは「すべての文字が"数字(Digits)"か」を見るので、
/// 文字が1つも無ければ条件に反する文字も無く、trueになります。
/// 名前が似ていますが問いが違うので、用途に合う方を選んでください。
/// </remarks>
public static bool IsNumeric(string input)
{
Expand All @@ -94,7 +105,15 @@ public static bool IsNumeric(string input)
/// <remarks>
/// 数値チェックという意味ではParse、TryParse
/// メソッドを使用すべきかどうかも検討下さい。
///
/// 空文字列が指定された場合は、trueが返ります。
/// 「すべての文字が"数字(Digits)"か」を見るメソッドなので、
/// 文字が1つも無ければ条件に反する文字も無く、trueになるためです。
/// (連続一致が0回以上(*)なのも、必須入力チェックと被らせないためです)
///
/// IsNumericとは、空文字列に対する結果が逆になります(あちらはfalse)。
/// あちらは「単体の"数値(Number)"として評価・変換できるか」を見ます。
/// 名前が似ていますが問いが違うので、用途に合う方を選んでください。
/// </remarks>
public static bool IsNumbers(string input)
{
Expand Down
73 changes: 59 additions & 14 deletions root/programs/CS/Frameworks/Infrastructure/Public/Xml/XmlLib.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
//* 日時 更新者 内容
//* ---------- ---------------- -------------------------------------------------
//* 2019/05/29 西野 大介 新規作成(分割
//* 2026/08/18 玄人 幸道 index引数が使われていなかったので実装した(#563)。
//* GetAttributeFromXmlNodeのindexは、属性名が一意で
//* 意味を持たないため、引数なしのオーバーロードを
//* 追加し、引数ありをObsoleteとした。
//**********************************************************************************

using System;
Expand All @@ -53,35 +57,52 @@ public static class XmlLib
/// <param name="xPath">string</param>
/// <param name="attrName">string</param>
/// <param name="xmlnsManager">XmlNamespaceManager</param>
/// <param name="index">string</param>
/// <param name="index">
/// XPath に一致するノードのうち、何番目を見るか(0 始まり、既定は 0)
/// </param>
/// <returns>attr string</returns>
/// <remarks>
/// 見つからない場合は空文字列を返します(例外にはなりません)。
/// index が一致件数の範囲外の場合も同様です。
///
/// index を効かせるため SelectNodes を使っていますが、
/// index が 0(既定)のときの結果は SelectSingleNode と同じです。
/// </remarks>
public static string GetAttributeByXPath(
XmlDocument xmlDoc, string xPath, string attrName,
XmlNamespaceManager xmlnsManager = null, int index = 0)
{
return XmlLib.GetAttributeFromXmlNode(
xmlDoc.SelectSingleNode(xPath, xmlnsManager), attrName, index);
XmlNodeList xmlNodeList = xmlDoc.SelectNodes(xPath, xmlnsManager);

// 範囲外は「見つからない」として扱う(例外にしない)。
if (xmlNodeList != null && 0 <= index && index < xmlNodeList.Count)
{
return XmlLib.GetAttributeFromXmlNode(xmlNodeList[index], attrName);
}

return "";
}

/// <summary>GetAttributeByTagName</summary>
/// <param name="xmlDoc">XmlDocument</param>
/// <param name="tagName">string</param>
/// <param name="attrName">string</param>
/// <param name="index">string</param>
/// <param name="index">
/// タグ名が一致する要素のうち、何番目を見るか(0 始まり、既定は 0)
/// </param>
/// <returns>attr string</returns>
/// <remarks>
/// 見つからない場合は空文字列を返します(例外にはなりません)。
/// index が要素数の範囲外の場合も同様です。
/// </remarks>
public static string GetAttributeByTagName(XmlDocument xmlDoc, string tagName, string attrName, int index = 0)
{
XmlNodeList xmlNodeList = xmlDoc.GetElementsByTagName(tagName);

if (xmlNodeList.Count != 0)
// 範囲外は「見つからない」として扱う(例外にしない)。
if (0 <= index && index < xmlNodeList.Count)
{
if (xmlNodeList[0].Attributes != null)
{
if (xmlNodeList[0].Attributes[attrName] != null)
{
return xmlNodeList[0].Attributes[attrName].Value;
}
}
return XmlLib.GetAttributeFromXmlNode(xmlNodeList[index], attrName);
}

return "";
Expand Down Expand Up @@ -127,10 +148,34 @@ public static XmlNode GetXmlNodeById(XmlDocument xmlDoc, string referenceId)
/// <summary>GetAttributeFromXmlNode</summary>
/// <param name="xmlNode">XmlNode</param>
/// <param name="attrName">string</param>
/// <param name="index">int</param>
/// <param name="index">使用しません。</param>
/// <returns>attrValue</returns>
/// <remarks>
/// <index を使わない理由>
/// 1つの XmlNode の中で属性名は一意なので、
/// 「何番目の属性か」という指定が成り立ちません。
/// 「何番目のノードか」を指定したい場合は、
/// GetAttributeByTagName / GetAttributeByXPath の index を使ってください。
///
/// 長らく未使用のまま公開されていたため、
/// 引数の無いオーバーロードへ移行してください(#563)。
/// </remarks>
[Obsolete("This method is deprecated, please use another overload instead.")]
public static string GetAttributeFromXmlNode(
XmlNode xmlNode, string attrName, int index)
{
return XmlLib.GetAttributeFromXmlNode(xmlNode, attrName);
}

/// <summary>GetAttributeFromXmlNode</summary>
/// <param name="xmlNode">XmlNode</param>
/// <param name="attrName">string</param>
/// <returns>attrValue</returns>
/// <remarks>
/// 見つからない場合は空文字列を返します(xmlNode が null でも例外になりません)。
/// </remarks>
public static string GetAttributeFromXmlNode(
XmlNode xmlNode, string attrName, int index = 0)
XmlNode xmlNode, string attrName)
{
if (xmlNode != null)
{
Expand Down
Loading
Loading