Bug #8353
Fully support stanza INI LOAD/USE/UNLOAD scenarios
0%
Related issues
History
#1 Updated by Roger Borrello over 2 years ago
- Related to Feature #4517: optionally back the 4GL features for Registry access with the user-specific offline storage features added
#2 Updated by Roger Borrello over 2 years ago
Continuing progress on #4517...
When I introduced a testcase, there is other breakage since there are strange aspects to how Progress deals withLOAD/USE/UNLOAD in the areas of:
- The .ini extension doesn't seem to be required, it is added when needed
- The case of the INI value must match between LOAD/USE/UNLOAD.
The testing setup is taking longer than the code update, but I believe my updates in revision 15010 of this branch now handle what I've been able to test much better.
The rules I've found via checks on Progress are:- The fname and envname are 2 distinct entities in LOAD/USE/UNLOAD
- In LOAD, envname is the fname stripped and fname is forced to .ini extension, if none given.
- fname is the primary key. Lookups are done matching the envname to the filename and the first match is returned.
- In USE/UNLOAD, if an extension is passed it must match the fname, or fail.
- If an extension is not passed, first envname is checked for. If not found, then .ini appended and checked against the fname.
- All checks are case-sensitive
- use various combinations of names passed to
LOADand attemptUSE/UNLOADwith matching/non-matching combinations. - utilize multiple
LOADstatements in various orders, and verify usingGET-KEY-VALUEto validate values. - determine if a new file is created properly by writing/reading
- read groups of sections and keys by passing null where appropriate
- be performed in GUI and ChUI
There is a bug in the reading of a file when a section is the last line:
[section1] key1 = value3txt1 key2 = value3txt2 [section2]
I have to add a newline at the end of the file for section2 to be found.
Here is my currently manual testcase:
def var path as char init "testcases_v2/abl/stanza_ini". def var inidir as char. inidir = "z:/" + path. if opsys = "unix" then inidir= "/home/rfb/" + path. if opsys <> "win32" then message opsys "is an unsupported OS". DEFINE VARIABLE keyval AS CHARACTER NO-UNDO FORMAT "x(128)". /* Normal checks */ load "env.1.inifile" dir inidir base-key "INI". use "env.1.inifile". GET-KEY-VALUE SECTION "section1" KEY "key1" VALUE keyval. message "keyval="keyval. use "". unload "env.1.inifile". load "env1.ini" dir inidir base-key "INI". use "env1". GET-KEY-VALUE SECTION "section1" KEY "key1" VALUE keyval. message "keyval="keyval. use "". unload "env1". load "env1" dir inidir base-key "INI". use "env1.ini". GET-KEY-VALUE SECTION "section1" KEY "key1" VALUE keyval. message "keyval="keyval. use "". unload "env1". load "env1.ini" dir inidir base-key "INI". use "env1.ini". GET-KEY-VALUE SECTION "section1" KEY "key1" VALUE keyval. message "keyval="keyval. use "". unload "env1.ini". load "env3.txt" dir inidir base-key "INI". load "env3" dir inidir base-key "INI". use "env3". GET-KEY-VALUE SECTION "section1" KEY "key1" VALUE keyval. message "keyval="keyval. GET-KEY-VALUE SECTION "" KEY "key1" VALUE keyval. message "keyval="keyval. GET-KEY-VALUE SECTION "section1" KEY "" VALUE keyval. message "keyval="keyval. GET-KEY-VALUE SECTION "section" KEY DEFAULT VALUE keyval. message "keyval="keyval. unload "env3". use "". GET-KEY-VALUE SECTION "section1" KEY "key1" VALUE keyval. message "keyval="keyval.
#3 Updated by Roger Borrello over 2 years ago
I was able to learn enough to be dangerous for creating an ABL Unit testcase for stanza_ini. These 2 files are in tests/stanza_ini.
Suite.cls:
block-level on error undo, throw. @TestSuite(classes="tests.stanza_ini.Test"). class tests.stanza_ini.Suite: end class. /* EOF */
Test.cls:
using OpenEdge.Core.Assert.
block-level on error undo, throw.
/* Core tests for stanza INI file usage, refs #8353 */
class tests.stanza_ini.Test:
@Before.
method public void UT_SceneSetup():
session:suppress-warnings = false.
end method.
@After.
method public void UT_SceneTeardown():
end method.
@Setup.
method public void UT_TestSetup():
os-delete ./env.ini.
end method.
@TearDown.
method public void UT_TestTeardown():
os-delete ./env.ini.
end method.
@Test.
method public void TestSimpleNoIni():
/* Case 1 load should fail. No oddities */
LOAD "env.ini" DIR "./".
support.test.AssertExt:Error(4449, 'The LOAD of env.ini in path ./ failed. (4449)').
end method.
end class. /* Test */
/* EOF */
But there is a failure in conversion:
[java] ------------------------------------------------------------------------------
[java] Code Conversion Annotations
[java] ------------------------------------------------------------------------------
[java]
[java] Optional rule set [customer_specific_annotations_prep] not found.
[java] ./tests/stanza_ini/Suite.cls
[java] ./tests/stanza_ini/Test.cls
[java] Null annotation (full-java-class) for support.test.AssertExt [CLASS_NAME] @32:7 (231928234154)
[java] Null annotation (simple-java-class) for support.test.AssertExt [CLASS_NAME] @32:7 (231928234154)
[java] Null annotation (containing-package) for support.test.AssertExt [CLASS_NAME] @32:7 (231928234154)
[java] Null annotation (found-in-full-java-class) for Error [OO_METH_VOID] @32:30 (231928234155)
[java] EXPRESSION EXECUTION ERROR:
[java] ---------------------------
[java] persist()
[java] ^ { null value for annotation 'full-java-class':support.test.AssertExt [CLASS_NAME]:231928234154 @32:7
[java] }
[java] ---------------------------
[java] ERROR:
[java] com.goldencode.p2j.pattern.TreeWalkException: ERROR! Active Rule:
[java] -----------------------
[java] RULE REPORT
[java] -----------------------
[java] Rule Type : POST
[java] Source AST: [ block ] BLOCK/ @0:0 {231928233985}
[java] Copy AST : [ block ] BLOCK/ @0:0 {231928233985}
[java] Condition : persist()
[java] Loop : false
[java] --- END RULE REPORT ---
I'm not too familiar with OO conversion. Is there any pointers to what this might be?
#4 Updated by Roger Borrello over 2 years ago
The failure was because I didn't include support/test/AssertExt.cls in the conversion file. Now I get:
[javac] /home/rfb/projects/testcases_v2_dev2/src/com/goldencode/testcases/tests/stanza_ini/Suite.java:14: error: incompatible types: Suite cannot be converted to Annotation
[javac] @Suite
[javac] ^
[javac] /home/rfb/projects/testcases_v2_dev2/src/com/goldencode/testcases/tests/stanza_ini/Test.java:80: error: incompatible types: Test cannot be converted to Annotation
[javac] @Test(order = 1)
[javac] ^
[javac] 2 errors
The Suite.java was created, so I'm not sure what I did wrong. Vladimir, if there's any help getting this "Hello World" testcase going, I'd appreciate it.
...
/**
* Business logic (converted to Java from the 4GL source code
* in tests/stanza_ini/Suite.cls).
*/
@Suite
@SelectClasses(value =
{
"tests.stanza_ini.Test"
})
public class Suite
extends BaseObject
{
...
#5 Updated by Roger Borrello over 2 years ago
- Assignee set to Roger Borrello
- Status changed from New to WIP
By changing my test to a procedure, I was able to get it running.
I am finding that LOAD gIniName DIR gDir. results in NPE when we get to the client side EnvironmentDaemon.load, as baseKey is null:
public boolean load(String env,
String directory,
boolean flagNew,
String baseKey)
{
EnvironmentReader envAcc;
Map<String, EnvironmentReader> envs;
boolean isIniType = EnvironmentReader.TYPE_INI.equalsIgnoreCase(baseKey);
if (!isIniType && !PlatformHelper.isUnderWindowsFamily())
{
envs = envFallbackMap;
env = env.toLowerCase();
envAcc = new FallbackEnvironmentReader(env, clientStorage, baseKey.toLowerCase()); // <-- NPE here
}
I'm thinking we should invoke from the server side
EnvironmentOps.load with more protection:
if (baseKey != null)
{
baseKeyAsString = baseKey.toStringMessage();
}
else // Add an else case
{
baseKeyAsString = new String("");
}
if (!Environments.load(envAsString, directoryAsString, flagNewAsBoolean, baseKeyAsString))
{
onLoadError(env, directory);
}
#6 Updated by Roger Borrello over 2 years ago
Actually, the fact that baseKey is null should be OK on the client side. It just needs to be a little more protected, since FallbackEnvironmentReader can accept a null:
boolean isIniType = EnvironmentReader.TYPE_INI.equalsIgnoreCase(baseKey);
if (!isIniType && !PlatformHelper.isUnderWindowsFamily())
{
envs = envFallbackMap;
env = env.toLowerCase();
baseKey = (baseKey != null) ? baseKey.toLowerCase() : baseKey;
envAcc = new FallbackEnvironmentReader(env, clientStorage, baseKey);
}
There is a problem with this case of trying to load a file that doesn't exist, such as my first testcase, LOAD "env.ini" DIR "./". because we get to the fallback environment. In Progress, we get an error, because somehow it knows that env.ini is a file, even though it doesn't exist, and we don't specify basekey "INI".
The LOAD documentation for environment has:
A CHARACTER expression that evaluates to one of the following:
- The name of a registry key to create
- The name of an initialization file to create
- The name of an existing registry key
- The name of an existing initialization file
So I am not sure how to get boolean isIniType to be true, if we don't have a file, nor pass the basekey. Perhaps assuming it is INI if there is .ini at the end of the environment?
#7 Updated by Greg Shah over 2 years ago
Actually, the fact that
baseKeyis null should be OK on the client side. It just needs to be a little more protected, sinceFallbackEnvironmentReadercan accept a null:
Correct, the null has meaning.
Perhaps assuming it is INI if there is
.iniat the end of the environment?
It seems reasonable approach if basekey is null or possibly if it is the empty string (please check this in the 4GL).
#8 Updated by Roger Borrello almost 2 years ago
I did a test on the legacy application, and that was to remove the .ini that is loaded upon executing the "Edit colors" function. In FWD, we exit the application, since the error condition is passed on. When I debugged, the legacy application didn't display any error regarding the file not being found, like we do in FWD. Just an observation that needs to check out the NO ERROR results in a testcase.
#9 Updated by Roger Borrello almost 2 years ago
I am trying to duplicate the situation on the customer application where the INI file is not found when a USE occurs. However, this is a Windows GUI and the server is Unix. In Progress, does this Windows client still look in the Windows OS for the INI file? It doesn't look at the server, correct?
#10 Updated by Galya B almost 2 years ago
OE doc on LOAD says in Notes (the last section) what's the exact order of looking for the environment. When BASE-KEY "INI" is not added, Progress looks through the registry with and without the extension of the environment name and finally checks for the file. In the whole process ".ini" is never added to the file name. Initialization files in Progress can have any extension. The only ".ini" coming from Progress is when NEW BASE-KEY "INI" needs to create a new file and .ini is added to the env name. The environment having or not having .ini in the name seems irrelevant to any lookup logic, so env.ini is a valid registry env and inifile is a valid initialization file. So this .ini concat in our code seems wrong.
The other thing: EnvironmentDaemon.load should be extended to do an actual search in the registry before assigning envAcc, when the OS is Windows, baseKey is not "ini" and flagNew is false. Then if not found, set the env as ini continue with the current load logic.
It can get messy with such rework, so posting the results of the tests in both Progress and FWD can help pinpoint the necessary changes.
As for the server / client question. Isn't Progress running thick desktop clients, so they are always on the 'server'?
#11 Updated by Galya B almost 2 years ago
One more thing, since one and the same env name can be both a registry entry and an ini file in different calls, we still need to account for it. With all environments going in the same map, something needs to change.
#12 Updated by Greg Shah almost 2 years ago
In Progress, does this Windows client still look in the Windows OS for the INI file?
Whether it is a registry lookup or an INI file access, the LOAD statement is exclusively executed on the local OS.
It doesn't look at the server, correct?
Correct.
Isn't Progress running thick desktop clients, so they are always on the 'server'?
Yes, they are thick desktop clients. They do not call over to the appserver to do the LOAD which I think is what Roger was asking about.
#13 Updated by Roger Borrello almost 2 years ago
Greg Shah wrote:
Yes, they are thick desktop clients. They do not call over to the appserver to do the
LOADwhich I think is what Roger was asking about.
Exactly. I was trying to duplicate the scenario on the customer's configuration, and it worked whether the file.ini existed or not. I wasn't sure if renaming it on the client workstation should have been enough.
I know I'm focusing a lot on this particular customer's configuration, but I'm trying to get my head around how Progress handles INI files. I don't even see where the application is performing a LOAD, since my break point in EnvironmentalDaemon.load() was never hit. I was under the impressiona LOAD has to be performed first, and my simple testcase bears that out. It's difficult to plan a testcase if Progress behaves differently under different configurations, like a thick desktop client versus a Windows VM running prowin.exe.
#14 Updated by Greg Shah almost 2 years ago
In that customer's case, aren't they specifying the -ininame command line parameter in OE? In other words, it is a kind of implicit LOAD statement.
#15 Updated by Roger Borrello almost 2 years ago
Greg Shah wrote:
In that customer's case, aren't they specifying the
-ininamecommand line parameter in OE? In other words, it is a kind of implicitLOADstatement.
I believe so, but the INI specified on the command line isn't the same as the one specified in the USE statement.
#16 Updated by Greg Shah almost 2 years ago
And what is the USE statement? If it is USE "". then it is just making the default environment the current environment.
#17 Updated by Roger Borrello almost 2 years ago
Greg Shah wrote:
And what is the
USEstatement? If it isUSE "".then it is just making the default environment the current environment.
No, it's USE inifile without an extension. When the system is available, I'll take another look and note specifics.
#18 Updated by Roger Borrello almost 2 years ago
The command line used is: C:\Progress\OpenEdge\bin\prowin32.exe -assemblies clientnet -basekey "ini" -ininame progress-medium -pf xxx.pf
The directory is: C:\DEV\sources\client
The progress-medium.ini file is found in C:\Users\fwd\Desktop\backup\client which is also where the appname-DEV-HV01.ini is found that the USE is "using". But like I said, I can't seem to catch any LOAD when I debug the FWD application by breaking in FWD. If there is a place where LOAD is performed, it might help to get the customer to point it out, since I don't think -ininame is doing it. There's no mention of the appname-DEV-HV01.ini in the progress-medium.ini file.
#19 Updated by Galya B almost 2 years ago
Is initialization-file (progress-medium) specified in the client bootstrap configs for the FWD client? It is supposed to call EnvironmentDaemon.setDefaultEnvironment and set defaultEnv instead of calling load.
As for appname-DEV-HV01.ini, look in the -pf file, but unlikely to be there. It looks like a concatenated name, the LOAD can be somewhere unexpected. Check for any LOAD in the original code. It may not have been migrated for some reason.
#20 Updated by Roger Borrello almost 2 years ago
Galya B wrote:
Is
initialization-file(progress-medium) specified in the client bootstrap configs for the FWD client? It is supposed to callEnvironmentDaemon.setDefaultEnvironmentand setdefaultEnvinstead of callingload.
Yes, it uses a user_client.xml specified in the directory:
<node type="client">
<client>
<project token="gui" />
<cmd-line-option initialization-file="progress-medium.ini" />
<logging path="../logs/gui_%uos_%pid_%uf_%g.log" rotationLimit="500000" rotationCount="4" />
</client>
</node>
So that explains how the default environment is setup.
As for
appname-DEV-HV01.ini, look in the -pf file, but unlikely to be there. It looks like a concatenated name, the LOAD can be somewhere unexpected. Check for anyLOADin the original code. It may not have been migrated for some reason.
I believe I have the reports still around, so I'll find it.
In any case, I see the Progress behavior is to give an error when USE is performed, without a LOAD. This little test shows "The USE of x.ini failed (4452)" on Progress:
message "using x.ini no-error". use "x.ini" no-error. message "using x.ini". use "x.ini".
So I need to find the LOAD.
#21 Updated by Roger Borrello almost 2 years ago
Roger Borrello wrote:
I believe I have the reports still around, so I'll find it.
I had the 7z file, but the files in callgraph are very small, so something must have gone wrong. Is EnvironmentalDaemon.load() where every LOAD would pass through? I debugged server startup, but I may have missed one of the clients, although I can only picture the web client being what might execute LOAD, not an app server.
#22 Updated by Galya B almost 2 years ago
Roger Borrello wrote:
Roger Borrello wrote:
I believe I have the reports still around, so I'll find it.
I had the 7z file, but the files in callgraph are very small, so something must have gone wrong. Is
EnvironmentalDaemon.load()where everyLOADwould pass through? I debugged server startup, but I may have missed one of the clients, although I can only picture the web client being what might executeLOAD, not an app server.
Any OE code can use LOAD. To USE an env, the code should either LOAD, or have the startup param. Can you simply search in the original OE code for LOAD? If you find the mechanism of loading the file in the original setup, it would be easier to reason about the FWD conversion.
#23 Updated by Roger Borrello almost 2 years ago
Galya B wrote:
Any OE code can use
LOAD. ToUSEan env, the code should eitherLOAD, or have the startup param. Can you simply search in the original OE code forLOAD? If you find the mechanism of loading the file in the original setup, it would be easier to reason about the FWD conversion.
I tried to use prowin.exe -p useit.p -ininame p.ini where p.ini was a copy of the C:\progress\oe116_64\bin\progress.ini. The useit.p contains:
message "using env1". use "env1". message "used env1".
I get error 4452 trying to
use and no load before it. This is very similar to how the customer application is structured, but does not fail in the same manner. In the reports, I see all the places where load is being performed in the application code, and I am not hitting any breakpoint in EnvironmentDaemon.load(), even when debugging the initialization of the web client.#24 Updated by Galya B almost 2 years ago
Don't debug FWD, we need to debug their OE code running on Progress to understand what hasn't been migrated to FWD. If you specify -ininame p.ini cmd line, then you can't load env1. It should be use p.ini.
My point was to do a plain text search in their original code to find the LOAD uses.
#25 Updated by Greg Shah almost 2 years ago
My point was to do a plain text search in their original code to find the
LOADuses.
Don't use plain text search. Use FWD Analytics. The language statements support will show you EVERY location of LOAD in the application and there will be no false positives (matches to the text load that are really something else) or false negatives (missed matches because of some weirdness in the text matching like case-sensitivity or otherwise). For something simple like LOAD, false negatives are unlikely but false positiives are very likely. Just use FWD Analytics, it is why we made it.
#26 Updated by Galya B almost 2 years ago
Does FWD Analytics work over a file directory with original OE code or does it need the app loaded in FWD?
#27 Updated by Greg Shah almost 2 years ago
It is a developer tool that operates on 4GL source code. If that code is what is running in OE, then we are getting a true picture.
Roger mentioned "reports" in #8353-23, which is probably a reference to FWD Analytics. If that is correct, then he should be making a plan to look at these locations in OE not in FWD. If he has a debuggable environment on OE (unfortunately, not always the case) that could be used or those locations could be instrumented with logging.
#28 Updated by Roger Borrello almost 2 years ago
Galya B wrote:
Don't debug FWD, we need to debug their OE code running on Progress to understand what hasn't been migrated to FWD. If you specify
-ininame p.inicmd line, then you can't loadenv1. It should beuse p.ini.
I'm pretty sure everything has been migrated. I can use the analytics to determine what might be performing the load, and can set breaks in the legacy code, to see. However, it appears I have to attach to the process at a certain point in execution, so if the load happens during initialization, I wouldn't be able to catch it (unless there is a debug technique I don't know about, which is highly likely).
Greg Shah wrote:
Roger mentioned "reports" in #8353-23, which is probably a reference to FWD Analytics. If that is correct, then he should be making a plan to look at these locations in OE not in FWD. If he has a debuggable environment on OE (unfortunately, not always the case) that could be used or those locations could be instrumented with logging.
Exactly. I had to get a 5TB external drive to allow me space to hold the database, which is 91GB.
The load [KW_LOAD] (36 in 20 files) is reported, and almost have are the LOAD ""., so it's about 18 spots in 20 files. I can break in those to find this.
#29 Updated by Roger Borrello almost 2 years ago
I found the actual load. I set about 8 breakpoints, and caught it. The EnvironmentDaemon.load() pushes the environment named without any .ini extension, but in EnvironmentDaemon.use(), it attempts to retrieve the environment with a .ini extension.
My update in 4517b makes sure the environment named with .ini at the end, so it does get found, but could do the opposite... make sure there isn't any .ini during the push, and pull.
#30 Updated by Roger Borrello almost 2 years ago
- % Done changed from 0 to 100
- Status changed from WIP to Review
I have committed revision 15388 of branch 4517b, which ensures that the environment name for INI does not contain an extension both when creating the Stanza INI during LOAD, and when finding it via USE.
I would appreciate if there could be a review.
I also looked for some LOAD/USE testcases, but don't find any. Marian, can you point me towards them?
#31 Updated by Galya B almost 2 years ago
I haven't worked on StanzaIni.java, but with all the questions around adding the registry fallback for Linux, I probably know enough to help. But Roger, can you formulate with an example what is the problem found on trunk and what is the solution provided in 4517b. There are certain parts that don't make sense to me, like removing the original file extension with envName = env.substring(0, lastIndex);.
#32 Updated by Greg Shah almost 2 years ago
Agreed. We need to see the 4GL testcase(s) that show the difference between OE and FWD. Then we can assess your changes.
#33 Updated by Roger Borrello almost 2 years ago
Greg Shah wrote:
Agreed. We need to see the 4GL testcase(s) that show the difference between OE and FWD. Then we can assess your changes.
This is the testcase:
load "env1". use "env1". GET-KEY-VALUE SECTION "section1" KEY "key1" VALUE keyval. message "keyval="keyval. use "". unload "env1".
and the
env1.ini contains:[section1] key1 = value11 key2 = value12 [section2]
OE will show keyval=value11. In trunk, there will be an NPE since the trunk EnvironmentDaemon.load() has:
...
boolean isIniType = EnvironmentReader.TYPE_INI.equalsIgnoreCase(baseKey);
if (!isIniType && !PlatformHelper.isUnderWindowsFamily())
{
envs = envFallbackMap;
env = env.toLowerCase();
envAcc = new FallbackEnvironmentReader(env, clientStorage, baseKey.toLowerCase());
}
...
My updates to protect the .toLowerCase(), but we really need to be able to determine that "env1" is an ini Type. OE does that. We will create a fallback environment, but there isn't any data backing it.
This branch contains:
boolean isIniType = EnvironmentReader.TYPE_INI.equalsIgnoreCase(baseKey) ||
(env.toLowerCase().endsWith(".ini"));
if (!isIniType && !PlatformHelper.isUnderWindowsFamily())
{
envs = envFallbackMap;
env = env.toLowerCase();
baseKey = (baseKey != null) ? baseKey.toLowerCase() : baseKey;
envAcc = new FallbackEnvironmentReader(env, clientStorage, baseKey);
}
else if (isIniType)
{
envs = envIniMap;
envAcc = new StanzaIni(env, directory, flagNew, isReadOnly);
}
but it needs to not just look to see if the environment passed has
.ini extension, it needs to determine if there is a file backing it before falling back.
I could use a clue on how to do that check here, so we can find "env1.ini", even though just "env1" is passed in.
#34 Updated by Roger Borrello almost 2 years ago
- % Done changed from 100 to 90
- Status changed from Review to WIP
#35 Updated by Marian Edu almost 2 years ago
Roger,
I've pushed some unit tests for this environment INI support - you can find them under tests/base_language/environment_registryINI_access in testcases rev #1628.
#36 Updated by Greg Shah almost 2 years ago
I could use a clue on how to do that check here, so we can find "env1.ini", even though just "env1" is passed in.
I would create a method public static boolean isIniFile(String filename) in StanzaIni which should implement the same testing logic the OE uses. You can read the code in that class to see how it accesses the filesystem. Use the same techniques.
Galya will review it to confirm that it doesn't cause problems with her work in #4065.
#37 Updated by Galya B almost 2 years ago
According to the section Notes in LOAD statement the default LOAD without BASE-KEY "INI" first looks in the registry, so the current trunk implementation is correct in this regard. On Linux the registry is the fallback env, so the new part of the condition is not correct (looking for the ext). Actually what's missing is that the FallbackEnvironmentReader needs to check if the 'registry key' exists and then fallback to StanzaIni (but only if BASE-KEY key-name is not specified).
#38 Updated by Galya B almost 2 years ago
Greg Shah wrote:
I could use a clue on how to do that check here, so we can find "env1.ini", even though just "env1" is passed in.
I would create a method
public static boolean isIniFile(String filename)inStanzaIniwhich should implement the same testing logic the OE uses. You can read the code in that class to see how it accesses the filesystem. Use the same techniques.Galya will review it to confirm that it doesn't cause problems with her work in #4065.
Roger can add anything necessary, I'll take it into consideration on merge.
The actual method should be checking for the 'registry key' via the fallback env.
#39 Updated by Roger Borrello almost 2 years ago
Galya B wrote:
According to the section Notes in LOAD statement the default
LOADwithoutBASE-KEY "INI"first looks in the registry, so the current trunk implementation is correct in this regard. On Linux the registry is the fallback env, so the new part of the condition is not correct (looking for the ext). Actually what's missing is that theFallbackEnvironmentReaderneeds to check if the 'registry key' exists and then fallback toStanzaIni(but only ifBASE-KEY key-nameis not specified).
So in load, before calling FallbackEnvironmentReader it would need to check for 'registry key'? What section/key would be checked in clientStorage for that indication?
In my testing I have found that loading "env3.txt" and then "env3" ignores the 2nd load, because the values I read came from "env3.txt", so it much check that an environment is already in place, and doesn't override it, nor keep a 2nd because of extensions being different. I'll have to add a check for exiting env before putting another of the same name.
#40 Updated by Galya B almost 2 years ago
Roger Borrello wrote:
Galya B wrote:
According to the section Notes in LOAD statement the default
LOADwithoutBASE-KEY "INI"first looks in the registry, so the current trunk implementation is correct in this regard. On Linux the registry is the fallback env, so the new part of the condition is not correct (looking for the ext). Actually what's missing is that theFallbackEnvironmentReaderneeds to check if the 'registry key' exists and then fallback toStanzaIni(but only ifBASE-KEY key-nameis not specified).So in
load, before callingFallbackEnvironmentReaderit would need to check for 'registry key'? What section/key would be checked inclientStoragefor that indication?
ClientStorageImpl relies on two types of KeyValueStorage. Both UserPreferences and LocalStorageAccessor will need a new method along the lines of doesSectionExist that will lookup for the path instead of a specific key. The path is concat by first adding env and baseKey in FallbackEnvironmentReader and then fwdUser and storageId in KeyValueStorage. LocalStorageAccessor will require a trip to the browser and probably some weird parsing of the whole storage content. For UserPreferences it's an easy check with preferences.nodeExists(section).
In my testing I have found that loading "env3.txt" and then "env3" ignores the 2nd load, because the values I read came from "env3.txt", so it much check that an environment is already in place, and doesn't override it, nor keep a 2nd because of extensions being different. I'll have to add a check for exiting env before putting another of the same name.
You can load many envs, but the values will be taken from the env that is in use. If the env has been loaded with startup args it's probably in use.
Roger, now that we've identified the problem and the solution, I can take over the task if you don't mind. I wasn't aware of that lookup rule, when first implemented the fallback env. If the customer's code uses BASE-KEY "INI" this is not replicable.
#41 Updated by Greg Shah almost 2 years ago
- Assignee changed from Roger Borrello to Galya B
#42 Updated by Roger Borrello almost 2 years ago
- Assignee changed from Galya B to Roger Borrello
Galya B wrote:
You can load many envs, but the values will be taken from the env that is in
use. If the env has been loaded with startup args it's probably in use.
The point I was making was when you have multiple LOAD in effect with the same environment name, but different files, the first one loaded is used.
Take this example:
load "env3.txt" dir inidir base-key "INI". load "env3" dir inidir base-key "INI". use "env3". GET-KEY-VALUE SECTION "section1" KEY "key1" VALUE keyval. message "keyval="keyval. GET-KEY-VALUE SECTION "" KEY "key1" VALUE keyval. message "keyval="keyval. GET-KEY-VALUE SECTION "section1" KEY "" VALUE keyval. message "keyval="keyval. GET-KEY-VALUE SECTION "section" KEY DEFAULT VALUE keyval. message "keyval="keyval. unload "env3". use "". GET-KEY-VALUE SECTION "section1" KEY "key1" VALUE keyval. message "keyval="keyval.
The contents of env3.txt is:
[section1] key1 = value3txt1 key2 = value3txt2 [section2]
The contents of env3.ini is:
[section1] key1 = value3ini1 key2 = value3ini2 [section2]
When executed, 4GL shows:
keyval= value3txt1 keyval= section1,section2 keyval= key1,key2 keyval= ? keyval= ?
When executed, FWD (trunk) shows:
keyval= value3ini1 keyval= section1 keyval= key1,key2 keyval= ? keyval= ?
So the wrong env3 is used. I don't think the 2nd load should have replaced the first.
Thanks for straightening this one out.
#43 Updated by Galya B almost 2 years ago
The logic with checking the registry before using ini should be implemented for regular Windows Registry as well, so it was an oversight from the beginning. Hope you can test Windows too.
#44 Updated by Greg Shah almost 2 years ago
- Assignee changed from Roger Borrello to Galya B
Roger: Please add your tests into the Testcases unit tests.
#45 Updated by Galya B almost 2 years ago
- Assignee changed from Galya B to Roger Borrello
Roger Borrello wrote:
Galya B wrote:
You can load many envs, but the values will be taken from the env that is in
use. If the env has been loaded with startup args it's probably in use.The point I was making was when you have multiple LOAD in effect with the same environment name, but different files, the first one loaded is used.
Take this example:
[...]The contents of
env3.txtis:
[...]The contents of
env3.iniis:
[...]When executed, 4GL shows:
[...]When executed, FWD (trunk) shows:
[...]So the wrong env3 is used. I don't think the 2nd load should have replaced the first.
Thanks for straightening this one out.
I've said that the file extension should not be removed in 4517b. Otherwise this type of issues occur.
I'll implement #8353-40 and #8353-43 and the issue in #8353-33 should be fixed.
#46 Updated by Galya B almost 2 years ago
- Assignee changed from Roger Borrello to Galya B
- % Done changed from 90 to 0
#47 Updated by Galya B almost 2 years ago
Roger Borrello wrote:
Greg Shah wrote:
Agreed. We need to see the 4GL testcase(s) that show the difference between OE and FWD. Then we can assess your changes.
This is the testcase:
[...]
and theenv1.inicontains:
[...]OE will show keyval=value11. In trunk, there will be an NPE since the trunk
EnvironmentDaemon.load()has:
[...]My updates to protect the
.toLowerCase(), but we really need to be able to determine that "env1" is an ini Type. OE does that. We will create a fallback environment, but there isn't any data backing it.This branch contains:
[...]
but it needs to not just look to see if the environment passed has.iniextension, it needs to determine if there is a file backing it before falling back.I could use a clue on how to do that check here, so we can find "env1.ini", even though just "env1" is passed in.
Where do you test Progress? I can't use the registry methods in the #5600 env, because I don't have admin rights and I get The LOAD of (key-value file) failed. (4450).
I can't find it anywhere in the documentation that loading env env1 will read from the file env1.ini and I want to test it.
#48 Updated by Roger Borrello almost 2 years ago
- Assignee changed from Galya B to Roger Borrello
#49 Updated by Galya B almost 2 years ago
Galya B wrote:
Where do you test Progress?
Not FWD.
#50 Updated by Galya B almost 2 years ago
My bad. This is a Progress VM. I didn't remember there is one.
#51 Updated by Greg Shah almost 2 years ago
Don't we have a Windows based 4GL dev system at multiple customers? Use one that is associated with the customer that inspired this task.
#52 Updated by Galya B almost 2 years ago
Greg Shah wrote:
Don't we have a Windows based 4GL dev system at multiple customers? Use one that is associated with the customer that inspired this task.
I've never used it. Does it come with admin rights? Otherwise the registry can't be used it seems.
#53 Updated by Roger Borrello almost 2 years ago
Galya B wrote:
I've never used it. Does it come with admin rights? Otherwise the registry can't be used it seems.
We do not have admin rights on those environments. The VM, yes.
#54 Updated by Galya B almost 2 years ago
Testing Progress 11.6.3:
1. Create a new ini env:
LOAD "env1" NEW BASE-KEY "INI". USE "env1".
Creates an empty file
env1.ini in the Progress dir.
2. Create a new registry env without any keys:
LOAD "env1" NEW. USE "env1".
Doesn't create a registry section / key named
env1, or ini file, but gets executed successfully.
3. Try to use a registry env created without any keys (after 2.):
LOAD "env1". USE "env1".
Results in an error "The LOAD of env1 failed. (4450)".
4. Create a new registry env and put a key:
LOAD "env1" NEW. USE "env1". PUT-KEY-VALUE SECTION "section1" KEY "key1" VALUE "value1".
Creates a registry section
HKEY_CURRENT_USER/env1/section1 key key1 and value value1.
5. Create a new ini env with a name ending with .ini and put a key:
LOAD "env1.ini" NEW. USE "env1.ini". PUT-KEY-VALUE SECTION "section1" KEY "key1" VALUE "value1".
Creates a registry section
HKEY_CURRENT_USER/env1.ini/section1 key key1 and value value1.
6. Create a new ini env with a name ending with .ini and put a key:
LOAD "env1.ini" NEW BASE-KEY "INI". USE "env1.ini". PUT-KEY-VALUE SECTION "section1" KEY "key1" VALUE "value1".
Creates a file
env1.ini in the Progress dir with section [section1] and key1=value1.
7. Use an old ini env with a name ending with .ini and read a key (after 6.):
LOAD "env1.ini" BASE-KEY "INI". USE "env1". GET-KEY-VALUE SECTION "section1" KEY "key1" VALUE valuevar.
Reads
key1 in section [section1] from the file env1.ini in the Progress dir.
8. Create a new ini env with a name ending with .ext and put a key:
LOAD "env1.ext" NEW BASE-KEY "INI". USE "env1.ext". PUT-KEY-VALUE SECTION "section1" KEY "key1" VALUE "value1".
Creates a file
env1.ext in the Progress dir with section [section1] and key1=value1.
9. Use an old ini env with a name ending with .ext and read a key (after 8.):
LOAD "env1.ext" BASE-KEY "INI". USE "env1.ext". GET-KEY-VALUE SECTION "section1" KEY "key1" VALUE valuevar.
Reads
key1 in section [section1] from the file env1.ext in the Progress dir.
10. Use an old ini env with a name ending with .ext and read a key (after 8.):
LOAD "env1.ext" BASE-KEY "INI". USE "env1". GET-KEY-VALUE SECTION "section1" KEY "key1" VALUE valuevar.
Reads
key1 in section [section1] from the file env1.ext in the Progress dir.
11. Create a new ini env with a name ending with .ini.ext and put a key:
LOAD "env1.ini.ext" NEW BASE-KEY "INI". USE "env1.ini.ext". PUT-KEY-VALUE SECTION "section1" KEY "key1" VALUE "value1".
Creates a file
env1.ini.ext in the Progress dir with section [section1] and key1=value1.
12. Use an old ini env with a name ending with .ini.ext and read a key (after 11.):
LOAD "env1.ini.ext" BASE-KEY "INI". USE "env1.ini.ext". GET-KEY-VALUE SECTION "section1" KEY "key1" VALUE valuevar.
Reads
key1 in section [section1] from the file env1.ext in the Progress dir.
13. Use an old ini env with a name ending with .ini.ext and read a key (after 11.):
LOAD "env1.ini.ext" BASE-KEY "INI". USE "env1.ini". GET-KEY-VALUE SECTION "section1" KEY "key1" VALUE valuevar.
Results in an error
The LOAD of env1.ini failed. (4450).
14. Use an old ini env with a name ending with .ini.ext and read a key (after 11.):
LOAD "env1.ini.ext" BASE-KEY "INI". USE "env1". GET-KEY-VALUE SECTION "section1" KEY "key1" VALUE valuevar.
Results in an error
The LOAD of env1 failed. (4450).
15. Create two registry envs with the same name and different base-key or lack thereof:
LOAD "env1" NEW BASE-KEY "test". LOAD "env1" NEW.
Results in an error
The LOAD of env1 failed. (4450). Every variation of loading two different envs with the same name leads to the same result.
16. Load first a new ini env and load an env with the same name after that:
LOAD "env1" NEW BASE-KEY "INI". LOAD "env1.ini" NEW BASE-KEY "test". USE "env1". PUT-KEY-VALUE SECTION "section1" KEY "key1" VALUE "value1".
Creates a file
env1.ini in the Progress dir with section [section1] and key1=value1.
17. Load first a new registry env and load an ini env with the same name after that:
LOAD "env1.ini" NEW BASE-KEY "test". LOAD "env1" NEW BASE-KEY "INI".
Results in an error
The LOAD of env1.ini failed. (4450).
18. Create two new ini envs with a name ending with .ini and .ext respectively and put a key:
LOAD "env1.ini" BASE-KEY "INI". LOAD "env1.ext" BASE-KEY "INI". USE "env1". PUT-KEY-VALUE SECTION "section1" KEY "key1" VALUE "value1".
Creates two files
env1.ext and env1.ini in the Progress dir and puts section [section1] with key1=value1 in one of the files env1.ext.
19. Create several new ini envs with a name ending with unusual extensions and put a key:
LOAD "env1.abc" BASE-KEY "INI". LOAD "env1.wzc" BASE-KEY "INI". LOAD "env1.ert" BASE-KEY "INI". USE "env1". PUT-KEY-VALUE SECTION "section1" KEY "key1" VALUE "value1".
Creates the last file
env1.ert in the Progress dir and puts section [section1] with key1=value1 inside. On first attempt with a new env name, creates all files. After the files are deleted and the procedure re-executed, it creates only env1.ert, but from time to time one of the other files is also created (empty), it's not consistently reproducible.#55 Updated by Galya B almost 2 years ago
Testing Progress 11.6.3:
20. Create a new registry env and call use with the same name, but different case:
LOAD "env1" NEW. USE "ENV1".
Results in an error
The LOAD of ENV1 failed. (4452). Note the error number is different from the other errors with similar text. The same result with reverted values for load and use (first uppercase, then lowercase).
So it seems env names are case-sensitive. I'm not sure why we have env.toLowerCase(), but it will be removed.
#56 Updated by Galya B almost 2 years ago
My tests show that BASE-KEY can be only one of the root keys for Windows: HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CURRENT_CONFIG or INI. In any other case running Progress in Windows LOAD returns the error 4450. Also, I wasn't able to actually use HKEY_LOCAL_MACHINE, HKEY_USERS even when starting as admin, it causes the error The PUT-KEY-VALUE failed. (4454).
Marian / Roger, can we confirm this behavior? I'm not sure if we want to migrate it. Also I'm not sure if Progress can be running on Linux and behave differently in this department.
This behavior is important though, when making conclusions based on the tests. I'll have to update #8353-54 to reflect it.
#57 Updated by Roger Borrello almost 2 years ago
Galya B wrote:
My tests show that
BASE-KEYcan be only one of the root keys for Windows:HKEY_CLASSES_ROOT,HKEY_CURRENT_USER,HKEY_LOCAL_MACHINE,HKEY_USERS,HKEY_CURRENT_CONFIGorINI. In any other case running Progress in WindowsLOADreturns the error4450. Also, I wasn't able to actually useHKEY_LOCAL_MACHINE,HKEY_USERSeven when starting as admin, it causes the errorThe PUT-KEY-VALUE failed.(4454).Marian / Roger, can we confirm this behavior? I'm not sure if we want to migrate it. Also I'm not sure if Progress can be running on Linux and behave differently in this department.
This behavior is important though, when making conclusions based on the tests. I'll have to update #8353-54 to reflect it.
Marian, I don't see any tests in tests/base_language/environment_registryINI_access that utilize BASE-KEY. Is that possible to add, with some of the options Galya listed?
#58 Updated by Roger Borrello almost 2 years ago
- Assignee changed from Roger Borrello to Galya B
#59 Updated by Galya B over 1 year ago
Our Win Registry implementation by default checks for the value (when no BASE-KEY specified) only in the root HKEY_CURRENT_USER section, while in OE it checks multiple locations under HKEY_CURRENT_USER and HKEY_LOCAL_MACHINE. Should we make FWD fully compatible with OE?
#60 Updated by Galya B over 1 year ago
There is a funky behavior in OE: create a key env1 directly in win registry under HKEY_LOCAL_MACHINE/SOFTWARE and run a procedure to LOAD (without NEW) + USE env1 and PUT a key value; reload the regisry and the value is actually written to HKEY_CURRENT_USER/Software. Rinse and repeat, same result. But the env is loaded originally from HKEY_LOCAL_MACHINE.
#61 Updated by Greg Shah over 1 year ago
Should we make FWD fully compatible with OE?
Yes
I can't speak for the funky behavior from #8353-60. That seems like a bug in OE. Normally we don't implement things that seem to be bugs, except when an application actually relies upon it. Then it is not a bug, it is a "quirk".
#62 Updated by Galya B over 1 year ago
Greg Shah wrote:
Should we make FWD fully compatible with OE?
Yes
I can't speak for the funky behavior from #8353-60. That seems like a bug in OE. Normally we don't implement things that seem to be bugs, except when an application actually relies upon it. Then it is not a bug, it is a "quirk".
I agree, it looks like a bug in the version I'm testing with. I won't look more into it, it shouldn't be reproduced either.
#63 Updated by Marian Edu over 1 year ago
Roger Borrello wrote:
Marian, I don't see any tests in
tests/base_language/environment_registryINI_accessthat utilizeBASE-KEY. Is that possible to add, with some of the options Galya listed?
Roger, the team will add some more tests including use of BASE-KEY, will reply back when available in testcases.
#64 Updated by Galya B over 1 year ago
- If the environment has one dot in the name, the part after the dot is considered file extension and allows the environment to be used without it. For example
LOAD "file.ext".and thenUSE "file". This applies to any ext, not only .ini. Also this applies only when the environment is considered INI file, i.e. the fallback ofLOADwithoutBASE-KEY "INI"when the key is not found in the registry, or whenBASE-KEY "INI"is specified explicitly. - If the environment has multiple dots in the name, only the full name can be used in
USE. - LOAD with
NEW BASE-KEY "INI"creates a new file with the given name and adds.inias file extension only when the name doesn't have a dot in the name. For exampleLOAD "test." NEW BASE-KEY "INI"creates a filetest, butLOAD "test" NEW BASE-KEY "INI"creates a filetest.ini. - Loading an old ini file works without specifying the ext, e.g.
LOAD "test".will load test.ini. This is not the behavior for any other ext type.LOAD "test" BASE-KEY "INI".doesn't load the filetestwithout the ini extension. - The Procedure Editor creates a cache of all environments loaded and often gives ambiguous results. For example creating a registry env (key) with name
test, later continuously refers to the same env even if it's deleted or an attempt to create an ini with the same name is executed by a different procedure. This behavior persists until the editor is closed. I think the same cache may be present in production environments. Needs to be kept in mind.
#65 Updated by Galya B over 1 year ago
- OE is case-sensitive between
LOADandUSE, but not when it comes to loading the key from registry or the file in Windows. In other wordsLOAD "Test.ini".loads the filetest.ini, butUSE "test.ini"doesn't work afterwards and fails with 4452.
The following procedure successfully loads the file test.ext twice with different cases and once the registry key test.ext and then expects a case-sensitive match to use the env.
LOAD "Test.EXT" BASE-KEY "INI". LOAD "TeSt.ext" LOAD "TeST.ext" BASE-KEY "INI". USE "TeSt.ext".
#66 Updated by Galya B over 1 year ago
All the above comments for USE (case-sensitivity and file extension) apply to UNLOAD too.
#68 Updated by Roger Borrello over 1 year ago
Galya, the situation where the application gives NPE noted in #8353-33 has been "re-reported" by the customer. I created branch 4517c since I could not rebase 4517b to the current trunk (so my changes were preserved). However, you had noted that my changes were probably not accurate, so if that branch isn't helpful it could be abandoned.
#69 Updated by Galya B over 1 year ago
Roger Borrello wrote:
Galya, the situation where the application gives NPE noted in #8353-33 has been "re-reported" by the customer. I created branch 4517c since I could not rebase 4517b to the current trunk (so my changes were preserved). However, you had noted that my changes were probably not accurate, so if that branch isn't helpful it could be abandoned.
I've started work in 8353a and there is only a little left to be completed. I'll try to schedule this work to one of the next days and we can discuss it again.
#70 Updated by Greg Shah over 1 year ago
- Assignee deleted (
Galya B)
The work to complete the implementation, as documented by Galya:
- confirm the native code is not case sensitive when doing checks in Win Registry
- implement the new JNI method Registry.hasKey
- convert permissions exception to an OE error