Feature #4517
optionally back the 4GL features for Registry access with the user-specific offline storage features
100%
Related issues
History
#1 Updated by Greg Shah over 4 years ago
In #4286, an offline storage facility was created that allows persistent storage/retrieval of key/value pairs in the user's local system. This implementation depends upon the client driver being used. For non-web based clients, the Java Preferences.userRoot()
is used. For web clients, the browser's local storage API is used. In both cases, the key/value pairs can survive across client restarts. The facility is included in trunk revision 11330. This initially is planned for usage by the enhanced browse (see #3880) to store user-specific configuration choices.
This task in intended to provide a mechanism that can be used at the 4GL code level. Now that we have a functioning direct Java access mechanism (see #3867), we can create a new helper class that provides a simple API for this service. Then 4GL code can access these Java classes directly to store/retrieve key/value pairs. We will document this as an enhancement capability of FWD, but at this time I think there is no reason to actually provide 4GL syntax changes. I just want the helper class to provide a clean and simple API that is easy to use by 4GL code.
One customer is planning to use this to store a kind of "device id" that differentiates the user's system in their application. Other customers may use this to store data that they would previously have stored in an ini file or in the Windows registry. Please start with reviewing the current offline storage capability. Then design an API that meets the requirements above. Post it here for review. The implementation won't be hard.
#2 Updated by Greg Shah over 4 years ago
- Related to Feature #4286: support user-specific offline storage that is provided by the client's UI driver added
#3 Updated by Greg Shah over 4 years ago
- Related to Feature #3880: enhanced browse 3rd phase of improvements added
#4 Updated by Greg Shah over 3 years ago
- Subject changed from create a facility available from converted 4GL code which allows persistent storage/retrieval of user-specific key/value pairs to optionally back the 4GL features for Registry access with the user-specific offline storage features
The 4GL features LOAD
, UNLOAD
, USE
, GET-KEY-VALUE
, PUT-KEY-VALUE
provide a mechanism to read and write key/value data from/into either INI files (any platform) or the Registry (Windows only). We support this fully.
Today, on non-Windows platforms, if the 4GL code is trying to access the registry, it will not work. When the FWD client runs on Windows it does work because the registry support is backed by native code (JNI) that handles reading/writing the registry using WIN32.
Nearly all 4GL GUI applications we have ever seen use the registry for some configuration. It seems silly that we don't transparently map this access into a similar feature on non-Windows platforms. This would allow any such code to just work instead of requiring it to be re-written.
In #4286, a persistent offline storage facility was created. This allows the storage and retrieval of key/value pairs from a client-specific storage medium (local storage in the browser and Java-based user preferences in non-web clients). This seems to be a perfect match for backing the registry support.
System-wide values won't be able to shared by multiple users, but that really should not matter much. The storage will be per-user and that is OK.
The other advantage of this approach is that there is no new 4GL syntax needed. We can implement this completely in the runtime.
#5 Updated by Greg Shah over 3 years ago
- Related to Feature #4854: origin affinity added
#6 Updated by Greg Shah over 3 years ago
- Related to Feature #4129: map web client users to OS accounts added
#7 Updated by Greg Shah over 3 years ago
In #4129 we are implementing features to implement a stable mapping of end users to OS accounts. This will be needed for non-web clients to have a stable persistent storage.
In #4854, we are implementing features to implement a stable mapping of browser + user to the FWD client Jetty host + port. This will be needed for web clients to have a stable persistent storage.
#9 Updated by Galya B 11 months ago
To sum it up: This FWD persistent storage should be used:
1. On non-Windows operating system for global environment storage, alternative to Windows registry, accessible through the global 4GL methods LOAD
, UNLOAD
, USE
, GET-KEY-VALUE
, PUT-KEY-VALUE
.
2. On all operating system and all types of drivers for storing BROWSE
widget enhancement preferences for in-app users (or OS users when no in-app users known). Accessible in client processes through the driver's KeyValueStorageAdapter
.
Do we expect multiple different apps to use the enhanced BROWSE
on the same host? For example several swing clients running different procedures will use the same OS account, but may need different preferences?
#11 Updated by Greg Shah 11 months ago
Galya B wrote:
What class implements the global 4GL methods accessing the Windows registry store?
To the converted code, the 4GL calls will be converted into methods in EnvironmentOps
. That code downcalls to the client through the normal RemoteObject
protocol and the EnvironmentAccessor
interface. The client side implementation is in EnvironmentDaemon
, it supports both "stanza-based" INI files and (when on Windows) the WIN32 registry. The registry access is via JNI code.
Do we expect multiple different apps to use the enhanced BROWSE on the same host?
At this time the browse does not consider an "app" level, but rather there are global, user and browse-level settings.
#13 Updated by Galya B 6 months ago
Storage for GET-KEY-VALUE
and PUT-KEY-VALUE
:
OS | LOAD BASE-KEY "INI" |
Client Type | Storage | Storage lifespan | Shared between |
Win | ❌ | Web | Server/Broker machine HKEY_CURRENT_USER |
OS reinstall | All end-users with the same OS user on the server/broker machine |
Win | ❌ | Appserver, Scheduled batch |
Server/Broker machine HKEY_CURRENT_USER |
OS reinstall | All end-users with the same OS user on the server/broker machine |
Win | ❌ | Desktop | Client machine HKEY_CURRENT_USER |
OS reinstall | All end-users with the same OS user on the client machine |
Win/Other | ✅ | Web | Server/Broker machine .ini file |
Disk change, cleanup | All web users and processes on the server/broker machine |
Win/Other | ✅ | Appserver, Scheduled batch |
Server/Broker machine .ini file |
Disk change, cleanup | All web users and processes on the server/broker machine |
Win/Other | ✅ | Desktop | Client machine .ini file |
Disk change, cleanup | All end-users on the client machine |
Other | ❌ | Web | With webClient/useLocalStorage -> localStorage |
Browser storage cleanup | Unique for the in-app user (with SSO) or same for all browser users |
Without webClient/useLocalStorage -> Server/Broker machine JVM Preferences.userRoot |
JVM reinstall?, version? | All end-users with the same OS user on the server/broker machine | |||
Other | ❌ | Appserver, Scheduled batch |
Server/Broker machine JVM Preferences.userRoot File in [userhome]/.java/.userPrefs on Linux |
JVM reinstall?, version? | All end-users with the same OS user on the server/broker machine |
Other | ❌ | Desktop | Client machine JVM Preferences.userRoot File in [userhome]/.java/.userPrefs on Linux |
JVM reinstall?, version? | All end-users with the same OS user on the client machine |
One customer is planning to use this to store a kind of "device id" that differentiates the user's system in their application. Other customers may use this to store data that they would previously have stored in an ini file or in the Windows registry.
There is some inconsistency in the level of collision between users who will share the same storage in the different cases, but at the moment I can't make something out of it.
#14 Updated by Galya B 6 months ago
The most obvious problem I see right away is with web users on Windows. All of them would share this "device id" the customer is planning to store. Anything "user" specific will be shared with all other web users, if the webClient/defaultOsUser
is configured. Even worse with .ini on any OS is how all processes, no matter what OS user they are running under, can potentially share the same file. One of the differences in FWD in comparison to 4GL is that "user" is no longer an OS user on that same machine.
#22 Updated by Greg Shah 6 months ago
Review of #4517-13:
- Shouldn't the "Shared between" column for the
Win/other
scenarios that useLOAD BASE-KEY "INI"
report "Anyone with file system access to that.ini
file."? - For OS "Other" can you please clarify the implementation idea for "Unique for the in-app user (with SSO) or same for all browser users"?
Do we want the web under linux to also store in
Preferences.userRoot
? It will be more consistent to everything else, where the storage is OS user dependent.
It is a good question. I generally like it and some customers will certainly find it very useful. However, it won't work for customers that want to store a "device-id" or who want different behavior based on which browser instance is being used.
What is the effort to implement it both ways and allow configuration of the approach to use?
I can hear the groans now. Sorry. :)
#23 Updated by Galya B 6 months ago
Greg Shah wrote:
Review of #4517-13:
Do we want the web under linux to also store in
Preferences.userRoot
? It will be more consistent to everything else, where the storage is OS user dependent.It is a good question. I generally like it and some customers will certainly find it very useful. However, it won't work for customers that want to store a "device-id" or who want different behavior based on which browser instance is being used.
What is the effort to implement it both ways and allow configuration of the approach to use?
I can hear the groans now. Sorry. :)
Not this time, because I raised the question imagining the consequences. I'm already done with the implementation as it is in the table, so adding a secondary alternative may require new methods exposed by the ClientExport
. It's doable, but then can we make localStorage
the non-default, because it's more different?
- Shouldn't the "Shared between" column for the
Win/other
scenarios that useLOAD BASE-KEY "INI"
report "Anyone with file system access to that.ini
file."?
Yes, there are other details that could have been added to that column like "Disk failure", but I decided to keep it simple. The thing is that some customers use defaultOsUser
, so all their web users will have the same access.
- For OS "Other" can you please clarify the implementation idea for "Unique for the in-app user (with SSO) or same for all browser users"?
Well, localStorage
being used for browse
configs initially, that are very personal led to the introduction of storageId
somewhere in #3931 (I'm pretty sure I mentioned it) that allows the same localStorage
to be store in independent keys for each in-app user. Directly reusing web storage as it is for registry will cause the effect described in the table.
#30 Updated by Galya B 6 months ago
- Related to Feature #7997: Encryption for client storage data / registry added
#33 Updated by Roger Borrello 3 months ago
There is a regression caused by revision 14823
to src/com/goldencode/p2j/util/EnvironmentDaemon.java
method public String use(String env)
.
The code had:
else { currentEnv = envIniMap.get(env); if (currentEnv != null) { return currentEnv.getEnvironmentName(); } // not found env = null; }
Which was expanded to extra cases:
... // stanza third currentEnv = envIniMap.get(envIni); if (currentEnv != null) { return currentEnv.getEnvironmentName(); } // fallback currentEnv = envFallbackMap.get(env); if (currentEnv != null) { return currentEnv.getEnvironmentName(); } // not found return null; ...
Because the envIni
was used to lookup the environment (instead of env
), it isn't being found. By modifying to:
... // stanza third currentEnv = envIniMap.get(env); ...
We find the environment.
In my research, I came across a regression that has been around in src/com/goldencode/p2j/util/StanzaIni.java
since revision 11266 where the environment name is being stored with .ini appended to the end. This came about when the constructor was changed from:
public StanzaIni(String env, String directory, boolean flagNew, boolean readOnly) { this(); name = env.endsWith(".ini") ? env : env + ".ini"; if (directory != null) { workingDirectory = directory; } isNew = flagNew; isReadOnly = readOnly; // environment name should not contain .ini file extension envName = env; }
to modifying
env
:public StanzaIni(String env, String directory, boolean flagNew, boolean readOnly) { contList = new LinkedList<Content>(); sectMap = new TreeMap<String, Content>(String.CASE_INSENSITIVE_ORDER); // get driver type and read only property. ThinClient tc = ThinClient.getInstance(); isChui = tc.isChui(); if (env.indexOf('.') < 0) { env = env + ".ini"; } name = env; if (directory != null) { workingDirectory = directory; } isNew = flagNew; isReadOnly = readOnly; // environment name should not contain .ini file extension envName = env; }
This can be easily fixed:
--- /tmp/brz-diff-c2sl6_b2/old/src/com/goldencode/p2j/util/StanzaIni.java +++ /home/rfb/projects/fwd/trunk_14929-bad/src/com/goldencode/p2j/util/StanzaIni.java @@ -154,6 +156,9 @@ // get driver type and read only property. ThinClient tc = ThinClient.getInstance(); isChui = tc.isChui(); + + // environment name should not contain .ini file extension + envName = env; if (env.indexOf('.') < 0) { @@ -168,9 +173,6 @@ isNew = flagNew; isReadOnly = readOnly; - - // environment name should not contain .ini file extension - envName = env; } /**
Can I create a branch here for the updates?
#35 Updated by Galya B 3 months ago
Roger Borrello wrote:
There is a regression caused by revision
14823
tosrc/com/goldencode/p2j/util/EnvironmentDaemon.java
methodpublic String use(String env)
.The code had:
[...]
Which was expanded to extra cases:
[...]Because the
envIni
was used to lookup the environment (instead ofenv
), it isn't being found. By modifying to:
[...]
We find the environment.
Roger, this is not so.
Current version of EnvironmentDaemon.use
:
public String use(String env)
{
// Empty string as environment makes the default environment the current one
if (env == null || env.isEmpty())
{
currentEnv = null;
return "";
}
// registry first
currentEnv = envRegMap.get(env.toLowerCase());
if (currentEnv != null)
{
return currentEnv.getEnvironmentName();
}
String envIni = env.indexOf('.') >= 0 ? env : env + ".ini";
// default ini second
if (defaultEnv != null && envIni.equals(defaultEnv.getEnvironmentName()))
{
currentEnv = null;
return "";
}
// stanza third
currentEnv = envIniMap.get(envIni);
if (currentEnv != null)
{
return currentEnv.getEnvironmentName();
}
// fallback
currentEnv = envFallbackMap.get(env.toLowerCase());
if (currentEnv != null)
{
return currentEnv.getEnvironmentName();
}
// not found
return null;
}
The previous version of EnvironmentDaemon.use
:
public String use(String env)
{
// Empty string as environment makes the default environment the current one
if (env == null || env.isEmpty())
{
currentEnv = null;
env = "";
}
else
{
// registry first
currentEnv = envRegMap.get(env.toLowerCase());
if (currentEnv != null)
{
return currentEnv.getEnvironmentName();
}
// stanza second
if (env.indexOf('.') < 0)
{
env = env + ".ini";
}
if (defaultEnv != null && env.equals(defaultEnv.getEnvironmentName()))
{
// switch to default environment loaded from ini
currentEnv = null;
env = "";
}
else
{
currentEnv = envIniMap.get(env);
if (currentEnv != null)
{
return currentEnv.getEnvironmentName();
}
// not found
env = null;
}
}
return env;
}
You might get confused by the original code variable being reassigned, but in actual fact it was env ini at the point of searching through the envIniMap
. Do you see this line in the original code: env = env + ".ini";
?
#36 Updated by Roger Borrello 3 months ago
Galya B wrote:
You might get confused by the original code variable being reassigned, but in actual fact it was env ini at the point of searching through the
envIniMap
. Do you see this line in the original code:env = env + ".ini";
?
All I know is what I see... No crash when opening the color palette in the customer application. I'll create a branch so I can more fully test.
With respect to branch... Galya, your #4517-31 post shows branch 4854a merged and archived, and I see branch 4517a is active. Was that just a mistake when archiving?
4854a was merged to trunk as rev. 14823 and archived.
#37 Updated by Galya B 3 months ago
Roger Borrello wrote:
Galya B wrote:
You might get confused by the original code variable being reassigned, but in actual fact it was env ini at the point of searching through the
envIniMap
. Do you see this line in the original code:env = env + ".ini";
?All I know is what I see...
Since you're seeing, then we're on the same opinion that there is no regression in r14823. Go ahead and fix the r11266 regression.
With respect to branch... Galya, your #4517-31 post shows branch 4854a merged and archived, and I see branch 4517a is active. Was that just a mistake when archiving?
There is no mistake. The relevant changes were in 4854a. 4517a is an abandoned branch I forgot to delete.
#39 Updated by Roger Borrello 3 months ago
Galya B wrote:
All I know is what I see...
Since you're seeing, then we're on the same opinion that there is no regression in r14823. Go ahead and fix the r11266 regression.
I still believe there is a regression. The env will be passed in without any .ini
on it, so you are always adding the extension for the check in the envIniMap
. In the map is CounterAct=com.goldencode.p2j.util.StanzaIni@423c5404
so it doesn't ever match.
The envIniMap
is created in the load
method:
... boolean loaded = envAcc.load(); if (loaded) { envs.put(env, envAcc); }
At this point,
envs
is the envIniMap
, and the env
in this load has not been changed to have an .ini extenstion in this method. This explains why the issue I noted related to r11266
has no bearing on the issue of the env not being found.#40 Updated by Roger Borrello 3 months ago
- % Done changed from 100 to 90
Greg Shah wrote:
Shouldn't we be testing to see if
env
already ends in.ini
and removing it if it is there before assigning it toenvName
?
No, I don't think so. The original code, before Constantin made the current change was:
public StanzaIni(String env, String directory, boolean flagNew, boolean readOnly) { this(); name = env.endsWith(".ini") ? env : env + ".ini"; if (directory != null) { workingDirectory = directory; } isNew = flagNew; isReadOnly = readOnly; // environment name should not contain .ini file extension envName = env; }
So it was intended that
name
should end in .ini
and envName
would not. I can change it to the below, but the results would be the same:public StanzaIni(String env, String directory, boolean flagNew, boolean readOnly) { contList = new LinkedList<Content>(); sectMap = new TreeMap<String, Content>(String.CASE_INSENSITIVE_ORDER); // get driver type and read only property. ThinClient tc = ThinClient.getInstance(); isChui = tc.isChui(); name = env.endsWith(".ini") ? env : env + ".ini"; if (directory != null) { workingDirectory = directory; } isNew = flagNew; isReadOnly = readOnly; // environment name should not contain .ini file extension envName = env; }
#41 Updated by Roger Borrello 3 months ago
- Status changed from Closed to Internal Test
- Assignee changed from Galya B to Roger Borrello
- % Done changed from 90 to 100
Created branch 4517b (dead-ended 4517a) and is at revision 14979. Not sure how to put this into review.
#42 Updated by Greg Shah 3 months ago
There is this comment // environment name should not contain .ini file extension
and this code name = env.endsWith(".ini") ? env : env + ".ini";
which implies that sometimes env
does have .ini
in it. In that case, it seems like we should remove it before assignment in envName = env;
.
#43 Updated by Roger Borrello 3 months ago
How about this? It's pretty explicit:
public StanzaIni(String env, String directory, boolean flagNew, boolean readOnly)
{
contList = new LinkedList<Content>();
sectMap = new TreeMap<String, Content>(String.CASE_INSENSITIVE_ORDER);
// get driver type and read only property.
ThinClient tc = ThinClient.getInstance();
isChui = tc.isChui();
if (env.endsWith(".ini"))
{
// environment name should not contain .ini file extension
envName = env.substring(0, env.length() - 4);
name = env;
}
else
{
envName = env;
name = env + ".ini";
}
if (directory != null)
{
workingDirectory = directory;
}
isNew = flagNew;
isReadOnly = readOnly;
}
#45 Updated by Roger Borrello 3 months ago
- Status changed from Internal Test to Review
Greg Shah wrote:
Yes, that seems reasonable.
Does your branch have the fix or fixes for the regression(s)?
I have both the fix for the regression (EnvironmentDaemon.java
tested in the customer application) and the fix from way back in StanzaIni.java
both in the branch.
I need to find appropriate testcases for regression testing in the new testcase model (which will have a bit of a learning curve for me).
#48 Updated by Galya B 2 months ago
envIniMap
is used in two places in EnvironmentDaemon
: when using and unloading the environment.
Roger, you've introduced a regression, because the env is stored without .ini
, but unload
looks for it with the file ext.
Also the env can end with .ini
and this is a perfectly valid use of LOAD
:
LOAD "env.ini" DIR "/some-dir/" NEW BASE-KEY "INI". USE "env.ini". UNLOAD "env.ini"
If you remove the extension in StanzaIni
EnvironmentDaemon.use
will return a wrong value and also not find it in envIniMap
.
Also, don't forget that the actual file always ends with .ini
, but it's not added, when the env already has it in the name.
Please do more in-dept testing of all cases and share your testing methods.
#49 Updated by Roger Borrello 2 months ago
Thank you for the review. I'll take a look again.
#50 Updated by Roger Borrello 2 months ago
I have been absent from this task to get the testcases_v2
standardized. In doing so, I failed to find any testcases that might have covered LOAD
/USE
/PUT-KEY-VALUE
/GET-KEY-VALUE
. Galya, what testing were you able to do for your enhancements?
My assumption that the environment stored in the map does not contain the .ini extension is based upon the comments within the code. The Progress documentation makes reference to the search logic assuming that environment has the format path\rootname.extension (where path and extension are optional). Then the search logic makes it to the initialization file with "Else search for the initialization file path\rootname.extension. If found, load it." My interpretation of that is that the environment name should be devoid of the .ini
extension when dealing with a stanza INI. So USE and UNLOAD should make sure to remove any extension when dealing with the envIniMap
in the case of stanza INI.
Am I off base?
#51 Updated by Roger Borrello 2 months ago
Revision 15002 contains updates to make the mapping key standard (no .ini
extension). The testcase I used was:
LOAD "env.ini" DIR "./data/" NEW BASE-KEY "INI". USE "env.ini". UNLOAD "env.ini". LOAD "Env.ini" DIR "./data/" BASE-KEY "INI". USE "ENV.ini". UNLOAD "env.ini". LOAD "env" DIR "./data/" BASE-KEY "INI". USE "ENV.ini". UNLOAD "env.ini".
However, there is the issue of case-sensitivity to be addressed. I would assume that each of those 3 sets should result in proper handling of env.ini
, regardless of the case. Or should this take into account the case-sensitivity of the environment?
#52 Updated by Galya B 2 months ago
Roger Borrello wrote:
Am I off base?
Yes.
Greg Shah wrote:
The 4GL features
LOAD
,UNLOAD
,USE
,GET-KEY-VALUE
,PUT-KEY-VALUE
provide a mechanism to read and write key/value data from/into either INI files (any platform) or the Registry (Windows only). We support this fully.
This task is to port GET-KEY-VALUE
, PUT-KEY-VALUE
on non-Windows clients to ClientStorage
. I've done a few fixes to the original registry logic, but it wasn't my focus. That's why I told you to reopen the original task and get yourself familiar with the state, since you're interested.
My assumption that the environment stored in the map does not contain the .ini extension is based upon the comments within the code.
The code does a check for .ini
in the name of the env, so obviously the comment you're referring to is not in sync. I haven't done any changes to StanzaIni
, so I can't help you with investigating how it came to that.
I'm just trying to help you not introduce bugs by giving you a few hints about things I've seen and tested. Since you're committed to do changes here, just do your best to test them and ask the test team if you need support.
#53 Updated by Roger Borrello 2 months ago
Maybe I'm off base, but I am just trying to be helpful. There was a change introduced in the area of INI handling when #8074 was merged, which caused a significant regression in my customer's application, so I'm more than a little "interested." No INIs would load. I found that with this one change, I can prevent the failures in the customer's application:
=== modified file 'src/com/goldencode/p2j/util/EnvironmentDaemon.java' --- old/src/com/goldencode/p2j/util/EnvironmentDaemon.java 2023-12-05 09:51:00 +0000 +++ new/src/com/goldencode/p2j/util/EnvironmentDaemon.java 2024-02-23 02:20:01 +0000 @@ -233,7 +233,8 @@ if (loaded) { + envs.put(envAcc.getEnvironmentName(), envAcc); - envs.put(env, envAcc); } return loaded;
Perhaps I should have looked at #8074 more closely and posted there, to be clearer. After looking that task over, it looks like there wasn't a lot of attention paid to this update:
Galya B wrote:
In any case, I've spent a lot of time tracking down this regression and taking it down a rabbit hole, since there wasn't any testing for INI in the testcases. When I introduced a testcase, there is other breakage since there are strange aspects to how Progress deals with
EnvironmentDaemon
: Fix for some inconsistencies in case-sensitivity. Handling several specific cases ofPUT-KEY-VALUE
deleting values / sections, as described here.
LOAD
/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.
We can carry this on in whichever task you'd like, but I'd appreciate helpful comments, specifically, why was that change necessary to env
instead of the environment name?
#55 Updated by Roger Borrello 2 months ago
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
LOAD
and attemptUSE
/UNLOAD
with matching/non-matching combinations. - utilize multiple
LOAD@s in various orders, and verify using @GET-KEY-VALUE
to 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.
#56 Updated by Greg Shah 2 months ago
Roger: Please create a new task in the base language project for this work. Copy your #4517-55 content there and keep working. You should look at the existing unit tests to understand how to structure the code. Make sure you read Writing 4GL Testcases, especially the section on "Automated/Batch Execution".
#57 Updated by Roger Borrello 2 months ago
- Related to Bug #8353: Fully support stanza INI LOAD/USE/UNLOAD scenarios added
#58 Updated by Greg Shah about 1 month ago
- Status changed from Review to Closed