From 02e5cc471b8fd2d07cece8d8539033fdf5479393 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Babski?= <rbabski@n7space.com>
Date: Tue, 11 Jun 2024 22:05:10 +0100
Subject: [PATCH 1/3] Asn1ToPromelaTranslator: added support for string
 literals for constants

---
 .../visitors/valueassignmentvisitor.cpp       | 78 +++++++++++++++++--
 .../visitors/valueassignmentvisitor.h         |  3 +
 2 files changed, 74 insertions(+), 7 deletions(-)

diff --git a/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.cpp b/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.cpp
index 3b45931cd2..a9ba1b09d6 100644
--- a/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.cpp
+++ b/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.cpp
@@ -22,12 +22,15 @@
 #include "sequencecomponentvaluevisitor.h"
 #include "sizeconstraintvisitor.h"
 
+#include <QDebug>
 #include <asn1library/asn1/choicevalue.h>
 #include <asn1library/asn1/multiplevalue.h>
 #include <asn1library/asn1/namedvalue.h>
 #include <asn1library/asn1/singlevalue.h>
 #include <asn1library/asn1/types/choice.h>
+#include <asn1library/asn1/types/ia5string.h>
 #include <asn1library/asn1/types/integer.h>
+#include <asn1library/asn1/types/octetstring.h>
 #include <asn1library/asn1/types/sequence.h>
 #include <asn1library/asn1/types/sequenceof.h>
 #include <asn1library/asn1/types/userdefinedtype.h>
@@ -41,7 +44,9 @@ using Asn1Acn::ChoiceValue;
 using Asn1Acn::IntegerValue;
 using Asn1Acn::MultipleValue;
 using Asn1Acn::NamedValue;
+using Asn1Acn::OctetStringValue;
 using Asn1Acn::SingleValue;
+using Asn1Acn::StringValue;
 using Asn1Acn::Value;
 using Asn1Acn::ValuePtr;
 using Asn1Acn::Types::BitString;
@@ -99,31 +104,70 @@ void ValueAssignmentVisitor::visit(const Boolean &type)
 void ValueAssignmentVisitor::visit(const Null &type)
 {
     Q_UNUSED(type);
-    throw ConverterException("Value generation is not implemented for NULL datatype");
+    throw ConverterException(QString("Value assignment is not implemented for %1, NULL datatype").arg(m_typeName));
 }
 
 void ValueAssignmentVisitor::visit(const BitString &type)
 {
     Q_UNUSED(type);
-    throw ConverterException("Value generation is not implemented for BIT STRING datatype");
+    throw ConverterException(
+            QString("Value assignment is not implemented for %1, BIT STRING datatype").arg(m_typeName));
 }
 
 void ValueAssignmentVisitor::visit(const OctetString &type)
 {
-    Q_UNUSED(type);
-    throw ConverterException("Value generation is not implemented for OCTET STRING datatype");
+    if (m_value->typeEnum() != Value::SINGLE_VALUE) {
+        throw ConverterException("Invalid value for OCTET STRING datatype");
+    }
+
+    SizeConstraintVisitor<OctetStringValue> sizeConstraintVisitor;
+    type.constraints().accept(sizeConstraintVisitor);
 }
 
 void ValueAssignmentVisitor::visit(const IA5String &type)
 {
-    Q_UNUSED(type);
-    throw ConverterException("Value generation is not implemented for IA5String datatype");
+    if (m_value->typeEnum() != Value::SINGLE_VALUE) {
+        throw ConverterException("Invalid value for OCTET STRING datatype");
+    }
+
+    SizeConstraintVisitor<StringValue> sizeConstraintVisitor;
+    type.constraints().accept(sizeConstraintVisitor);
+
+    const SingleValue *singleValue = dynamic_cast<const SingleValue *>(m_value);
+    QString value = singleValue->value();
+    // remove first and last character, it is quotation mark
+    value.remove(0, 1);
+    value.remove(value.length() - 1, 1);
+    QVector<QChar> bytes = getBytesFromString(value);
+
+    size_t index = 0;
+
+    for (const QChar b : bytes) {
+        VariableRef target = m_target;
+        target.appendElement("data", std::make_unique<Expression>(promela::model::Constant(index)));
+        m_sequence.appendElement(Assignment(target, Expression(promela::model::Constant(b.unicode()))));
+        ++index;
+    }
+    while (index < sizeConstraintVisitor.getMaxSize()) {
+        VariableRef target = m_target;
+        target.appendElement("data", std::make_unique<Expression>(promela::model::Constant(index)));
+        m_sequence.appendElement(Assignment(target, Expression(promela::model::Constant(0))));
+        ++index;
+    }
+
+    if (sizeConstraintVisitor.getMinSize() != sizeConstraintVisitor.getMaxSize()) {
+        VariableRef target = m_target;
+        target.appendElement("length");
+        int stringSize = bytes.size();
+        m_sequence.appendElement(Assignment(target, Expression(promela::model::Constant(stringSize))));
+    }
 }
 
 void ValueAssignmentVisitor::visit(const NumericString &type)
 {
     Q_UNUSED(type);
-    throw ConverterException("Value generation is not implemented for NUMERIC STRING datatype");
+    throw ConverterException(
+            QString("Value generation is not implemented for %1, NUMERIC STRING datatype").arg(m_typeName));
 }
 
 void ValueAssignmentVisitor::visit(const Enumerated &type)
@@ -264,4 +308,24 @@ void ValueAssignmentVisitor::visit(const UserdefinedType &type)
 
     type.type()->accept(visitor);
 }
+
+QVector<QChar> ValueAssignmentVisitor::getBytesFromString(const QString &str)
+{
+    QVector<QChar> result;
+
+    bool escape = false;
+    for (const QChar c : str) {
+        if (c == '\\') {
+            if (escape) {
+                result.append(c);
+                escape = false;
+            } else {
+                escape = true;
+            }
+        } else {
+            result.append(c);
+        }
+    }
+    return result;
+}
 }
diff --git a/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.h b/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.h
index fedab1e97e..d72933f33a 100644
--- a/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.h
+++ b/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.h
@@ -128,6 +128,9 @@ public:
      */
     void visit(const Asn1Acn::Types::UserdefinedType &type) override;
 
+private:
+    QVector<QChar> getBytesFromString(const QString &str);
+
 private:
     Asn1Acn::Value *m_value;
     model::Sequence &m_sequence;
-- 
GitLab


From f3db0ac3a0bce9a3ae38fbd720eacc81ec311a25 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Babski?= <rbabski@n7space.com>
Date: Wed, 12 Jun 2024 09:28:50 +0100
Subject: [PATCH 2/3] Asn1ToPromelaTranslator, ASN.1 constants for OCTET
 STRING, IA5String

---
 .../visitors/valueassignmentvisitor.cpp       | 43 ++++++++++++-------
 1 file changed, 27 insertions(+), 16 deletions(-)

diff --git a/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.cpp b/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.cpp
index a9ba1b09d6..78d0a763aa 100644
--- a/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.cpp
+++ b/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.cpp
@@ -104,14 +104,13 @@ void ValueAssignmentVisitor::visit(const Boolean &type)
 void ValueAssignmentVisitor::visit(const Null &type)
 {
     Q_UNUSED(type);
-    throw ConverterException(QString("Value assignment is not implemented for %1, NULL datatype").arg(m_typeName));
+    throw ConverterException(QString("ASN.1 constants not supported for %1, NULL datatype").arg(m_typeName));
 }
 
 void ValueAssignmentVisitor::visit(const BitString &type)
 {
     Q_UNUSED(type);
-    throw ConverterException(
-            QString("Value assignment is not implemented for %1, BIT STRING datatype").arg(m_typeName));
+    throw ConverterException(QString("ASN.1 constants not supported for %1, BIT STRING datatype").arg(m_typeName));
 }
 
 void ValueAssignmentVisitor::visit(const OctetString &type)
@@ -122,12 +121,32 @@ void ValueAssignmentVisitor::visit(const OctetString &type)
 
     SizeConstraintVisitor<OctetStringValue> sizeConstraintVisitor;
     type.constraints().accept(sizeConstraintVisitor);
+
+    const SingleValue *singleValue = dynamic_cast<const SingleValue *>(m_value);
+    QString value = singleValue->value();
+    QVector<QChar> bytes = getBytesFromString(value);
+
+    size_t index = 0;
+
+    for (const QChar b : bytes) {
+        VariableRef target = m_target;
+        target.appendElement("data", std::make_unique<Expression>(promela::model::Constant(index)));
+        m_sequence.appendElement(Assignment(target, Expression(promela::model::Constant(b.unicode()))));
+        ++index;
+    }
+
+    if (sizeConstraintVisitor.getMinSize() != sizeConstraintVisitor.getMaxSize()) {
+        VariableRef target = m_target;
+        target.appendElement("length");
+        int stringSize = bytes.size();
+        m_sequence.appendElement(Assignment(target, Expression(promela::model::Constant(stringSize))));
+    }
 }
 
 void ValueAssignmentVisitor::visit(const IA5String &type)
 {
     if (m_value->typeEnum() != Value::SINGLE_VALUE) {
-        throw ConverterException("Invalid value for OCTET STRING datatype");
+        throw ConverterException("Invalid value for IA5String datatype");
     }
 
     SizeConstraintVisitor<StringValue> sizeConstraintVisitor;
@@ -135,25 +154,18 @@ void ValueAssignmentVisitor::visit(const IA5String &type)
 
     const SingleValue *singleValue = dynamic_cast<const SingleValue *>(m_value);
     QString value = singleValue->value();
-    // remove first and last character, it is quotation mark
-    value.remove(0, 1);
-    value.remove(value.length() - 1, 1);
     QVector<QChar> bytes = getBytesFromString(value);
 
     size_t index = 0;
 
     for (const QChar b : bytes) {
         VariableRef target = m_target;
+        // the character is converted to numeric value
+        // promela has character literal, but it is not supported in promela model
         target.appendElement("data", std::make_unique<Expression>(promela::model::Constant(index)));
         m_sequence.appendElement(Assignment(target, Expression(promela::model::Constant(b.unicode()))));
         ++index;
     }
-    while (index < sizeConstraintVisitor.getMaxSize()) {
-        VariableRef target = m_target;
-        target.appendElement("data", std::make_unique<Expression>(promela::model::Constant(index)));
-        m_sequence.appendElement(Assignment(target, Expression(promela::model::Constant(0))));
-        ++index;
-    }
 
     if (sizeConstraintVisitor.getMinSize() != sizeConstraintVisitor.getMaxSize()) {
         VariableRef target = m_target;
@@ -166,8 +178,7 @@ void ValueAssignmentVisitor::visit(const IA5String &type)
 void ValueAssignmentVisitor::visit(const NumericString &type)
 {
     Q_UNUSED(type);
-    throw ConverterException(
-            QString("Value generation is not implemented for %1, NUMERIC STRING datatype").arg(m_typeName));
+    throw ConverterException(QString("ASN.1 constants not supported for %1, NUMERIC STRING datatype").arg(m_typeName));
 }
 
 void ValueAssignmentVisitor::visit(const Enumerated &type)
@@ -282,7 +293,7 @@ void ValueAssignmentVisitor::visit(const Real &type)
 void ValueAssignmentVisitor::visit(const LabelType &type)
 {
     Q_UNUSED(type);
-    throw ConverterException("Value generation is not implemented for LabelType");
+    throw ConverterException(QString("ASN.1 constants not supported for %1, LabelType datatype").arg(m_typeName));
 }
 
 void ValueAssignmentVisitor::visit(const Integer &type)
-- 
GitLab


From a0d5093fe0f3263e89f26bf1db478d5d5addf20b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Babski?= <rbabski@n7space.com>
Date: Wed, 12 Jun 2024 10:38:28 +0100
Subject: [PATCH 3/3] Asn1ToPromelaTranslator: Updated tests and fixes in
 support for string constants

---
 .../visitors/valueassignmentvisitor.cpp       |  39 ++++-
 .../visitors/valueassignmentvisitor.h         |   2 +
 .../tst_asn1topromelatranslator_values.cpp    | 142 +++++++++++++++++-
 .../tst_asn1topromelatranslator_values.h      |   5 +
 4 files changed, 183 insertions(+), 5 deletions(-)

diff --git a/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.cpp b/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.cpp
index 78d0a763aa..564a65f102 100644
--- a/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.cpp
+++ b/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.cpp
@@ -124,14 +124,14 @@ void ValueAssignmentVisitor::visit(const OctetString &type)
 
     const SingleValue *singleValue = dynamic_cast<const SingleValue *>(m_value);
     QString value = singleValue->value();
-    QVector<QChar> bytes = getBytesFromString(value);
+    QVector<unsigned char> bytes = getBytesFromOctetString(value);
 
     size_t index = 0;
 
-    for (const QChar b : bytes) {
+    for (const unsigned char b : bytes) {
         VariableRef target = m_target;
         target.appendElement("data", std::make_unique<Expression>(promela::model::Constant(index)));
-        m_sequence.appendElement(Assignment(target, Expression(promela::model::Constant(b.unicode()))));
+        m_sequence.appendElement(Assignment(target, Expression(promela::model::Constant(b))));
         ++index;
     }
 
@@ -339,4 +339,37 @@ QVector<QChar> ValueAssignmentVisitor::getBytesFromString(const QString &str)
     }
     return result;
 }
+
+QVector<unsigned char> ValueAssignmentVisitor::getBytesFromOctetString(const QString &str)
+{
+    QVector<unsigned char> result;
+
+    int high_nibble = 0;
+    int low_nibble = 0;
+
+    auto iter = str.begin();
+    while (iter != str.end()) {
+        high_nibble = hexdigit(iter->unicode());
+        ++iter;
+        low_nibble = hexdigit(iter->unicode());
+        ++iter;
+
+        result.append((high_nibble << 4) | low_nibble);
+    }
+    return result;
+}
+
+int ValueAssignmentVisitor::hexdigit(int c)
+{
+    if (isdigit(c)) {
+        return c - '0';
+    }
+    if (c >= 'A' && c <= 'F') {
+        return 10 + c - 'A';
+    }
+    if (c >= 'a' && c <= 'f') {
+        return 10 + c - 'a';
+    }
+    return 0;
+}
 }
diff --git a/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.h b/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.h
index d72933f33a..4abc3ca1cd 100644
--- a/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.h
+++ b/src/libs/promela/Asn1ToPromelaTranslator/visitors/valueassignmentvisitor.h
@@ -130,6 +130,8 @@ public:
 
 private:
     QVector<QChar> getBytesFromString(const QString &str);
+    QVector<unsigned char> getBytesFromOctetString(const QString &str);
+    int hexdigit(int c);
 
 private:
     Asn1Acn::Value *m_value;
diff --git a/tests/unittests/promela/asn1topromelatranslator/tst_asn1topromelatranslator_values.cpp b/tests/unittests/promela/asn1topromelatranslator/tst_asn1topromelatranslator_values.cpp
index e4ea0bd270..2e3d8924a1 100644
--- a/tests/unittests/promela/asn1topromelatranslator/tst_asn1topromelatranslator_values.cpp
+++ b/tests/unittests/promela/asn1topromelatranslator/tst_asn1topromelatranslator_values.cpp
@@ -30,7 +30,9 @@
 #include <asn1library/asn1/types/boolean.h>
 #include <asn1library/asn1/types/choice.h>
 #include <asn1library/asn1/types/enumerated.h>
+#include <asn1library/asn1/types/ia5string.h>
 #include <asn1library/asn1/types/integer.h>
+#include <asn1library/asn1/types/octetstring.h>
 #include <asn1library/asn1/types/real.h>
 #include <asn1library/asn1/types/sequence.h>
 #include <asn1library/asn1/types/sequenceof.h>
@@ -58,7 +60,9 @@ using Asn1Acn::Types::Choice;
 using Asn1Acn::Types::ChoiceAlternative;
 using Asn1Acn::Types::Enumerated;
 using Asn1Acn::Types::EnumeratedItem;
+using Asn1Acn::Types::IA5String;
 using Asn1Acn::Types::Integer;
+using Asn1Acn::Types::OctetString;
 using Asn1Acn::Types::Real;
 using Asn1Acn::Types::Sequence;
 using Asn1Acn::Types::SequenceOf;
@@ -74,9 +78,9 @@ using promela::model::VariableRef;
 using promela::translator::Asn1NodeVisitor;
 
 namespace tmc::test {
-void tst_Asn1ToPromelaTranslator_Values::initTestCase() {}
+void tst_Asn1ToPromelaTranslator_Values::initTestCase() { }
 
-void tst_Asn1ToPromelaTranslator_Values::cleanupTestCase() {}
+void tst_Asn1ToPromelaTranslator_Values::cleanupTestCase() { }
 
 void tst_Asn1ToPromelaTranslator_Values::testSequence() const
 {
@@ -575,6 +579,124 @@ void tst_Asn1ToPromelaTranslator_Values::testChoice() const
     QCOMPARE(std::get<Constant>(inlineCall->getArguments().last()).getValue(), 3);
 }
 
+void tst_Asn1ToPromelaTranslator_Values::testOctetString() const
+{
+    auto asn1Model = createModel();
+
+    {
+        auto stringType = std::make_unique<OctetString>();
+        Asn1Acn::Range<int64_t> range(0, 4);
+        auto rangeConstraint = std::make_unique<Asn1Acn::Constraints::RangeConstraint<Asn1Acn::IntegerValue>>(range);
+        auto sizeConstraint = std::make_unique<Asn1Acn::Constraints::SizeConstraint<Asn1Acn::OctetStringValue>>(
+                std::move(rangeConstraint));
+        stringType->constraints().append(std::move(sizeConstraint));
+
+        auto myIntegerAssignment = std::make_unique<TypeAssignment>(
+                QStringLiteral("MyString"), QStringLiteral("MyString"), SourceLocation(), stringType->clone());
+
+        asn1Model->addType(std::move(myIntegerAssignment));
+
+        auto stringReference = std::make_unique<UserdefinedType>("MyString", "myModule");
+        stringReference->setType(stringType->clone());
+
+        auto myValueAssignment = std::make_unique<ValueAssignment>(QStringLiteral("myValue"), SourceLocation(),
+                std::move(stringReference), std::make_unique<SingleValue>("0011aabb"));
+        asn1Model->addValue(std::move(myValueAssignment));
+    }
+
+    PromelaModel promelaModel;
+    Asn1NodeVisitor visitor(promelaModel, true);
+    visitor.visit(*asn1Model);
+
+    QCOMPARE(promelaModel.getDeclarations().size(), 1);
+
+    QCOMPARE(promelaModel.getDeclarations().at(0).getName(), "myValue");
+    QVERIFY(promelaModel.getDeclarations().at(0).getType().isUtypeReference());
+    QCOMPARE(promelaModel.getDeclarations().at(0).getType().getUtypeReference().getName(), "MyString");
+
+    QCOMPARE(promelaModel.getInlineDefs().size(), 3);
+    {
+        const InlineDef *inlineDef = findInline(promelaModel.getInlineDefs(), "myValue_init");
+        QVERIFY(inlineDef != nullptr);
+        QCOMPARE(inlineDef->getArguments().size(), 0);
+        QCOMPARE(inlineDef->getSequence().getContent().size(), 5);
+
+        verifyArrayAssignment(findProctypeElement<Assignment>(inlineDef->getSequence(), 0), "myValue", 0, 0x0);
+        verifyArrayAssignment(findProctypeElement<Assignment>(inlineDef->getSequence(), 1), "myValue", 1, 0x11);
+        verifyArrayAssignment(findProctypeElement<Assignment>(inlineDef->getSequence(), 2), "myValue", 2, 0xaa);
+        verifyArrayAssignment(findProctypeElement<Assignment>(inlineDef->getSequence(), 3), "myValue", 3, 0xbb);
+
+        const Assignment *lengthAssignment = findProctypeElement<Assignment>(inlineDef->getSequence(), 4);
+        QVERIFY(lengthAssignment);
+        QCOMPARE(lengthAssignment->getVariableRef().getElements().size(), 2);
+        QCOMPARE(lengthAssignment->getVariableRef().getElements().front().m_name, "myValue");
+        QVERIFY(!lengthAssignment->getVariableRef().getElements().front().m_index);
+        QCOMPARE(lengthAssignment->getVariableRef().getElements().back().m_name, "length");
+        QVERIFY(!lengthAssignment->getVariableRef().getElements().back().m_index);
+        QVERIFY(std::holds_alternative<Constant>(lengthAssignment->getExpression().getContent()));
+        QCOMPARE(std::get<Constant>(lengthAssignment->getExpression().getContent()).getValue(), 4);
+    }
+}
+
+void tst_Asn1ToPromelaTranslator_Values::testIA5String() const
+{
+    auto asn1Model = createModel();
+
+    {
+        auto stringType = std::make_unique<IA5String>();
+        Asn1Acn::Range<int64_t> range(0, 4);
+        auto rangeConstraint = std::make_unique<Asn1Acn::Constraints::RangeConstraint<Asn1Acn::IntegerValue>>(range);
+        auto sizeConstraint = std::make_unique<Asn1Acn::Constraints::SizeConstraint<Asn1Acn::StringValue>>(
+                std::move(rangeConstraint));
+        stringType->constraints().append(std::move(sizeConstraint));
+
+        auto myIntegerAssignment = std::make_unique<TypeAssignment>(
+                QStringLiteral("MyString"), QStringLiteral("MyString"), SourceLocation(), stringType->clone());
+
+        asn1Model->addType(std::move(myIntegerAssignment));
+
+        auto stringReference = std::make_unique<UserdefinedType>("MyString", "myModule");
+        stringReference->setType(stringType->clone());
+
+        auto myValueAssignment = std::make_unique<ValueAssignment>(QStringLiteral("myValue"), SourceLocation(),
+                std::move(stringReference), std::make_unique<SingleValue>("test"));
+        asn1Model->addValue(std::move(myValueAssignment));
+    }
+
+    PromelaModel promelaModel;
+    Asn1NodeVisitor visitor(promelaModel, true);
+    visitor.visit(*asn1Model);
+
+    QCOMPARE(promelaModel.getDeclarations().size(), 1);
+
+    QCOMPARE(promelaModel.getDeclarations().at(0).getName(), "myValue");
+    QVERIFY(promelaModel.getDeclarations().at(0).getType().isUtypeReference());
+    QCOMPARE(promelaModel.getDeclarations().at(0).getType().getUtypeReference().getName(), "MyString");
+
+    QCOMPARE(promelaModel.getInlineDefs().size(), 3);
+    {
+        const InlineDef *inlineDef = findInline(promelaModel.getInlineDefs(), "myValue_init");
+        QVERIFY(inlineDef != nullptr);
+        QCOMPARE(inlineDef->getArguments().size(), 0);
+        QCOMPARE(inlineDef->getSequence().getContent().size(), 5);
+
+        verifyArrayAssignment(findProctypeElement<Assignment>(inlineDef->getSequence(), 0), "myValue", 0, 't');
+        verifyArrayAssignment(findProctypeElement<Assignment>(inlineDef->getSequence(), 1), "myValue", 1, 'e');
+        verifyArrayAssignment(findProctypeElement<Assignment>(inlineDef->getSequence(), 2), "myValue", 2, 's');
+        verifyArrayAssignment(findProctypeElement<Assignment>(inlineDef->getSequence(), 3), "myValue", 3, 't');
+
+        const Assignment *lengthAssignment = findProctypeElement<Assignment>(inlineDef->getSequence(), 4);
+        QVERIFY(lengthAssignment);
+        QCOMPARE(lengthAssignment->getVariableRef().getElements().size(), 2);
+        QCOMPARE(lengthAssignment->getVariableRef().getElements().front().m_name, "myValue");
+        QVERIFY(!lengthAssignment->getVariableRef().getElements().front().m_index);
+        QCOMPARE(lengthAssignment->getVariableRef().getElements().back().m_name, "length");
+        QVERIFY(!lengthAssignment->getVariableRef().getElements().back().m_index);
+        QVERIFY(std::holds_alternative<Constant>(lengthAssignment->getExpression().getContent()));
+        QCOMPARE(std::get<Constant>(lengthAssignment->getExpression().getContent()).getValue(), 4);
+    }
+}
+
 std::unique_ptr<Definitions> tst_Asn1ToPromelaTranslator_Values::createModel() const
 {
     return std::make_unique<Definitions>("myModule", SourceLocation());
@@ -607,4 +729,20 @@ const T *tst_Asn1ToPromelaTranslator_Values::findProctypeElement(
     return nullptr;
 }
 
+void tst_Asn1ToPromelaTranslator_Values::verifyArrayAssignment(const ::promela::model::Assignment *assignment,
+        const QString &target, int32_t index, int32_t expectedValue) const
+{
+    QVERIFY(assignment);
+    QCOMPARE(assignment->getVariableRef().getElements().size(), 2);
+    QCOMPARE(assignment->getVariableRef().getElements().front().m_name, target);
+    QVERIFY(!assignment->getVariableRef().getElements().front().m_index);
+    QCOMPARE(assignment->getVariableRef().getElements().back().m_name, "data");
+    QVERIFY(assignment->getVariableRef().getElements().back().m_index);
+    QVERIFY(std::holds_alternative<Constant>(assignment->getVariableRef().getElements().back().m_index->getContent()));
+    QCOMPARE(std::get<Constant>(assignment->getVariableRef().getElements().back().m_index->getContent()).getValue(),
+            index);
+    QVERIFY(std::holds_alternative<Constant>(assignment->getExpression().getContent()));
+    QCOMPARE(std::get<Constant>(assignment->getExpression().getContent()).getValue(), expectedValue);
+}
+
 }
diff --git a/tests/unittests/promela/asn1topromelatranslator/tst_asn1topromelatranslator_values.h b/tests/unittests/promela/asn1topromelatranslator/tst_asn1topromelatranslator_values.h
index cb54c893e9..651b14c155 100644
--- a/tests/unittests/promela/asn1topromelatranslator/tst_asn1topromelatranslator_values.h
+++ b/tests/unittests/promela/asn1topromelatranslator/tst_asn1topromelatranslator_values.h
@@ -45,6 +45,8 @@ private Q_SLOTS:
     void testBoolean() const;
     void testSequenceOf() const;
     void testChoice() const;
+    void testOctetString() const;
+    void testIA5String() const;
 
 private:
     std::unique_ptr<Definitions> createModel() const;
@@ -53,5 +55,8 @@ private:
 
     template<typename T>
     const T *findProctypeElement(const ::promela::model::Sequence &sequence, size_t index) const;
+
+    void verifyArrayAssignment(const ::promela::model::Assignment *assignment, const QString &target, int32_t index,
+            int32_t expectedValue) const;
 };
 }
-- 
GitLab