Trying to compare web service response and expected xml from file - web-services

We're developing in Java for the most, but we want to integration test (using https://github.com/scottmuc/Pester) our web-services with ms as well. To do this I'm writing powershell scripts that connects to a web-service and compares the response to xml that I've loaded from a file.
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
$instance = New-WebServiceProxy -Uri "https://localhost:7002/service?WSDL" -Namespace "myspace"
$instance.Credentials = new-object System.Net.NetworkCredential("user", "pass")
...
$reply = $instance.fetchInformation($inputA, $inputB)
[xml]$expected = Get-Content ("expected.xml")
...
However, now I have a $reply that contains objects from the myspace namespace and an $expected that contains an XMLNode. I see two ways I can do this (there are probably many more):
Get the original XML response and compare that. However, I can't seem to find out how to get that.
Serialise the $expected XML into the myspace namespace objects. Is that possible?

You could serialize the response returned by the web service to XML and compare it with the contents of the expected.xml file as strings.
Here's an example:
$writer = New-Object System.IO.StringWriter
$serializer = New-Object System.Xml.Serialization.XmlSerializer($reply.GetType())
$serializer.Serialize($writer, $reply)
$replyAsXml = $writer.ToString()
$expectedReplyAsXml = Get-Content expected.xml
$replyAsXml -eq $expectedReplyAsXml
Note that in this example you need to make sure that XML contained in the expected.xml file matches the one returned by the XmlSerializer also in regard to spacing and indenting. In order to avoid that, you could strip all extra characters (such as spaces and newlines) from the two strings before comparing them.

I ended up with a completely different approach. The two XML's was quite different from each other so instead I created a custom comparator. This made it possible for me to simply write custom code to ignore uninteresting differences.
This lead to some pile of crude code that does the job:
# Assume two arrays of equal length
Function Zip {
Param($a1, $a2)
$sum = New-Object object[] $a1.Count
For ($i = 0; $i -lt $a1.Count; ++$i) {
$sum[$i] = New-Object object[] 2
$sum[$i][0] = $a1[$i]
$sum[$i][1] = $a2[$i]
}
Return ,$sum
}
Function XmlChildNodes2List{
param($nodes)
$myArray = New-Object object[] 0
For ($i = 0; $i -lt $nodes.Count; ++$i) {
$node = $nodes.Item($i)
If ($node -ne $null) {
$myArray += $node
}
}
Return ,$myArray
}
Function ShowContext{
Param($ctx)
" at " + $ctx
}
Function CompareNode{
Param($o1, $o2, $ctx)
Try {
Switch ($o1.GetType().Name) {
"XmlDocument" {
CompareXml $o1.ChildNodes $o2.ChildNodes
}
"XmlChildNodes" {
$olist1 = XmlChildNodes2List $o1 | Sort
$olist2 = XmlChildNodes2List $o2 | Sort
If ($olist1.Count -ne $olist2.Count) {
$msg = "Unequal child node count " + ($olist1 -join ",") + " and " + ($olist2 -join ",") + (ShowContext $ctx)
throw $msg
} Else {
$list = Zip $olist1 $olist2
$value = $true
foreach ($item in $list) {
if ($value -eq $true) {
$value = CompareXml $item[0] $item[1] $ctx
}
}
$value
}
}
"XmlElement" {
If ($o1.LocalName -eq $o2.LocalName) {
If ($o1.LocalName -eq "uninterestingElement" -or $o1.LocalName -eq "uninterestingElement2") {
$true
} Else {
CompareXML $o1.ChildNodes $o2.ChildNodes ($ctx + "/" + $o1.LocalName)
}
} Else {
throw ("Element " + $o1.LocalName + " != " + $o2.LocalName + (ShowContext $ctx))
}
}
"XmlDeclaration" {
$true
}
"XmlText" {
$result = $o1.InnerText.Replace("`r`n","`n")
$expect = $o2.InnerText.Replace("`r`n","`n")
# TODO: Hack to remove timezone from expected dates in format 2005-09-01+02:00, the webservice side of the
# reply to xml-conversion looses them
If ($expect -match "^(\d{4}-\d\d-\d\d)\+\d\d:\d\d$") {
$expect = $Matches[1]
}
If ($result -eq $expect) {
$true
} Else {
throw ($o1.InnerText + " is not equal to " + $o2.InnerText + (ShowContext $ctx))
}
}
Default {
throw ("What to do with node " + $o1.GetType().Name + (ShowContext $ctx))
}
}
} Catch [Exception] {
throw $_
}
}
Function CompareXML{
Param($o1, $o2, $ctx)
If ($o1 -eq $null -and $o2 -eq $null) {
$true
} ElseIf ($o1 -eq $null -or $o2 -eq $null) {
throw ("Response or expected is null")
} ElseIf ($o1.GetType() -eq $o2.GetType()) {
CompareNode $o1 $o2 $ctx
} Else {
throw ($o1.GetType().Name + " is not " + $o2.GetType().Name + (ShowContext $ctx))
}
}
This can then be run on two XML's like this:
CompareXML $result $expected ""

Related

Why is this switch deleting an extra line (PowerShell)

This code is supposed to find a line with a regular expression and replace the line with "test". It is finding that line and replace it with "test" but also deleting the line under it, no matter what is in the next line down. I feel like I am just missing something about how a switch works in PowerShell.
Note: This is super boiled down code. There is a larger program this is part of.
$reg = '^HI\*BH'
$appendText = ''
$file = Get-ChildItem (join-path $PSScriptRoot "a.txt.BAK")
foreach ($f in $file){
switch -regex -file $f {
$reg
{
$appendText = "test"
}
default {
If ($appendText -eq '') {$appendText = $_}
$appendText
$appendText = ''
}
}
}
a.txt.BAK
HI*BH>00>D8>0*BH>00>D8>0*BH>A1>D8>0*BH>B1>D8>0000000~
HI*BE>02>>>0.00*BE>00>>>0.00~
NM1*71*1*TTT*NAME****XX*0000000~
PRV*AT*PXC*000V00000X~
Output:
test
NM1*71*1*TTT*NAME****XX*0000000~
PRV*AT*PXC*000V00000X~
The switch is not "deleting" anything - but you explicit ask it to overwrite $appendText on match, and you only ever output (and reset the value of) $appendText when it doesn't.
This code is supposed to find a line with a regular expression and replace the line with "test".
In that case I suggest you simplify your switch:
switch -regex -file $f {
$reg {
"test"
}
default {
$_
}
}
That's it - no fiddling around with variables - just output "test" on match, otherwise output the line as-is.
If you insist on using the intermediate variable, you'll need to output + reset the value in both cases:
switch -regex -file $f {
$reg {
$appendText = "test"
$appendText
$appendText = ''
}
default {
$appendText = $_
$appendText
$appendText = ''
}
}

How should C++ execute the PowerShell command?

I want to execute the PowerShell command in C + + programming. I've edited the command statement that needs to be run.PowerShell_CMD、XML_File
My assumption here is that you're trying to add -auto to the arguments. After reviewing the supplied image I would change the PowerShell code as well.
$task = Get-ScheduledTask "Test"
$items = #{}
if ($task.Actions.Execute -ne $null) {$items.Add('Execute', "$($task.Actions.Execute)")}
$items.Add('Argument', "$($task.Actions.Arguments) -auto")
if ($task.Actions.WorkingDirectory -ne $null) {$items.Add('WorkingDirectory',"$($task.Actions.WorkingDirectory)")}
$action = New-ScheduledTaskAction #items
$task.Actions = $action
Set-ScheduledTask -InputObject $task
Far simpler and easier to understand.
To run this in c++ you should dump the code to a temporary file.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ofstream file;
file.open("test.ps1");
string newArg = "-auto";
string powershell;
powershell = "$task = Get-ScheduledTask \"Test\"\n";
powershell += "$items = #{}\n";
powershell += "if ($task.Actions.Execute -ne $null) {$items.Add('Execute', \"$($task.Actions.Execute)\")} \n";
powershell += "$items.Add('Argument', \"$($task.Actions.Arguments) " + newArg + "\") \n"; // 'Argument' not a typo
powershell += "if ($task.Actions.WorkingDirectory -ne $null) {$items.Add('WorkingDirectory',\"$($task.Actions.WorkingDirectory)\")} \n";
powershell += "$action = New-ScheduledTaskAction #items\n";
powershell += "$task.Actions = $action\n";
powershell += "Set-ScheduledTask -InputObject $task\n";
file << powershell << endl;
file.close();
system("powershell -ExecutionPolicy Bypass -F test.ps1");
remove("test.ps1");
}

Vtiger CRM #: How to write PHP code in log4php.properties file

I am new to Vtiger CRM. I want to write php code in log4php.properties file and also it need to be executed.
I can write the code but it is not executing at all. So kindly help me with a way which will allow to execute the file.
Also this need to be executed dynamic with separate domains.
Thanks
Open your index.php file from crm root directory and Add this code
function replace_string_in_a_file($filepath, $search, $replace) {
if (#file_exists($filepath)) {
$file = file($filepath);
foreach ($file as $index => $string) {
if (strpos($string, $search) !== FALSE)
$file[$index] = "$replace\n";
}
$content = implode($file);
return $content;
}else {
return NULL;
}
}
$filepath = $root_directory . 'log4php.properties';
$search = 'log4php.appender.A1.File=';
$replace = 'log4php.appender.A1.File=' . DOMAIN_PATH . '/logs/vtigercrm.log';
$log_properties_content = replace_string_in_a_file($filepath, $search, $replace);
if (!empty($log_properties_content)) {
file_put_contents($filepath, $log_properties_content);
}

powershell script to call a list of variables to input into current script

So below is my script on how to call recursive members in groups across a trusted domain. what i need help with is to convert this from looking up a single group to multiple groups.
At the line $objGrp = [ADSI]"LDAP://CN=Administrators,CN=Builtin,DC=domain,DC=com" i have to manually change it to whatever group i want to search for. i instead want this script to call a text file with a list of groups.
for example, in the text file there would be
CN=Administrators,CN=Builtin,DC=domain,DC=com
CN=domain admins,CN=users,DC=domain,DC=com
CN=enterprise admins,CN=users,DC=domain,DC=com
what do i need to add/change to be able to do this?
# Script begins
#
# Bind to the AD group
$objGrp = [ADSI]"LDAP://CN=Administrators,CN=Builtin,DC=domain,DC=com"
#[ADSI]"LDAP://CN=Administrators,CN=Builtin,DC=domain,DC=com"
#
$Global:GroupMembers = #()
# Function to read the group members - nested members
Function GetGroupMember($objGrp)
{
# Enumerate the group members
foreach($member in $objGrp.member)
{
# Bind to the each user using DN
$strTemp = "LDAP://" + $member
$objTemp = [ADSI]$strTemp
# Check for AD Group object based on objectCategory
$strCat = [System.String]$objTemp.objectCategory
#foreign object
$res = $strCat.StartsWith("CN=Foreign-Security-Principal")
#$strCat
If($res -eq $True)
{
# bind to the foreign object
$strTemp = "LDAP://" + $member
$tempObj = [ADSI]$strTemp
# convert binary SID to bindable string SID
$objBin = $tempObj.objectSID.Item(0)
$objSID = New-Object System.Security.Principal.SecurityIdentifier($objBin,0)
$srchDomain = New-Object System.DirectoryServices.DirectoryEntry("LDAP://dc=domain,dc=com")
$dirSrchObj = New-Object System.DirectoryServices.DirectorySearcher($srchDomain)
#$objSID.Value
[System.Environment]::NewLine
$dirSrchObj.Filter = "((objectSID=" + $objSID.Value + "))"
# Search scope to sub-level
$dirSrchObj.SearchScope = "Subtree"
$dirSrchObj.PageSize = 1
# Array of result collection - users
$srchResArr = $dirSrchObj.FindOne()
"======================================="
If ($srchResArr -ne $NULL)
{
# bind to the object
#$strTem = [System.String]$srchResArr.ToString()
$objEntry = $srchResArr.GetDirectoryEntry()
# read and compare the object category for group object
[System.String]$strTemp1 = $objEntry.objectcategory
$res1 = $strTemp1.StartsWith("CN=Group")
if($res1 -eq $True)
{
#enumerate the group members
Write-Host "The members of foreign group " $objEntry.Name "are: "
Foreach($obj in $objEntry.member)
{
$strTemp2 = "LDAP://" + $obj
$objTemp2 = [ADSI]$strTemp2
[System.String]$strTemp3 = $objTemp2.objectCategory
$res2 = $strTemp3.StartsWith("CN=Group")
if($res2 -eq $True)
{
GetGroupMember($objTemp2)
}
Else
{
$objTemp2.distinguishedName
$Global:GroupMembers += $objTemp2.distinguishedName
}
}
}
Else
{
"Foreign user object: "
$objEntry.distinguishedName
$Global:GroupMembers += $objEntry.distinguishedName
}
}
"======================================="
[System.Environment]::NewLine
}
Else
{
$flag = $strCat.StartsWith("CN=Group")
# If it is a Group object then call this method (recursive)
If($flag -eq $TRUE)
{
Write-Host "++++++++++++++++++++++Recursive Call to Enumerate" $objTemp.distinguishedName
GetGroupMember($objTemp)
Write-Host "---------------------- End Recursive Call to Enumerate" $objTemp.distinguishedName
}
# If user object then display its DN
if($flag -eq $False)
{
$objTemp.distinguishedName
$Global:GroupMembers += $objTemp.distinguishedName
#$objTemp.sAMAccountname
}
}
}
}
#
GetGroupMember $objGrp
""
""
"Final List:"
$Global:GroupMembers | sort -uniq | out-file c:\temp\test.csv
If your list of groups is in C:\grouplist.txt then you can use Get-Content to get the names, then loop through them:
$groupNames = Get-Content 'C:\grouplist.txt'
foreach($groupName in $groupNames)
{
GetGroupMember [ADSI]$groupName
}
"Final List:"
$Global:GroupMembers | sort -uniq | out-file c:\temp\test.csv

Text Pattern Processing in paragraph with unix linux utilities

I have a file with the following pattern (please note this is a file generated using sed,
awk, grep etc processing). The part of file input is as follows.
filename1,
BASE=a/b/c
CONFIG=$BASE/d
propertiesfile1=$CONFIG/e.properties
EndOfFilefilename1
filename2,
BASE=f/g/h
CONFIG=$BASE/i
propertiesfile1=$CONFIG/j.properties
EndOfFilefilename2
filename3,
BASE=k/l/m
CONFIG=$BASE/n
propertiesfile1=$CONFIG/o.properties
EndOfFilefilename3
I want the output like
filename1,a/b/c/d/e.properties,
filename2,f/g/h/i/j.properties,
filename3, k/l/m/n/o.properties,
I could not find a solution with sed or awk or grep. So I ams tuck. Please do let me know if you know the solution with these unix utilities or any other language, platform.
Regards,
Suhaas
Assuming you generated the original file, and therefore it is safe to execute it as a script:
sed -e 's/^.*,/FILE=&/' \
-e 's/^.*=\$CONFIG/PROPFILE=$CONFIG/' \
-e 's/^EndOfFile.*/echo $FILE $PROPFILE/' < yourInputFile | sh
This converts each section of your file into the form:
FILE=filename1,
BASE=a/b/c
CONFIG=$BASE/d
PROPFILE=$CONFIG/e.properties
echo $FILE $PROPFILE
... and then sends it into a shell for processing.
Line-by-line explanation:
Line 1: Searches for the lines ending in a comma (the filenames), and sets FILE to the name.
Line 2: Searches for lines that set the properties file, and renames the variable to PROPFILE.
Line 3: Replaces the EndOfFile lines with a command to echo the file name and the properties file, then pipes it into a shell.
This is an excellent use case for structural regular expressions, which have been implemented as a python library, amongst other places. Here's an article which descibes how to emulate SREs in Perl.
And here is an awk script to process that input and generate what you want:
BEGIN {
FS="="
state = 0;
base = "";
config = "";
prop = "";
filename = "";
dbg = 0;
}
/^BASE=/ {
if (dbg) {
print "BASE";
print $0;
}
if (state != 1) {
print "Error base!";
exit 1;
}
state++;
base = $2;
if (dbg > 1) printf ("BASE = %s\n", base);
}
/^CONFIG=/ {
if (dbg) {
print "CONFIG";
print $0;
}
if (state != 2) {
print "Error config!";
exit 1;
}
state++;
config = $2;
sub (/\$BASE/, base, config);
if (dbg > 1) printf ("CONFIG = %s\n", config);
}
/^propertiesfile1=/ {
if (dbg) {
print "PROP";
print $0;
}
if (state != 3) {
print "Error pF!";
exit 1;
}
state++;
prop = $2;
sub (/\$CONFIG/, config, prop);
}
/^EndOfFile/ {
if (dbg) {
print "EOF";
print $0;
}
if (state != 4) {
print "Error EOF!";
print state;
exit 1;
}
state = 0;
printf ("%s%s,\n", filename, prop);
}
/,$/{
if (dbg) {
print "FILENAME";
print $0;
}
if (state != 0) {
print "Error filename!";
print state;
exit 1;
}
state++;
filename = $1;
}
gawk
gawk -vRS= 'BEGIN{FS="BASE[=]?|CONFIG|\n"}
{
s=$1
for(i=1;i<=NF;i++){
if($i~/\// ){ s=s $i }
}
print s
s=""
}' file
output
$ more file
filename1,
BASE=a/b/c
CONFIG=$BASE/d
propertiesfile1=$CONFIG/e.properties
EndOfFilefilename1
filename2,
BASE=f/g/h
CONFIG=$BASE/i
propertiesfile1=$CONFIG/j.properties
EndOfFilefilename2
filename3,
BASE=k/l/m
CONFIG=$BASE/n
propertiesfile1=$CONFIG/o.properties
EndOfFilefilename3
$ ./shell.sh
filename1,a/b/c/d/e.properties
filename2,f/g/h/i/j.properties
filename3,k/l/m/n/o.properties
A perl script that does what you want would be something like (note this is untested)
while (<>) {
$base = $1 if (m/BASE=(.+)/);
$config = $1 if (m/CONFIG=(.+)/);
if (m/propertiesfile1=(.+)/) {
$props = $1;
$props =~ m/\$CONFIG/$config/;
$props =~ m/\$BASE/$base/;
print $ARGV . ", " . $props . "\n";
}
}
you give the script the filenames as arguments.
Multi-steps but it works!
cat yourInputFile | egrep ',|\/' | \
sed -e "s/^.*=//g" -e "s/\$.*\(\/.*\)/\1/g" | \
awk '{if($0 ~ "properties") print $0; else printf $0}'
The egrep grabs the lines containing a "," or a "/" and so eliminates the last line:
BASE=a/b/c
CONFIG=$BASE/d
propertiesfile1=$CONFIG/e.properties
The sed reduces the output to:
filename1,
a/b/c
/d
/e.properties
The awk portion reassembles the line to:
filename1,a/b/c/d/e.properties