stevedlawrence commented on code in PR #800:
URL: https://github.com/apache/daffodil/pull/800#discussion_r890291203


##########
daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala:
##########
@@ -397,6 +407,10 @@ class CLIConf(arguments: Array[String]) extends 
scallop.ScallopConf(arguments) {
     descr("List or execute TDML tests")
     helpWidth(width)
 
+    val implementation = opt[TDMLImplementation](short = 'I', argName = 
"implementation",
+      descr = "Implementation to run TDML tests. Choose one of %s. Defaults to 
%s."
+        .format(TDMLImplementation.allValues.mkString(", "), 
TDMLImplementation.allValues.head.toString),

Review Comment:
   Thoughts on using `TDMLImplementation.Daffodil` as the default? That way if 
the order ever changes and thus `allValues.head` changes, we'll still default 
to runtime1? 



##########
daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala:
##########
@@ -397,6 +407,10 @@ class CLIConf(arguments: Array[String]) extends 
scallop.ScallopConf(arguments) {
     descr("List or execute TDML tests")
     helpWidth(width)
 
+    val implementation = opt[TDMLImplementation](short = 'I', argName = 
"implementation",
+      descr = "Implementation to run TDML tests. Choose one of %s. Defaults to 
%s."
+        .format(TDMLImplementation.allValues.mkString(", "), 
TDMLImplementation.allValues.head.toString),

Review Comment:
   Another thing to consider, the "ibm" implementation probably won't work with 
the Daffodil CLI by default. IBM needs a handful of classpath changes in order 
for this to work correctly. I'm not sure it's worth worrying about, it might be 
nice to allow it and then someone could eventually figure out exactly how the 
classpath needs to changed. But just a consideration.



##########
daffodil-runtime2/src/main/resources/org/apache/daffodil/runtime2/c/libruntime/parsers.c:
##########
@@ -507,26 +507,25 @@ parse_le_uint8(uint8_t *number, size_t num_bits, PState 
*pstate)
     *number = (uint8_t)integer;
 }
 
-// Skip fill bytes until end bitPos0b is reached
+// Parse fill bits until end bitPos0b is reached
 
 void
-parse_fill_bytes(size_t end_bitPos0b, PState *pstate)
+parse_fill_bits(size_t end_bitPos0b, PState *pstate)
 {

Review Comment:
   In the future, I'd prefer we split up unrelated changes into separate PRs. I 
don't think the TDML implementation and the fill bits are really that related, 
makes code review easier when everything is about one thing.



##########
daffodil-runtime2/src/main/resources/org/apache/daffodil/runtime2/c/libruntime/unparsers.c:
##########
@@ -401,27 +401,24 @@ unparse_le_uint8(uint8_t number, size_t num_bits, UState 
*ustate)
     unparse_endian_uint64(LITTLE_ENDIAN_DATA, number, num_bits, ustate);
 }
 
-// Add fill bytes until end bitPos0b is reached
+// Unparse fill bits until end bitPos0b is reached
 
 void
-unparse_fill_bytes(size_t end_bitPos0b, const uint8_t fill_byte, UState 
*ustate)
+unparse_fill_bits(size_t end_bitPos0b, const uint8_t fill_byte, UState *ustate)
 {
-    union
-    {
-        uint8_t bytes[1];
-    } buffer;
-    buffer.bytes[0] = fill_byte;
+    assert(ustate->bitPos0b <= end_bitPos0b);
 
-    // Update our last successful write position only if this loop
-    // finishes without any errors
-    size_t current_bitPos0b = ustate->bitPos0b;
-    while (current_bitPos0b < end_bitPos0b)
+    size_t fill_bits = end_bitPos0b - ustate->bitPos0b;
+    while (fill_bits)
     {
-        write_bits(buffer.bytes, BYTE_WIDTH, ustate);
+        size_t num_bits = (fill_bits >= BYTE_WIDTH) ? BYTE_WIDTH : fill_bits;
+        write_bits(&fill_byte, num_bits, ustate);

Review Comment:
   Does this do fill bits correctly? The spec says
   
   > If bit K ... of a data stream byte is unspecified, its value is taken from 
bit K of the dfdl:fillByte property value. 
    
   So say we have already unparsed a single `0` bit and we need to fill the 
remaining 7 bits to fill out the byte. Also assume the the fill byte is `0xF0.` 
I *think* the way you have it, it will unparse to `0111 1000`, but it should 
unparse to `0111 0000`, right?
   
   That said, I think runtime1 doesn't implement this correctly either. In 
fact, I think there's a serious bug? Say we have this schema that describes the 
above scenario:
   
   ```xml
   <schema
     xmlns="http://www.w3.org/2001/XMLSchema";
     xmlns:xs="http://www.w3.org/2001/XMLSchema";
     xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/";>
   
     <include 
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd" />
   
     <annotation>
       <appinfo source="http://www.ogf.org/dfdl/";>
         <dfdl:format xmlns="" ref="GeneralFormat"
           representation="binary"
           lengthKind="explicit"
           lengthUnits="bits"
           fillByte="%#xF0;" />
       </appinfo>
     </annotation>
   
     <element name="container" dfdl:length="8">
       <complexType>
         <sequence>
           <element name="bit" type="xs:int" dfdl:length="1" />
         </sequence>
       </complexType>
     </element>
   
   </schema>
   ```
   
   And this infoset to unparse:
   ```xml
   <container>
     <bit>0</bit>
   </container>
   ```
   
   Runtime1 currently unparses to `0011 1111`. I have no idea how it's getting 
that result, but it seems very wrong to me. Maybe I'm just not understanding 
fill byte correctly?



##########
daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd:
##########
@@ -587,15 +587,23 @@
         <xs:restriction base="dfdlx:ParseUnparsePolicyEnum" />
       </xs:simpleType>
       <xs:simpleType>
-        <xs:restriction base="xs:string">
+        <xs:restriction base="xs:token">
           <xs:enumeration value="fromRoot" />
         </xs:restriction>
       </xs:simpleType>
     </xs:union>
   </xs:simpleType>
 
+  <xs:simpleType name="TunableTDMLImplementation">

Review Comment:
   Do we want to call this something other than "Tunable...". TDML 
Implemementation isn't really a tunable anymore.



##########
daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala:
##########
@@ -397,6 +407,10 @@ class CLIConf(arguments: Array[String]) extends 
scallop.ScallopConf(arguments) {
     descr("List or execute TDML tests")
     helpWidth(width)
 
+    val implementation = opt[TDMLImplementation](short = 'I', argName = 
"implementation",
+      descr = "Implementation to run TDML tests. Choose one of %s. Defaults to 
%s."
+        .format(TDMLImplementation.allValues.mkString(", "), 
TDMLImplementation.allValues.head.toString),
+      default = TDMLImplementation.optionStringToEnum("I", 
sys.env.getOrElse("TDML_IMPLEMENTATION", "")))

Review Comment:
   I'm not sure I understand this. If TDML_IMPLEMENATION is defined we set the 
default to that, if we don't we set it to empty string? Should it be something 
like this instead:
   
   ```scala
   default = {
     val implStr = sys.env.getOrElse("TDML_IMPLEMENTATION", 
TDMLImplementation.Daffodil.toString)
     TDMLImplementation.optionStringToEnum("I", implStr)
   }
   ```
   
   Also, what happens if TDML_IMPLEMENTATION isn't valid? There's not really a 
default anymore so I'm not sure what would happen.



##########
daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml:
##########
@@ -158,4 +187,78 @@
     </tdml:validationErrors>
   </tdml:parserTestCase>
 
+  <tdml:parserTestCase
+    config="config-runtime2"
+    model="ex_nums.dfdl.xsd"
+    name="runtime2_error_on"
+    validation="on">
+    <tdml:document>
+      <tdml:documentPart type="file">ex_nums.error.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ex_nums.error.dat.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:validationErrors>
+      <tdml:error>value</tdml:error>
+      <tdml:error>boolean_false</tdml:error>
+      <tdml:error>does not match</tdml:error>
+    </tdml:validationErrors>
+  </tdml:parserTestCase>
+
+  <!--
+      In runtime2, unparse always writes non-fixed values with validation
+      diagnostics (doesn't even have a validation option)
+
+      c/daffodil unparse -o c/ex_nums.error.dat ex_nums.error.dat.xml
+  -->
+
+  <tdml:unparserTestCase
+    config="config-runtime2"
+    model="ex_nums.dfdl.xsd"
+    name="runtime2_error_unparse">
+    <tdml:infoset>

Review Comment:
   Is it worth adding `implementation="daffodilC"` to some of these so it's 
clear that they are testing runtime2 specific behavior?



##########
daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd:
##########
@@ -502,11 +502,11 @@
             </xs:documentation>
           </xs:annotation>
         </xs:element>
-        <xs:element name="tdmlImplementation" type="xs:string" 
default="daffodil" minOccurs="0">
+        <xs:element name="tdmlImplementation" 
type="daf:TunableTDMLImplementation" default="daffodil" minOccurs="0">

Review Comment:
   Should we remove this tunable? It's not backwards compatible, but I suspect 
this doesn't have many users.



##########
daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml:
##########
@@ -38,21 +38,25 @@
 
   <tdml:defineConfig name="config-runtime2">
     <daf:tunables>
-      <daf:tdmlImplementation>daffodil-runtime2</daf:tdmlImplementation>
+      <daf:tdmlImplementation>daffodilC</daf:tdmlImplementation>
     </daf:tunables>
   </tdml:defineConfig>

Review Comment:
   Should we remove/deprecate this way to select the implementation? 



##########
daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/RunnerFactory.scala:
##########
@@ -37,28 +39,48 @@ import org.apache.daffodil.util.Misc
  */
 object Runner {
   def apply(dir: String, file: String,
+    useTDMLImplementation: TDMLImplementation = 
TDMLImplementation.allValues.head,

Review Comment:
   Mentioned previously, but I'd consider not using `allValues.head` in case 
order ever changes. We probably want to be explicit about what the default is.
   
   I also wonder if it want `useTDMLImplementation` to be an `Option` that 
defaults to `None`? And then the TDMLRunner can check if it's defined, abd if 
it's not check TDML_IMPEMENATION, and if that's not defined then default to 
runtime1? That way you could do something like
   
   ```
   TDML_IMPLEMENTATION="daffodilC" sbt test
   ```
   
   That would run all sbt tests that don't explicitly specify an implementation 
to use  runtime2. I'm not sure `sbt test` would be all that helpful due to the 
differences in functionality, but doing something like `sbt testOnly 
some.subset.of.tests` might be useful.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to