Skip to content

Instantly share code, notes, and snippets.

@yumura
Last active September 2, 2016 05:58
Show Gist options
  • Save yumura/6fc37462b004df40b6d898d9368ba579 to your computer and use it in GitHub Desktop.
Save yumura/6fc37462b004df40b6d898d9368ba579 to your computer and use it in GitHub Desktop.
Convert-FromPOMP
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Converter.Tests.", ".")
$ConvertFromPomp = "$here\$sut"
Set-StrictMode -Version Latest
Describe "No Conversion" {
It Table {
$inJson = '{"Array":[{}]}'
$inPomp = @"
[[Array]]:
[Array.]
"@
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress
$outPomp | Should Be $outJson
}
It Array {
$inJson = '{"Array":[[]]}'
$inPomp = @"
[[Array]]:
[[Array.]]
"@
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress
$outPomp | Should Be $outJson
}
It KeyValue {
$inJson = '{"key":"value"}'
$inPomp = "key: = value"
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress
$outPomp | Should Be $outJson
}
It Value {
$inJson = '{"Array":["value"]}'
$inPomp = @"
[[Array]]:
value
"@
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress
$outPomp | Should Be $outJson
}
}
Describe Conversion {
It Null {
$inJson = '{"null":null}'
$inPomp = "null : null = null"
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress
$outPomp | Should Be $outJson
}
It Bool {
$inJson = '{"key1":true,"key2":false}'
$inPomp = @"
key1 : bool = true
key2 : bool = false
"@
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress
$outPomp | Should Be $outJson
}
It Nullable {
$inJson = '{"key1":true,"key2":false,"key3":null}'
$inPomp = @"
key1 : bool? = true
key2 : bool? = false
key3 : bool? = null
"@
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress
$outPomp | Should Be $outJson
}
It Default {
$inJson = '{"num":42}'
$inPomp = "num : int = 42"
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress
$outPomp | Should Be $outJson
}
}
Describe ConversionError {
It Table {
$message = "ConvertFrom-Pomp (2行目) : 要素の変換に失敗しました。"
$inPomp = @"
[[Array]]: hashtable # 空文字以外変換器とし受け付けない
[Array.]
"@
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
It Array {
$message = "ConvertFrom-Pomp (2行目) : 要素の変換に失敗しました。"
$inPomp = @"
[[Array]]: array # 空文字以外変換器とし受け付けない
[[Array.]]
"@
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
It Null {
$message = "ConvertFrom-Pomp (1行目) : 要素の変換に失敗しました。"
$inPomp = "key : null = 'null' # クオートのない null 以外受け付けない"
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
It Bool {
$message = "ConvertFrom-Pomp (1行目) : 要素の変換に失敗しました。"
$inPomp = "key : bool = 'true' # クオートのない true, false 以外受け付けない"
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
It Nullable {
$message = "ConvertFrom-Pomp (1行目) : 要素の変換に失敗しました。"
$inPomp = "key : bool? = 'true' # 変換に失敗しても null と評価されることはない"
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
It Default {
$message = "ConvertFrom-Pomp (1行目) : 要素の変換に失敗しました。"
$inPomp = "key : int = 10:00:00"
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
}
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Error.Tests.", ".")
$ConvertFromPomp = "$here\$sut"
Set-StrictMode -Version Latest
Describe UndefinitionParent {
It Table {
$message = "ConvertFrom-Pomp (1行目) : パスに未定義の親要素が指定されています。"
$inPomp = "[Parent.Child]"
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
It Array {
$message = "ConvertFrom-Pomp (1行目) : パスに未定義の親要素が指定されています。"
$inPomp = "[[Parent.Child]]"
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
# It KeyValue {}
# It Value {}
}
Describe RedefinitionParent {
It Table {
$message = "ConvertFrom-Pomp (2行目) : パスに定義済みの親要素が指定されています。"
$inPomp = @"
Parent = Definition
[Parent.Child]
"@
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
It Array {
$message = "ConvertFrom-Pomp (2行目) : パスに定義済みの親要素が指定されています。"
$inPomp = @"
Parent = Definition
[[Parent.Child]]
"@
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
# It KeyValue {}
# It Value {}
}
# Describe ValueIsNotParent {}
Describe RedefinitionPath {
It Table {
$message = "ConvertFrom-Pomp (2行目) : パスに定義済みの要素が指定されています。"
$inPomp = @"
Path = Definition
[Path]
"@
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
It Array {
$message = "ConvertFrom-Pomp (2行目) : パスに定義済みの要素が指定されています。"
$inPomp = @"
Path = Definition
[[Path]]
"@
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
It KeyValue {
$message = "ConvertFrom-Pomp (2行目) : パスに定義済みの要素が指定されています。"
$inPomp = @"
Path = Definition
Path = Definition
"@
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
# It Value {}
}
Describe NamedChild {
It Table {
$message = "ConvertFrom-Pomp (2行目) : 配列の子要素に名前付きのパスが指定されています。"
$inPomp = @"
[[Parent]]
[Parent.Child]
"@
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
It Array {
$message = "ConvertFrom-Pomp (2行目) : 配列の子要素に名前付きのパスが指定されています。"
$inPomp = @"
[[Parent]]
[[Parent.Child]]
"@
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
It KeyValue {
$message = "ConvertFrom-Pomp (2行目) : 配列の子要素に名前付きのパスが指定されています。"
$inPomp = @"
[[Parent]]
Child = Error
"@
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
# It Value {}
}
Describe UnnamedChild {
It Root {
$message = "ConvertFrom-Pomp (2行目) : テーブルの子要素に名無しのパスが指定されています。"
$inPomp = @"
['']
"@
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
It Table {
$message = "ConvertFrom-Pomp (2行目) : テーブルの子要素に名無しのパスが指定されています。"
$inPomp = @"
[Parent]
[Parent.]
"@
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
It Array {
$message = "ConvertFrom-Pomp (2行目) : テーブルの子要素に名無しのパスが指定されています。"
$inPomp = @"
[Parent]
[[Parent.]]
"@
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
It KeyValue {
$message = "ConvertFrom-Pomp (2行目) : テーブルの子要素に名無しのパスが指定されています。"
$inPomp = @"
[Parent]
'' = Error
"@
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
It Value {
$message = "ConvertFrom-Pomp (2行目) : テーブルの子要素に名無しのパスが指定されています。"
$inPomp = @"
[Parent]
Value
"@
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
}
Describe HeteroArray {
It Table {
$message = "ConvertFrom-Pomp (3行目) : 配列に異なるタイプの子要素が格納されています。"
$inPomp = @"
[[Parent]]
Child
[Parent.]
"@
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
It Array {
$message = "ConvertFrom-Pomp (3行目) : 配列に異なるタイプの子要素が格納されています。"
$inPomp = @"
[[Parent]]
Child
[[Parent.]]
"@
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
# It KeyValue {}
# It Value {}
}
Describe Unmatch {
It '[' {
$message = "ConvertFrom-Pomp (1行目) : 解析不能な文です。"
$inPomp = "Broken]"
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
It ']' {
$message = "ConvertFrom-Pomp (1行目) : 解析不能な文です。"
$inPomp = "[Broken"
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
It '[[' {
$message = "ConvertFrom-Pomp (1行目) : 解析不能な文です。"
$inPomp = "Broken]]"
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
It ']]' {
$message = "ConvertFrom-Pomp (1行目) : 解析不能な文です。"
$inPomp = "[[Broken"
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}}
catch {$_ | Should Be $message}
}
}
[CmdletBinding()]
Param ([Parameter(ValueFromPipeline=$true)] [string]$String)
Begin
{
# format
# ======
$Script:MsgFormat = 'ConvertFrom-Pomp ({0}行目) : {1}'
# regex
# =====
# primitive
$comment = '(#.*)'
$s = '([ \t]*)'
$id = '([a-zA-Z0-9?_-]+)'
$noneQ = '(\w([^\s#]*\w)?)'
$singleQ = "('([^']|'')*')"
$doubleQ = '("(\\*[^"\\]|\\(\\\\)*")*")'
# token
$Script:Key = "(|${id}|${singleQ}|${doubleQ})"
$Script:Value = "((?<None>${noneQ})|(?<Single>${singleQ})|(?<Double>${doubleQ}))"
$Script:Path = "(${key}(${s}\.${s}${key})*)"
$Script:Comment = "^${s}{0}${s}${comment}?$"
# helper function
# ===============
filter Get-POMP-LineRegex
{
# functions
filter func ($Name, $Pattern, $ScriptBlock)
{
@{
Name = $Name
Pattern = [regex]($Script:Comment -f $Pattern)
ScriptBlock = $ScriptBlock
Message = "${Name}として解析します。"
}
}
@(
func Skip '' {param($State, $MatchGroups)}
func Table "\[${s}(?<Path>${Script:Path})${s}\]" {
param($MatchGroups)
# Child
$childPath = Convert-POMP-Path $MatchGroups['Path'].Value
$childName = Convert-POMP-Name $childPath
$child = @{
Type = 'Table'
Value = New-Object PSCustomObject
Open = $true
LastName = Get-POMP-LastName $childPath
}
# Pearent
$parentPath = Get-POMP-ParentPath $childPath
$parentName = Convert-POMP-Name $parentPath
if (-not ($Script:State.Name.Contains($parentName))) {Throw-POMP-Error UndefinitionParent}
$parent = $Script:State.Name[$parentName]
if (-not ($parent.Open)) {Throw-POMP-Error RedefinitionParent}
# Pearent Type
switch ($parent.Type)
{
Table {
if ($Script:State.Name.Contains($childName)) {Throw-POMP-Error RedefinitionPath}
if ($child.LastName -eq '') {Throw-POMP-Error UnnamedChild}
$parent.Value | Add-Member $child.LastName $child.Value
}
Array {
if ($child.LastName -ne '') {Throw-POMP-Error NamedChild}
if ($Script:State.Name.Contains($childName))
{
$sibling = $Script:State.Name[$childName]
if (-not $sibling.Open) {Throw-POMP-Error RedefinitionPath}
if ($sibling.Type -ne $child.Type) {Throw-POMP-Error HeteroArray}
}
if ($parent.Converter -ne '') {Throw-POMP-Error ConversionError}
[void]$parent.Value.Add($child.Value)
}
Value {Throw-POMP-Error ValueIsNotParent}
default {throw '未定義型'}
}
Close-POMP-Path $childPath
$Script:State.Name[$childName] = $child
$Script:State.Current = $childPath
}
func Array "\[\[${s}(?<Path>${Script:Path})${s}\]\](${s}:${s}(?<Converter>${Script:Key}))?" {
param($MatchGroups)
# Path
$childPath = Convert-POMP-Path $MatchGroups['Path'].Value
$childName = Convert-POMP-Name $childPath
$child = @{
Type = 'Array'
Value = New-Object 'System.Collections.ArrayList'
Open = $true
LastName = Get-POMP-LastName $childPath
Converter = Convert-POMP-String $MatchGroups['Converter'].Value
}
# Pearent
$parentPath = Get-POMP-ParentPath $childPath
$parentName = Convert-POMP-Name $parentPath
if (-not ($Script:State.Name.Contains($parentName))) {Throw-POMP-Error UndefinitionParent}
$parent = $Script:State.Name[$parentName]
if (-not ($parent.Open)) {Throw-POMP-Error RedefinitionParent}
# Pearent Type
switch ($parent.Type)
{
Table {
if ($Script:State.Name.Contains($childName)) {Throw-POMP-Error RedefinitionPath}
if ($child.LastName -eq '') {Throw-POMP-Error UnnamedChild}
$parent.Value | Add-Member $child.LastName $child.Value
}
Array {
if ($child.LastName -ne '') {Throw-POMP-Error NamedChild}
if ($Script:State.Name.Contains($childName))
{
$sibling = $Script:State.Name[$childName]
if (-not $sibling.Open) {Throw-POMP-Error RedefinitionPath}
if ($sibling.Type -ne $child.Type) {Throw-POMP-Error HeteroArray}
}
if ($parent.Converter -ne '') {Throw-POMP-Error ConversionError}
[void]$parent.Value.Add($child.Value)
}
Value {Throw-POMP-Error ValueIsNotParent}
default {throw '未定義型'}
}
Close-POMP-Path $childPath
$Script:State.Name[$childName] = $child
$Script:State.Current = $childPath
}
func KeyValue "(?<Key>${Script:Key})${s}(:${s}(?<Converter>${Script:Key}))?${s}=${s}(?<Value>${Script:Value})" {
param($MatchGroups)
# Path
$LastName = Convert-POMP-String $MatchGroups['Key'].Value
$childPath = Get-POMP-ChildPath $Script:State.Current $LastName
$childName = Convert-POMP-Name $childPath
$child = @{
Type = 'Value'
Value = Convert-POMP-String $MatchGroups['Value'].Value
Open = $false
LastName = $LastName
Converter = Convert-POMP-String $MatchGroups['Converter'].Value
}
$child.ValueType = 'None', 'Single', 'Double' | ?{$MatchGroups[$_].Success} | Select-Object -First 1
# Pearent
$parentPath = Get-POMP-ParentPath $childPath
$parentName = Convert-POMP-Name $parentPath
if (-not ($Script:State.Name.Contains($parentName))) {Throw-POMP-Error UndefinitionParent}
$parent = $Script:State.Name[$parentName]
if (-not ($parent.Open)) {Throw-POMP-Error RedefinitionParent}
# Pearent Type
switch ($parent.Type)
{
Table {
if ($Script:State.Name.Contains($childName)) {Throw-POMP-Error RedefinitionPath}
if ($child.LastName -eq '') {Throw-POMP-Error UnnamedChild}
$success, $child.Value = Invoke-POMP-Converter $child.Converter $child.Value $child.ValueType
if (-not $success) {Throw-POMP-Error ConversionError}
$parent.Value | Add-Member $child.LastName $child.Value
}
Array {Throw-POMP-Error NamedChild}
Value {Throw-POMP-Error ValueIsNotParent}
default {throw '未定義型'}
}
Close-POMP-Path $childPath
$Script:State.Name[$childName] = $child
}
func Value "(?<Value>${Script:Value})" {
param($MatchGroups)
# Path
$LastName = ''
$childPath = Get-POMP-ChildPath $Script:State.Current $LastName
$childName = Convert-POMP-Name $childPath
$child = @{
Type = 'Value'
Value = Convert-POMP-String $MatchGroups['Value'].Value
Open = $true
LastName = $LastName
}
$child.ValueType = 'None', 'Single', 'Double' | ?{$MatchGroups[$_].Success} | Select-Object -First 1
# Pearent
$parentPath = Get-POMP-ParentPath $childPath
$parentName = Convert-POMP-Name $parentPath
if (-not ($Script:State.Name.Contains($parentName))) {Throw-POMP-Error UndefinitionParent}
$parent = $Script:State.Name[$parentName]
if (-not ($parent.Open)) {Throw-POMP-Error RedefinitionParent}
# Pearent Type
switch ($parent.Type)
{
Table {Throw-POMP-Error UnnamedChild}
Array {
if ($Script:State.Name.Contains($childName))
{
$sibling = $Script:State.Name[$childName]
if (-not $sibling.Open) {Throw-POMP-Error RedefinitionPath}
if ($sibling.Type -ne $child.Type) {Throw-POMP-Error HeteroArray}
}
$success, $child.Value = Invoke-POMP-Converter $parent.Converter $child.Value $child.ValueType
if (-not $success) {Throw-POMP-Error ConversionError}
[void]$parent.Value.Add($child.Value)
}
Value {Throw-POMP-Error ValueIsNotParent}
default {throw '未定義型'}
}
Close-POMP-Path $childPath
$Script:State.Name[$childName] = $child
}
)
}
filter Close-POMP-Path ([System.Collections.Generic.List[string]]$Path)
{
$oldPath = $Script:State.Current
$closePath = Copy-POMP-Path $oldPath
$i = 0
$len = [Math]::Min($oldPath.Count, $Path.Count)
while ($i -lt $len -and $oldPath[$i] -eq $Path[$i]){$i++}
for($j = $oldPath.Count - 1; $j -ge $i; $j--)
{
$close = $Script:State.Name[(Convert-POMP-Name $closePath)]
$close.Open = $false
$closePath.RemoveAt($j)
}
}
filter Convert-POMP-Name
([System.Collections.Generic.List[string]]$Path)
{($Path | %{[regex]::Escape($_)}) -join "`t"}
filter Convert-POMP-Path ([string] $String)
{
$loop = $true
$str = $String
$list = New-Object 'System.Collections.Generic.List[string]'
$list.Add('Root')
while ($loop)
{
switch -regex ($str)
{
# stop
"^${Script:Key}$" {
$list.Add((Convert-POMP-String $str))
$loop = $false
}
# split
"^(?<Head>${Script:key})${s}\.${s}(?<Tail>.*)$" {
$list.Add((Convert-POMP-String $Matches.Head))
$str = $Matches.Tail
}
}
}
,$list
}
filter Convert-POMP-String ([string] $String)
{
switch -regex ($String)
{
'^"(?<In>.*)"$' {[regex]::Unescape($Matches.In)}
"^'(?<In>.*)'$" {$Matches.In -replace "''", "'"}
default {$String}
}
}
filter Copy-POMP-Path ([System.Collections.Generic.List[string]]$Path)
{
$list = New-Object 'System.Collections.Generic.List[string]'
foreach ($str in $Path) {$list.Add($str)}
,$list
}
filter Get-POMP-ChildPath ([System.Collections.Generic.List[string]]$Path, $LastName)
{
$list = New-Object 'System.Collections.Generic.List[string]'
foreach ($str in $Path) {$list.Add($str)}
$list.Add($LastName)
,$list
}
filter Get-POMP-LastName
([System.Collections.Generic.List[string]]$Path)
{$Path[$Path.Count - 1]}
filter Get-POMP-ParentPath ([System.Collections.Generic.List[string]]$Path)
{
$list = New-Object 'System.Collections.Generic.List[string]'
for ($i = 0; $i -lt $Path.Count - 1; $i++) {$list.Add($Path[$i])}
,$list
}
filter Invoke-POMP-Converter ([String]$Converter, [String]$InputObject, [String]$Type)
{
switch ($Converter)
{
'' {return $true, $InputObject}
{$_.EndsWith('?')} {
$success, $value = Invoke-POMP-Converter Null $InputObject $Type
if ($success) {return $true, $value}
return Invoke-POMP-Converter ($_ -replace '\?$', '') $InputObject $Type
}
Null {return ($Type -eq 'None' -and $InputObject -eq 'Null'), $null}
Bool {
if ($Type -eq 'None')
{
switch ($InputObject)
{
true {return $true, $true }
false {return $true, $false}
}
}
}
default {
$return = $InputObject -as $Converter
if ($null -ne $return) {return $true, $return}
}
}
$false, $null
}
filter Throw-POMP-Error([string]$MessageID)
{
$Message = switch ($MessageID)
{
UndefinitionParent {'パスに未定義の親要素が指定されています。'}
RedefinitionParent {'パスに定義済みの親要素が指定されています。'}
RedefinitionPath {'パスに定義済みの要素が指定されています。'}
NamedChild {'配列の子要素に名前付きのパスが指定されています。'}
UnnamedChild {'テーブルの子要素に名無しのパスが指定されています。'}
HeteroArray {'配列に異なるタイプの子要素が格納されています。'}
Unmatch {'解析不能な文です。'}
ConversionError {'要素の変換に失敗しました。'}
default {"'${MessageID}'エラーが発生しました。"}
}
throw ($Script:MsgFormat -f $Script:State.LineNumber, $Message)
}
# Get Line RegEx
# ==============
$lineRegex = Get-POMP-LineRegex
# Get Root
# =============
$dummyPath = Convert-POMP-Path Dummy
$rootPath = Get-POMP-ParentPath $dummyPath
$rootName = Convert-POMP-Name $rootPath
}
Process
{
# Begin
$root = @{
Type = 'Table'
Value = New-Object PSCustomObject
Open = $true
}
$Script:State = @{
LineNumber = 1
Name = @{$rootName = $root}
Current = Copy-POMP-Path $rootPath
}
# Process
foreach ($str in $String -split "`r`n|`r|`n")
{
$success = $false
foreach ($fanc in $lineRegex)
{
$lineMatch = $fanc.Pattern.Match($str)
if (-not $lineMatch.Success) {continue}
Write-Verbose ($Script:MsgFormat -f $Script:State.LineNumber, $fanc.Message)
& $fanc.ScriptBlock $lineMatch.Groups
$State.LineNumber++
$success = $true
break
}
if (-not $success) {Throw-POMP-Error Unmatch}
}
# End
Close-POMP-Path (New-Object 'System.Collections.Generic.List[string]')
,$Script:State.Name[$rootName].Value
}
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Tests.", ".")
$ConvertFromPomp = "$here\$sut"
Set-StrictMode -Version Latest
Describe Skip {
It Skip {
$inJson = '{ }'
$inPomp = @"
# ハッシュ以降は、
# コメントとして扱われ、
# スペース、
`t # タブ、
# 空行は無視される
"@
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress
$outPomp | Should Be $outJson
}
It Table {
$inJson = '{"Table":{}}'
$inPomp = '[Table] # Comment'
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress
$outPomp | Should Be $outJson
}
It Array {
$inJson = '{"Array":[]}'
$inPomp = '[[Array]] # Comment'
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress
$outPomp | Should Be $outJson
}
It KeyValue {
$inJson = '{"Table":{"Key":"Value"}}'
$inPomp = @"
[Table]
Key = Value # Coment
"@
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress
$outPomp | Should Be $outJson
}
It Value {
$inJson = '{"Array":["Value"]}'
$inPomp = @"
[[Array]]
Value # Coment
"@
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress
$outPomp | Should Be $outJson
}
}
Describe Table {
It Table {
$inJson = '{"L":{"L":{},"R":{}},"R":{"L":{},"R":{}}}'
$inPomp = @'
[L]
[L.L]
[L.R]
[R]
[R.L]
[R.R]
'@
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress
$outPomp | Should Be $outJson
}
It Array {
$inJson = '{"Table":{"Array":[{"Array":[]}]}}'
$inPomp = @'
[Table]
[[Table.Array]]
[Table.Array.]
[[Table.Array..Array]]
'@
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress -Depth 10
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress -Depth 10
$outPomp | Should Be $outJson
}
It KeyValue {
$inJson = '{"Table":{"Key1":"Value","Key2":"Value","Key3":"Value"}}'
$inPomp = @'
[Table]
'Key1' = Value
'Key2' = Value
'Key3' = Value
'@
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress -Depth 10
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress -Depth 10
$outPomp | Should Be $outJson
}
# It Value {}
}
Describe Array {
It Table {
$inJson = '{"Array":[{"Array":[{}]}]}'
$inPomp = @'
[[Array]]
[Array.]
[[Array..Array]]
[Array..Array.]
'@
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress -Depth 10
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress -Depth 10
$outPomp | Should Be $outJson
}
It Array {
$inJson = '{"L":[[],[]],"R":[[],[]]}'
$inPomp = @'
[[L]]
[[L.]]
[[L.]]
[[R]]
[[R.]]
[[R.]]
'@
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress
$outPomp | Should Be $outJson
}
# It KeyValue {}
It Value {
$inJson = '{"Array":["Value","Value","Value"]}'
$inPomp = @'
[[Array]]
Value
Value
Value
'@
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress -Depth 10
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress -Depth 10
$outPomp | Should Be $outJson
}
}
Describe DoubleQuarto {
It Empty {
$string = ''
$inPomp = 'String = ""'
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string
}
It EscapeDoubleQuarto {
$string = '"'
$inPomp = 'String = "\""'
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string
}
It Escapes {
$string = " `0 `a `b `f `n `r `t `v `` `\ "
$inPomp = 'String = " \0 \a \b \f \n \r \t \v \` \\ "'
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string
}
It Japanese {
$string = "常用漢字、ひらがな、カタカナ"
$inPomp = 'String = "常用漢字、ひらがな、カタカナ"'
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string
}
}
Describe SingleQuarto {
It Empty {
$string = ""
$inPomp = "String = ''"
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string
}
It EscapeSingleQuarto {
$string = "'"
$inPomp = "String = ''''"
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string
}
It UnEscape {
$string = ' \0 \a \b \f \n \r \t \v \` \\ '
$inPomp = @'
String = ' \0 \a \b \f \n \r \t \v \` \\ '
'@
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string
}
It Japanese {
$string = '常用漢字、ひらがな、カタカナ'
$inPomp = "String = '常用漢字、ひらがな、カタカナ'"
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string
}
}
Describe SingleQuarto {
It Empty {
$string = ""
$inPomp = "String = ''"
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string
}
It EscapeSingleQuarto {
$string = "'"
$inPomp = "String = ''''"
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string
}
It UnEscape {
$string = ' \0 \a \b \f \n \r \t \v \` \\ '
$inPomp = @'
String = ' \0 \a \b \f \n \r \t \v \` \\ '
'@
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string
}
It Japanese {
$string = '常用漢字、ひらがな、カタカナ'
$inPomp = "String = '常用漢字、ひらがな、カタカナ'"
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string
}
}
Describe NoneQuarto {
# It Empty {}
# It EscapeNoneQuarto {}
It UnEscape {
$string = 'Begin:\0,\a,\b,\f,\n,\r,\t,\v,\`,\\:End'
$inPomp = "String = {0}" -f 'Begin:\0,\a,\b,\f,\n,\r,\t,\v,\`,\\:End'
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string
}
It Japanese {
$string = '常用漢字、ひらがな、カタカナ'
$inPomp = "String = 常用漢字、ひらがな、カタカナ"
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string
}
}
Describe Path {
It Space {
$inPomp = @"
[ Space`t]
[ Space`t`t. ' Space\t'`t]
[ Space`t`t. ' Space\t'`t. " Space\t\t"`t]
Path = OK
"@
$outPomp = $inPomp | & $ConvertFromPomp
$outPomp.Space.' Space\t'." Space`t`t".Path | Should Be OK
}
It Dot {
$inPomp = @"
['.']
['.'.".."]
Path = OK
"@
$outPomp = $inPomp | & $ConvertFromPomp
$outPomp.'.'.'..'.Path | Should Be OK
}
It Escape {
$unescape = ' \0 \a \b \f \n \r \t \v \` \\ '
$escape = " `0 `a `b `f `n `r `t `v `` `\ "
$inPomp = @"
['${unescape}'] # unescape
['${unescape}'."${unescape}"] # escape
Path = OK
"@
$outPomp = $inPomp | & $ConvertFromPomp
$outPomp.$unescape.$escape.Path | Should Be OK
}
It Japanese {
$inPomp = @"
['常用漢字']
['常用漢字'."ひらがな_カタカナ"]
Path = OK
"@
$outPomp = $inPomp | & $ConvertFromPomp
$outPomp.常用漢字.ひらがな_カタカナ.Path | Should Be OK
}
}
Describe Key {
It Space {
$inPomp = @"
Space1 `t = OK1
' Space2\t'`t = OK2
" Space3\t"`t = OK3
"@
$outPomp = $inPomp | & $ConvertFromPomp
$outPomp.Space1 | Should Be OK1
$outPomp.' Space2\t' | Should Be OK2
$outPomp." Space3`t" | Should Be OK3
}
It NoneQuarto {
$inPomp = @"
abc-xyz_ABC-XYZ_01-89? = OK
"@
$outPomp = $inPomp | & $ConvertFromPomp
$outPomp.'abc-xyz_ABC-XYZ_01-89?' | Should Be OK
}
It Escape {
$unescape = ' \0 \a \b \f \n \r \t \v \` \\ '
$escape = " `0 `a `b `f `n `r `t `v `` `\ "
$inPomp = @"
'${unescape}' = unescape
"${unescape}" = escape
"@
$outPomp = $inPomp | & $ConvertFromPomp
$outPomp.$unescape | Should Be unescape
$outPomp.$escape | Should Be escape
}
It Japanese {
$inPomp = @"
'常用漢字' = OK1
"ひらがな" = OK2
"カタカナ" = OK3
"@
$outPomp = $inPomp | & $ConvertFromPomp
$outPomp.常用漢字 | Should Be OK1
$outPomp.ひらがな | Should Be OK2
$outPomp.カタカナ | Should Be OK3
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment